Merge remote-tracking branch 'origin/main'

This commit is contained in:
coolGi
2023-07-17 02:14:43 +09:30
6 changed files with 51 additions and 48 deletions
@@ -47,10 +47,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
@Override
public CompletableFuture<IFullDataSource> read(DhSectionPos pos)
{
return super.read(pos).whenComplete((fullDataSource, ex) ->
{
//this.checkIfSectionNeedsAdditionalGeneration(pos, fullDataSource);
});
return super.read(pos);
}
@@ -139,7 +139,9 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
{
return CompletableFuture.completedFuture(null); // No need to save if the file doesn't exist.
}
CompletableFuture<ColumnRenderSource> source = getCachedDataSourceAsync(true);
// FIXME: TODO: Change doTriggerUpdate to true. Currently is false cause a dead future making render handler hang,
// and that render cache aren't actually used really yet due to missing versioning atm. So disabling for now.
CompletableFuture<ColumnRenderSource> source = getCachedDataSourceAsync(false);
if (source == null)
{
return CompletableFuture.completedFuture(null); // If there is no cached data, there is no need to save.
@@ -187,6 +189,9 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
this.fileHandler.onReadRenderSourceLoadedFromCacheAsync(this, cachedRenderDataSource)
// wait for the handler to finish before returning the renderSource
.handle((voidObj, ex) -> {
if (ex != null) {
LOGGER.error("Error while updating render source from cache", ex);
}
newFuture.complete(cachedRenderDataSource);
renderSourceLoadFutureRef.set(null);
return null;
@@ -218,7 +223,7 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
this.baseMetaData = this.makeMetaData(renderSource);
return renderSource;
})
.thenApply((renderSource) -> this.fileHandler.onRenderFileLoaded(renderSource, this))
.thenCompose((renderSource) -> this.fileHandler.onRenderFileLoaded(renderSource, this))
.whenComplete((renderSource, ex) ->
{
if (ex != null)
@@ -239,13 +244,13 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
}
else
{
CompletableFuture.supplyAsync(() ->
CompletableFuture.supplyAsync(() ->
{
if (this.baseMetaData == null)
{
throw new IllegalStateException("Meta data not loaded!");
}
// Load the file.
ColumnRenderSource renderSource;
try (FileInputStream fileInputStream = this.getFileInputStream();
@@ -257,10 +262,10 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
{
throw new CompletionException(ex);
}
renderSource = this.fileHandler.onRenderFileLoaded(renderSource, this);
return renderSource;
}, fileReaderThreads)
// TODO: Check for file version and only update if needed.
.thenCompose((renderSource) -> this.fileHandler.onRenderFileLoaded(renderSource, this))
.whenComplete((renderSource, ex) ->
{
if (ex != null)
@@ -14,6 +14,7 @@ import com.seibel.distanthorizons.core.level.IDhClientLevel;
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
import com.seibel.distanthorizons.core.util.FileScanUtil;
import com.seibel.distanthorizons.core.util.FileUtil;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.ThreadUtil;
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
import com.seibel.distanthorizons.core.config.Config;
@@ -378,9 +379,9 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
DebugRenderer.BoxWithLife box = new DebugRenderer.BoxWithLife(new DebugRenderer.Box(renderSource.sectionPos, 74f, 86f, 0.1f, Color.red), 1.0, 32f, Color.green.darker());
// get the full data source loading future
CompletableFuture<IFullDataSource> fullDataSourceFuture = this.fullDataSourceProvider.read(renderSource.getSectionPos());
fullDataSourceFuture = fullDataSourceFuture.thenApply((fullDataSource) ->
{
CompletableFuture<IFullDataSource> fullDataSourceFuture =
this.fullDataSourceProvider.read(renderSource.getSectionPos())
.thenApply((fullDataSource) -> {
// the fullDataSource can be null if the thread this was running on was interrupted
box.box.color = Color.yellow.darker();
return fullDataSource;
@@ -400,40 +401,30 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
{
if (ex == null)
{
this.writeRenderSourceToFile(renderSource, file, newRenderSource);
try {
this.writeRenderSourceToFile(renderSource, file, newRenderSource);
} catch (Throwable e) {
LOGGER.error("Exception when writing render data to file: ", e);
}
}
else
else if (!LodUtil.isInterruptOrReject(ex))
{
if (ex instanceof InterruptedException)
{
// expected if the transformer is shut down, the exception can be ignored
// LOGGER.warn("RenderSource file transforming interrupted.");
int ignoreEmptyWarning = 0; // explicitly handling these exceptions is important so we know where they are going and if there is an issue we can easily re-enable the logging
}
else if (ex instanceof RejectedExecutionException || ex.getCause() instanceof RejectedExecutionException)
{
// expected if the transformer was already shut down, the exception can be ignored
// LOGGER.warn("RenderSource file transforming interrupted.");
int ignoreEmptyWarning = 0;
}
else if (!UncheckedInterruptedException.isInterrupt(ex))
{
LOGGER.error("Exception when updating render file using data source: ", ex);
}
LOGGER.error("Exception when updating render file using data source: ", ex);
}
box.close();
transformationCompleteFuture.complete(null);
});
return transformationCompleteFuture;
}
/** TODO at some point this method may need to be made "async" like {@link RenderSourceFileHandler#onReadRenderSourceLoadedFromCacheAsync} since the insides are async */
public ColumnRenderSource onRenderFileLoaded(ColumnRenderSource renderSource, RenderMetaDataFile file)
public CompletableFuture<ColumnRenderSource> onRenderFileLoaded(ColumnRenderSource renderSource, RenderMetaDataFile file)
{
this.updateCacheAsync(renderSource, file).join();
return renderSource;
return this.updateCacheAsync(renderSource, file).handle((voidObj, ex) -> {
if (ex != null && !LodUtil.isInterruptOrReject(ex)) {
LOGGER.error("Exception when updating render file using data source: ", ex);
}
return renderSource;
});
}
public CompletableFuture<Void> onReadRenderSourceLoadedFromCacheAsync(RenderMetaDataFile file, ColumnRenderSource data) {
@@ -508,17 +499,18 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
// if the save futures didn't already complete, wait for them and then shut down the thread pool
CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
combinedFuture.thenRun(() ->
combinedFuture.handle((result, ex) -> {
if (ex != null && !LodUtil.isInterruptOrReject(ex)) {
LOGGER.error("Exception when waiting for render source files to save", ex);
}
return null;
}).thenRun(() ->
{
LOGGER.info("Finished closing "+this.getClass().getSimpleName()+", ["+futures.size()+"] files were saved out of ["+this.filesBySectionPos.size()+"] total files.");
this.fileHandlerThreadPool.shutdown();
});
}
// if the save futures were already completed, the above "thenRun" won't fire,
// if the executor isn't currently running anything, shut it down
if (!this.fileHandlerThreadPool.isTerminated() && this.fileHandlerThreadPool.getActiveCount() == 0)
{
else {
LOGGER.info("Finished closing " + this.getClass().getSimpleName() + " when files were already saved.");
this.fileHandlerThreadPool.shutdown();
}
@@ -138,7 +138,15 @@ public class BatchGenerator implements IDhApiWorldGenerator
// the consumer needs to be wrapped like this because the API can't use DH core objects (and IChunkWrapper can't be easily put into the API project)
Consumer<IChunkWrapper> consumerWrapper = (chunkWrapper) -> resultConsumer.accept(new Object[]{ chunkWrapper });
return this.generationEnvironment.generateChunks(chunkPosMinX, chunkPosMinZ, genChunkSize, targetStep, worldGeneratorThreadPool, consumerWrapper);
try {
return this.generationEnvironment.generateChunks(chunkPosMinX, chunkPosMinZ, genChunkSize, targetStep, worldGeneratorThreadPool, consumerWrapper);
}
catch (Exception e) {
if (!LodUtil.isInterruptOrReject(e)) LOGGER.error("Error starting future for chunk generation", e);
CompletableFuture<Void> future = new CompletableFuture<>();
future.completeExceptionally(e);
return future;
}
}
@Override
@@ -426,8 +426,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
if (exception != null)
{
// don't log the shutdown exceptions
if (!UncheckedInterruptedException.isInterrupt(exception)
&& !(exception instanceof CancellationException || exception.getCause() instanceof CancellationException))
if (!LodUtil.isInterruptOrReject(exception))
{
LOGGER.error("Error generating data for section "+taskPos, exception);
}
@@ -20,6 +20,7 @@
package com.seibel.distanthorizons.core.util;
import java.util.Iterator;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletionException;
import java.util.concurrent.RejectedExecutionException;
@@ -308,7 +309,8 @@ public class LodUtil
public static boolean isInterruptOrReject(Throwable t) {
Throwable unwrapped = LodUtil.ensureUnwrap(t);
return UncheckedInterruptedException.isInterrupt(unwrapped) ||
unwrapped instanceof RejectedExecutionException;
unwrapped instanceof RejectedExecutionException ||
unwrapped instanceof CancellationException;
}
}