diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java index 968eb6a00..ba2f457ef 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java @@ -389,15 +389,18 @@ public class FullDataFileHandler implements IFullDataSourceProvider // read in the existing data final ArrayList> loadDataFutures = new ArrayList<>(existingFiles.size()); - for (FullDataMetaFile existingFile : existingFiles) + for (int i = 0; i < existingFiles.size(); i++) { - loadDataFutures.add(existingFile.getOrLoadCachedDataSourceAsync() - .exceptionally((ex) -> /*Ignore file read errors*/null) - .thenAccept((existingFullDataSource) -> + FullDataMetaFile existingFile = existingFiles.get(i); + + CompletableFuture loadFileFuture = existingFile.getOrLoadCachedDataSourceAsync() + .handle((existingFullDataSource, ex) -> { - if (existingFullDataSource == null) + if (existingFullDataSource == null || ex != null) { - return; + // Ignore file read errors + //LOGGER.warn(recipientFullDataSource.getSectionPos()+" sample from, file read error for file "+existingFile.pos+": "+ex.getMessage(), ex); + return null; } if (showFullDataFileSampling) @@ -407,12 +410,18 @@ public class FullDataFileHandler implements IFullDataSourceProvider 0.2, 32f)); } - //LOGGER.info("Merging data from {} into {}", data.getSectionPos(), pos); recipientFullDataSource.sampleFrom(existingFullDataSource); - }) - ); + + // hopefully clearing the cached data source immediately after we are done with it will help the garbage collector a bit + existingFile.clearCachedDataSource(); + + return null; // TODO remove the need to un-necessarily return null + }); + + loadDataFutures.add(loadFileFuture); } - return CompletableFuture.allOf(loadDataFutures.toArray(new CompletableFuture[0])).thenApply(voidObj -> recipientFullDataSource); + return CompletableFuture.allOf(loadDataFutures.toArray(new CompletableFuture[0])) + .thenApply(voidObj -> recipientFullDataSource); } protected void makeFiles(ArrayList posList, ArrayList output) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java index aa14da933..785fedce9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java @@ -161,6 +161,20 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I return this.cachedFullDataSourceRef.get(); } + /** @return if any data was cleared */ + public boolean clearCachedDataSource() + { + boolean dataExists = this.cachedFullDataSourceRef.get() != null; + if (dataExists) + { + this.cachedFullDataSourceRef.close(); + this.cachedFullDataSourceRef.clear(); + } + + return dataExists; + } + + public CompletableFuture getOrLoadCachedDataSourceAsync() { @@ -606,6 +620,77 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I return completionFuture; } + /* + + private void applyWriteQueueAndSave(IFullDataSource fullDataSourceToUpdate) + { + boolean dataChanged = this.applyWriteQueueToFullDataSource(fullDataSourceToUpdate); + this.needsUpdate = false; + + // attempt to promote the data source + if (fullDataSourceToUpdate instanceof IIncompleteFullDataSource) + { + IFullDataSource newSource = ((IIncompleteFullDataSource) fullDataSourceToUpdate).tryPromotingToCompleteDataSource(); + dataChanged |= (newSource != fullDataSourceToUpdate); + fullDataSourceToUpdate = newSource; + } + + + // the provider may need to modify other files based on this data source changing + IFullDataSourceProvider.DataFileUpdateResult dataFileUpdateResult = this.fullDataSourceProvider.onDataFileUpdateAsync(fullDataSourceToUpdate, this, dataChanged); + IFullDataSource fullDataSource = dataFileUpdateResult.fullDataSource; + boolean dataSourceChanged = dataFileUpdateResult.dataSourceChanged; + + + // only save to file if something was changed + if (dataSourceChanged) + { + this.writeDataSource(fullDataSource); + } + + // keep track of non-null data sources + if (fullDataSource != null) + { + new DataObjTracker(fullDataSource); + new DataObjSoftTracker(this, fullDataSource); + } + + + boolean showFullDataFileStatus = Config.Client.Advanced.Debugging.DebugWireframe.showFullDataFileStatus.get(); + boolean showFullDataFileSampling = Config.Client.Advanced.Debugging.DebugWireframe.showFullDataFileSampling.get(); + if (showFullDataFileStatus || showFullDataFileSampling) + { + Color color; + if (this.pos.getDetailLevel() == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) + { + color = Color.GREEN; + } + else + { + color = Color.GREEN.darker().darker(); + } + + DebugRenderer.makeParticle(new DebugRenderer.BoxParticle( + new DebugRenderer.Box(this.pos, 64f, 72f, 0.03f, color), + 0.2, 32f)); + } + + + // save the updated data source + this.cachedFullDataSourceRef = new DataSourceReferenceTracker.FullDataSourceSoftRef(this, fullDataSource); + + + if (this.needsUpdate) + { + // another update was requested while this update was being processed + this.getOrLoadCachedDataSourceAsync(); + } + } + + */ + + + /** @return true if the queue was not empty and chunk data was applied to this meta file's {@link IFullDataSource}. */ private boolean applyWriteQueueToFullDataSource(IFullDataSource fullDataSource) {