diff --git a/core/src/main/java/com/seibel/lod/core/file/fullDatafile/GeneratedFullDataFileHandler.java b/core/src/main/java/com/seibel/lod/core/file/fullDatafile/GeneratedFullDataFileHandler.java index 8017dc8b3..196fcff61 100644 --- a/core/src/main/java/com/seibel/lod/core/file/fullDatafile/GeneratedFullDataFileHandler.java +++ b/core/src/main/java/com/seibel/lod/core/file/fullDatafile/GeneratedFullDataFileHandler.java @@ -16,6 +16,7 @@ import org.apache.logging.log4j.Logger; import java.io.File; import java.lang.ref.WeakReference; import java.util.*; +import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; @@ -121,7 +122,11 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler { if (exception != null) { - LOGGER.error("Uncaught Gen Task Exception at {}:", pos, exception); + // don't log the shutdown exceptions + if (!(exception instanceof CancellationException || exception.getCause() instanceof CancellationException)) + { + LOGGER.error("Uncaught Gen Task Exception at " + pos + ":", exception); + } } if (exception == null && genTaskCompleted) diff --git a/core/src/main/java/com/seibel/lod/core/generation/BatchGenerator.java b/core/src/main/java/com/seibel/lod/core/generation/BatchGenerator.java index b5405f740..7f4b861e1 100644 --- a/core/src/main/java/com/seibel/lod/core/generation/BatchGenerator.java +++ b/core/src/main/java/com/seibel/lod/core/generation/BatchGenerator.java @@ -149,7 +149,7 @@ public class BatchGenerator implements IDhApiWorldGenerator public void close() { this.stop(true); } public void stop(boolean blocking) { - LOGGER.info("Batch Chunk Generator shutting down..."); + LOGGER.info(BatchGenerator.class.getSimpleName()+" shutting down..."); this.generationGroup.stop(blocking); } diff --git a/core/src/main/java/com/seibel/lod/core/generation/WorldGenerationQueue.java b/core/src/main/java/com/seibel/lod/core/generation/WorldGenerationQueue.java index 1e4adf7ce..5809ea096 100644 --- a/core/src/main/java/com/seibel/lod/core/generation/WorldGenerationQueue.java +++ b/core/src/main/java/com/seibel/lod/core/generation/WorldGenerationQueue.java @@ -557,20 +557,22 @@ public class WorldGenerationQueue implements Closeable DhChunkPos chunkPosMin = new DhChunkPos(pos.getCornerBlockPos()); LOGGER.info("Generating section {} with granularity {} at {}", pos, granularity, chunkPosMin); task.genFuture = startGenerationEvent(this.generator, chunkPosMin, granularity, dataDetail, task.group::accept); - task.genFuture.whenComplete((voidObj, ex) -> + task.genFuture.whenComplete((voidObj, exception) -> { - if (ex != null) + if (exception != null) { - if (!UncheckedInterruptedException.isThrowableInterruption(ex)) + // don't log the shutdown exceptions + if (!UncheckedInterruptedException.isThrowableInterruption(exception) && !(exception instanceof CancellationException || exception.getCause() instanceof CancellationException)) { - LOGGER.error("Error generating data for section [{}]", pos, ex); + LOGGER.error("Error generating data for section "+pos, exception); } - task.group.generatorTasks.forEach(m -> m.future.complete(false)); + + task.group.generatorTasks.forEach(worldGenTask -> worldGenTask.future.complete(false)); } else { - LOGGER.info("Section generation at [{}] completed", pos); - task.group.generatorTasks.forEach(m -> m.future.complete(true)); + LOGGER.info("Section generation at "+pos+" completed"); + task.group.generatorTasks.forEach(worldGenTask -> worldGenTask.future.complete(true)); } boolean worked = this.inProgressGenTasksByLodPos.remove(pos, task); LodUtil.assertTrue(worked); @@ -585,40 +587,53 @@ public class WorldGenerationQueue implements Closeable public CompletableFuture startClosing(boolean cancelCurrentGeneration, boolean alsoInterruptRunning) { - this.waitingTaskGroupsByLodPos.values().forEach(g -> g.generatorTasks.forEach(t -> t.future.complete(false))); + this.waitingTaskGroupsByLodPos.values().forEach(worldGenTaskGroup -> worldGenTaskGroup.generatorTasks.forEach( + (worldGenTask) -> + { + try { worldGenTask.future.cancel(true); } catch (CancellationException ignored) { /* don't log shutdown exceptions */ } + } + )); + this.waitingTaskGroupsByLodPos.clear(); - ArrayList> array = new ArrayList<>(this.inProgressGenTasksByLodPos.size()); + + ArrayList> inProgressTasksCancelingFutures = new ArrayList<>(this.inProgressGenTasksByLodPos.size()); this.inProgressGenTasksByLodPos.values().forEach(runningTaskGroup -> - { - CompletableFuture genFuture = runningTaskGroup.genFuture; // Do this to prevent it getting swapped out - - if (cancelCurrentGeneration) - { - genFuture.cancel(alsoInterruptRunning); - } - - array.add(genFuture.handle((voidObj, ex) -> - { - if (ex instanceof CompletionException) - { - ex = ex.getCause(); - } - if (!UncheckedInterruptedException.isThrowableInterruption(ex)) - { - LOGGER.error("Error when terminating data generation for section {}", runningTaskGroup.group.pos, ex); - } - return null; - })); - }); - this.generatorClosingFuture = CompletableFuture.allOf(array.toArray(new CompletableFuture[0])); //FIXME: Closer threading issues with runCurrentGenTasksUntilBusy - this.looseWoldGenTasks.forEach(t -> t.future.complete(false)); + { + CompletableFuture genFuture = runningTaskGroup.genFuture; // Do this to prevent it getting swapped out + + if (cancelCurrentGeneration) + { + genFuture.cancel(alsoInterruptRunning); + } + + inProgressTasksCancelingFutures.add(genFuture.handle((voidObj, exception) -> + { + if (exception instanceof CompletionException) + { + exception = exception.getCause(); + } + + if (!UncheckedInterruptedException.isThrowableInterruption(exception) && !(exception instanceof CancellationException)) + { + LOGGER.error("Error when terminating data generation for section "+runningTaskGroup.group.pos, exception); + } + + return null; + })); + }); + this.generatorClosingFuture = CompletableFuture.allOf(inProgressTasksCancelingFutures.toArray(new CompletableFuture[0])); //FIXME: Closer threading issues with runCurrentGenTasksUntilBusy + + this.looseWoldGenTasks.forEach(worldGenTask -> worldGenTask.future.cancel(true)); //.complete(false)); this.looseWoldGenTasks.clear(); + return this.generatorClosingFuture; } @Override public void close() { + LOGGER.info("Closing "+WorldGenerationQueue.class.getSimpleName()+"..."); + if (this.generatorClosingFuture == null) { this.startClosing(true, true); @@ -633,6 +648,8 @@ public class WorldGenerationQueue implements Closeable { LOGGER.error("Failed to close generation queue: ", e); } + + LOGGER.info("Successfully closed "+WorldGenerationQueue.class.getSimpleName()); }