Load and reload BlueMapSponge off the server-thread

This commit is contained in:
Blue (Lukas Rieger) 2019-11-23 15:20:11 +01:00
parent 0d7657dcd7
commit 3f2d5e7e14
2 changed files with 78 additions and 64 deletions

View File

@ -1,6 +1,5 @@
package de.bluecolored.bluemap.sponge; package de.bluecolored.bluemap.sponge;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
@ -28,7 +27,6 @@
import de.bluecolored.bluemap.core.logger.Logger; import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.render.hires.HiresModelManager; import de.bluecolored.bluemap.core.render.hires.HiresModelManager;
import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException;
import de.bluecolored.bluemap.core.world.Block; import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException; import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException;
import de.bluecolored.bluemap.core.world.World; import de.bluecolored.bluemap.core.world.World;
@ -96,23 +94,26 @@ public CommandSpec createReloadCommand() {
.description(Text.of("Reloads all resources and configuration-files")) .description(Text.of("Reloads all resources and configuration-files"))
.permission("bluemap.reload") .permission("bluemap.reload")
.executor((source, args) -> { .executor((source, args) -> {
try {
source.sendMessage(Text.of(TextColors.GOLD, "Reloading BlueMap...")); source.sendMessage(Text.of(TextColors.GOLD, "Reloading BlueMap..."));
plugin.reload();
if (plugin.isLoaded()) { plugin.getAsyncExecutor().submit(() -> {
source.sendMessage(Text.of(TextColors.GREEN, "BlueMap reloaded!")); try {
return CommandResult.success(); plugin.reload();
} else {
source.sendMessage(Text.of(TextColors.RED, "Could not load BlueMap! See the console for details!")); if (plugin.isLoaded()) {
return CommandResult.empty(); source.sendMessage(Text.of(TextColors.GREEN, "BlueMap reloaded!"));
} } else {
} catch (IOException | NoSuchResourceException ex) { source.sendMessage(Text.of(TextColors.RED, "Could not load BlueMap! See the console for details!"));
Logger.global.logError("Failed to reload BlueMap!", ex); }
source.sendMessage(Text.of(TextColors.RED, "There was an error reloading BlueMap! See the console for details!")); } catch (Exception ex) {
return CommandResult.empty(); Logger.global.logError("Failed to reload BlueMap!", ex);
}
source.sendMessage(Text.of(TextColors.RED, "There was an error reloading BlueMap! See the console for details!"));
}
});
return CommandResult.success();
}) })
.build(); .build();
} }

View File

@ -38,6 +38,7 @@
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
@ -123,13 +124,10 @@ public SpongePlugin(org.slf4j.Logger logger) {
instance = this; instance = this;
} }
public synchronized void load() throws IOException, NoSuchResourceException { public synchronized void load() throws ExecutionException, IOException, NoSuchResourceException, InterruptedException {
if (loaded) return; if (loaded) return;
unload(); //ensure nothing is left running (from a failed load or something) unload(); //ensure nothing is left running (from a failed load or something)
//init commands
Sponge.getCommandManager().register(this, new Commands(this).createRootCommand(), "bluemap");
//load configs //load configs
File configFile = getConfigPath().resolve("bluemap.conf").toFile(); File configFile = getConfigPath().resolve("bluemap.conf").toFile();
config = ConfigurationFile.loadOrCreate(configFile, SpongePlugin.class.getResource("/bluemap-sponge.conf")).getConfig(); config = ConfigurationFile.loadOrCreate(configFile, SpongePlugin.class.getResource("/bluemap-sponge.conf")).getConfig();
@ -143,7 +141,9 @@ public synchronized void load() throws IOException, NoSuchResourceException {
unload(); unload();
//only register reload command //only register reload command
Sponge.getCommandManager().register(this, new Commands(this).createStandaloneReloadCommand(), "bluemap"); syncExecutor.submit(() -> //just to be save we do this on the server thread
Sponge.getCommandManager().register(this, new Commands(this).createStandaloneReloadCommand(), "bluemap")
).get();
return; return;
} }
@ -232,7 +232,9 @@ public synchronized void load() throws IOException, NoSuchResourceException {
} }
//start map updater //start map updater
updateHandler = new MapUpdateHandler(); syncExecutor.submit(() ->
this.updateHandler = new MapUpdateHandler()
).get();
//create/update webfiles //create/update webfiles
WebFilesManager webFilesManager = new WebFilesManager(config.getWebRoot()); WebFilesManager webFilesManager = new WebFilesManager(config.getWebRoot());
@ -257,6 +259,11 @@ public synchronized void load() throws IOException, NoSuchResourceException {
webServer.updateWebfiles(); webServer.updateWebfiles();
webServer.start(); webServer.start();
} }
//init commands
syncExecutor.submit(() -> //just to be save we do this on the server thread
Sponge.getCommandManager().register(this, new Commands(this).createRootCommand(), "bluemap")
).get();
//metrics //metrics
Sponge.getScheduler().createTaskBuilder() Sponge.getScheduler().createTaskBuilder()
@ -272,20 +279,25 @@ public synchronized void load() throws IOException, NoSuchResourceException {
} }
public synchronized void unload() { public synchronized void unload() {
try {
syncExecutor.submit(() -> { //just to be save we do this on the server thread
//unregister commands
Sponge.getCommandManager().getOwnedBy(this).forEach(Sponge.getCommandManager()::removeMapping);
//unregister listeners
if (updateHandler != null) Sponge.getEventManager().unregisterListeners(updateHandler);
//stop scheduled tasks
Sponge.getScheduler().getScheduledTasks(this).forEach(t -> t.cancel());
}).get();
} catch (InterruptedException | ExecutionException unexpected) {
throw new RuntimeException("Unexpected exception!", unexpected); //should never happen
}
//stop services //stop services
if (renderManager != null) renderManager.stop(); if (renderManager != null) renderManager.stop();
if (webServer != null) webServer.close(); if (webServer != null) webServer.close();
//unregister listeners
if (updateHandler != null) Sponge.getEventManager().unregisterListeners(updateHandler);
//unregister commands
Sponge.getCommandManager().getOwnedBy(this).forEach(Sponge.getCommandManager()::removeMapping);
//stop scheduled tasks
Sponge.getScheduler().getScheduledTasks(this).forEach(t -> t.cancel());
//save render-manager state //save render-manager state
if (updateHandler != null) updateHandler.flushTileBuffer(); //first write all buffered tiles to the render manager to save them too if (updateHandler != null) updateHandler.flushTileBuffer(); //first write all buffered tiles to the render manager to save them too
if (renderManager != null) { if (renderManager != null) {
@ -320,7 +332,7 @@ public synchronized void unload() {
loaded = false; loaded = false;
} }
public synchronized void reload() throws IOException, NoSuchResourceException { public synchronized void reload() throws IOException, NoSuchResourceException, ExecutionException, InterruptedException {
unload(); unload();
load(); load();
} }
@ -330,37 +342,42 @@ public void onServerStart(GameStartingServerEvent evt) {
syncExecutor = Sponge.getScheduler().createSyncExecutor(this); syncExecutor = Sponge.getScheduler().createSyncExecutor(this);
asyncExecutor = Sponge.getScheduler().createAsyncExecutor(this); asyncExecutor = Sponge.getScheduler().createAsyncExecutor(this);
try { asyncExecutor.execute(() -> {
load(); try {
if (isLoaded()) Logger.global.logInfo("Loaded!"); load();
} catch (IOException | NoSuchResourceException e) { if (isLoaded()) Logger.global.logInfo("Loaded!");
Logger.global.logError("Failed to load!", e); } catch (Exception e) {
} Logger.global.logError("Failed to load!", e);
}
});
} }
@Listener @Listener
public void onServerStop(GameStoppingEvent evt) { public void onServerStop(GameStoppingEvent evt) {
unload(); asyncExecutor.execute(() -> {
Logger.global.logInfo("Saved and stopped!"); unload();
Logger.global.logInfo("Saved and stopped!");
});
} }
@Listener @Listener
public void onServerReload(GameReloadEvent evt) { public void onServerReload(GameReloadEvent evt) {
try { asyncExecutor.execute(() -> {
reload(); try {
Logger.global.logInfo("Reloaded!"); Logger.global.logInfo("Reloading...");
} catch (IOException | NoSuchResourceException e) { reload();
Logger.global.logError("Failed to load!", e); Logger.global.logInfo("Reloaded!");
} } catch (Exception e) {
Logger.global.logError("Failed to load!", e);
}
});
} }
private void handleMissingResources(File resourceFile, File configFile) { private void handleMissingResources(File resourceFile, File configFile) {
if (config.isDownloadAccepted()) { if (config.isDownloadAccepted()) {
//download file async //download file async
Sponge.getScheduler().createTaskBuilder() asyncExecutor.execute(() -> {
.async()
.execute(() -> {
try { try {
Logger.global.logInfo("Downloading " + ResourcePack.MINECRAFT_CLIENT_URL + " to " + resourceFile + " ..."); Logger.global.logInfo("Downloading " + ResourcePack.MINECRAFT_CLIENT_URL + " to " + resourceFile + " ...");
ResourcePack.downloadDefaultResource(resourceFile); ResourcePack.downloadDefaultResource(resourceFile);
@ -369,20 +386,16 @@ private void handleMissingResources(File resourceFile, File configFile) {
return; return;
} }
//reload bluemap on server thread // and reload
Sponge.getScheduler().createTaskBuilder() Logger.global.logInfo("Download finished! Reloading...");
.execute(() -> { try {
try { reload();
Logger.global.logInfo("Download finished! Reloading..."); } catch (Exception e) {
reload(); Logger.global.logError("Failed to reload Bluemap!", e);
Logger.global.logInfo("Reloaded!"); return;
} catch (IOException | NoSuchResourceException e) { }
Logger.global.logError("Failed to reload BlueMap!", e); Logger.global.logInfo("Reloaded!");
} });
})
.submit(SpongePlugin.getInstance());
})
.submit(SpongePlugin.getInstance());
} else { } else {
Logger.global.logWarning("BlueMap is missing important resources!"); Logger.global.logWarning("BlueMap is missing important resources!");