*Kinda* working now. Async the updateCache to io thread, and fix stream close issue

This commit is contained in:
TomTheFurry
2022-09-08 22:31:24 +08:00
parent 00a18352d8
commit 0e001dd2d3
10 changed files with 44 additions and 52 deletions
@@ -22,12 +22,8 @@ public class ColumnRenderLoader extends RenderSourceLoader {
@Override
public LodRenderSource loadRender(RenderMetaFile dataFile, InputStream data, ILevel level) throws IOException {
try (
//TODO: Add decompressor here
DataInputStream dis = new DataInputStream(data);
) {
return new ColumnRenderSource(dataFile.pos, dis, dataFile.metaData.loaderVersion, level);
}
DataInputStream dis = new DataInputStream(data); // DO NOT CLOSE
return new ColumnRenderSource(dataFile.pos, dis, dataFile.metaData.loaderVersion, level);
}
@Override
@@ -369,9 +369,8 @@ public class ColumnRenderSource implements LodRenderSource, IColumnDatatype {
@Override
public void saveRender(IClientLevel level, RenderMetaFile file, OutputStream dataStream) throws IOException {
try (DataOutputStream dos = new DataOutputStream(dataStream)) {
writeData(dos);
}
DataOutputStream dos = new DataOutputStream(dataStream); // DO NOT CLOSE
writeData(dos);
}
@Override
@@ -16,11 +16,7 @@ public class FullDataLoader extends DataSourceLoader {
@Override
public LodDataSource loadData(DataMetaFile dataFile, InputStream data, ILevel level) throws IOException {
try (
//TODO: Add decompressor here
DataInputStream dis = new DataInputStream(data);
) {
return FullDataSource.loadData(dataFile, dis, level);
}
//TODO: Add decompressor here
return FullDataSource.loadData(dataFile, data, level);
}
}
@@ -10,6 +10,7 @@ import com.seibel.lod.core.a7.save.io.file.DataMetaFile;
import com.seibel.lod.core.a7.datatype.LodDataSource;
import com.seibel.lod.core.a7.util.IdMappingUtil;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.a7.util.UnclosableInputStream;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.objects.DHChunkPos;
import com.seibel.lod.core.util.LodUtil;
@@ -102,7 +103,8 @@ public class FullDataSource extends FullArrayView implements LodDataSource { //
@Override
public void saveData(ILevel level, DataMetaFile file, OutputStream dataStream) throws IOException {
try (DataOutputStream dos = new DataOutputStream(dataStream)) {
DataOutputStream dos = new DataOutputStream(dataStream); // DO NOT CLOSE
{
dos.writeInt(getDataDetail());
dos.writeInt(size);
dos.writeInt(level.getMinY());
@@ -138,7 +140,8 @@ public class FullDataSource extends FullArrayView implements LodDataSource { //
public static FullDataSource loadData(DataMetaFile dataFile, InputStream dataStream, ILevel level) throws IOException {
try (DataInputStream dos = new DataInputStream(dataStream)) {
DataInputStream dos = new DataInputStream(dataStream); // DO NOT CLOSE
{
int dataDetail = dos.readInt();
if(dataDetail != dataFile.metaData.dataLevel)
throw new IOException(LodUtil.formatLog("Data level mismatch: {} != {}", dataDetail, dataFile.metaData.dataLevel));
@@ -175,7 +178,7 @@ public class FullDataSource extends FullArrayView implements LodDataSource { //
// Id mapping
end = dos.readInt();
if (end != 0xFFFFFFFF) throw new IOException("invalid data content end guard");
IdBiomeBlockStateMap mapping = IdBiomeBlockStateMap.deserialize(dos);
IdBiomeBlockStateMap mapping = IdBiomeBlockStateMap.deserialize(new UnclosableInputStream(dos));
end = dos.readInt();
if (end != 0xFFFFFFFF) throw new IOException("invalid id mapping end guard");
return new FullDataSource(dataFile.pos, mapping, data);
@@ -1,5 +1,6 @@
package com.seibel.lod.core.a7.datatype.full;
import com.seibel.lod.core.a7.util.UnclosableInputStream;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper;
@@ -77,28 +78,21 @@ public class IdBiomeBlockStateMap {
return mapper;
}
void serialize(OutputStream os) {
try (DataOutputStream dos = new DataOutputStream(os)) {
dos.writeInt(entries.size());
for (Entry e : entries) {
dos.writeUTF(e.serialize());
}
} catch (IOException e) {
e.printStackTrace();
void serialize(OutputStream os) throws IOException {
DataOutputStream dos = new DataOutputStream(os); // DO NOT CLOSE!
dos.writeInt(entries.size());
for (Entry e : entries) {
dos.writeUTF(e.serialize());
}
}
static IdBiomeBlockStateMap deserialize(InputStream is) {
try (DataInputStream dis = new DataInputStream(is)) {
int size = dis.readInt();
IdBiomeBlockStateMap map = new IdBiomeBlockStateMap();
for (int i = 0; i < size; i++) {
map.entries.add(Entry.deserialize(dis.readUTF()));
}
return map;
} catch (IOException e) {
e.printStackTrace();
return null;
static IdBiomeBlockStateMap deserialize(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is); // DO NOT CLOSE!
int size = dis.readInt();
IdBiomeBlockStateMap map = new IdBiomeBlockStateMap();
for (int i = 0; i < size; i++) {
map.entries.add(Entry.deserialize(dis.readUTF()));
}
return map;
}
@Override
@@ -16,11 +16,6 @@ public class SparseDataLoader extends DataSourceLoader {
@Override
public LodDataSource loadData(DataMetaFile dataFile, InputStream data, ILevel level) throws IOException {
try (
//TODO: Add decompressor here
DataInputStream dis = new DataInputStream(data);
) {
return SparseDataSource.loadData(dataFile, dis, level);
}
return SparseDataSource.loadData(dataFile, data, level);
}
}
@@ -7,6 +7,7 @@ import com.seibel.lod.core.a7.level.ILevel;
import com.seibel.lod.core.a7.pos.DhLodPos;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.a7.save.io.file.DataMetaFile;
import com.seibel.lod.core.a7.util.UnclosableInputStream;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.util.LodUtil;
import org.apache.logging.log4j.Logger;
@@ -205,7 +206,8 @@ public class SparseDataSource implements LodDataSource {
public static SparseDataSource loadData(DataMetaFile dataFile, InputStream dataStream, ILevel level) throws IOException {
LodUtil.assertTrue(dataFile.pos.sectionDetail > SPARSE_UNIT_DETAIL);
LodUtil.assertTrue(dataFile.pos.sectionDetail <= MAX_SECTION_DETAIL);
try (DataInputStream dos = new DataInputStream(dataStream)) {
DataInputStream dos = new DataInputStream(dataStream); // DO NOT CLOSE!
{
int dataDetail = dos.readShort();
if(dataDetail != dataFile.metaData.dataLevel)
throw new IOException(LodUtil.formatLog("Data level mismatch: {} != {}", dataDetail, dataFile.metaData.dataLevel));
@@ -301,10 +301,12 @@ public class DataFileHandler implements IDataSourceProvider {
return source;
}
@Override
public LodDataSource onDataFileRefresh(LodDataSource source, Consumer<LodDataSource> updater) {
updater.accept(source);
if (source instanceof SparseDataSource) return ((SparseDataSource) source).trySelfPromote();
return source;
public CompletableFuture<LodDataSource> onDataFileRefresh(LodDataSource source, Consumer<LodDataSource> updater) {
return CompletableFuture.supplyAsync(() -> {
updater.accept(source);
if (source instanceof SparseDataSource) return ((SparseDataSource) source).trySelfPromote();
return source;
}, fileReaderThread);
}
@Override
@@ -230,16 +230,20 @@ public class DataMetaFile extends MetaFile
// For now, I'll go for the latter option and just hope nothing goes wrong...
if (inCacheWriteAccessAsserter.getAndSet(true) == false) {
try {
inner = handler.onDataFileRefresh((LodDataSource) inner, this::applyWriteQueue);
return handler.onDataFileRefresh((LodDataSource) inner, this::applyWriteQueue);
} catch (Exception e) {
LOGGER.error("Error while applying changes to LodDataSource at {}: ", pos, e);
} finally {
inCacheWriteAccessAsserter.set(false);
}
} else {
// or, return the cached data. FIXME: See above.
return CompletableFuture.completedFuture((LodDataSource) inner);
}
} else {
// or, return the cached data.
return CompletableFuture.completedFuture((LodDataSource) inner);
}
// Finally, return the cached data.
return CompletableFuture.completedFuture((LodDataSource)inner);
}
}
@@ -11,6 +11,7 @@ import javax.annotation.Nullable;
import java.io.File;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -26,7 +27,7 @@ public interface IDataSourceProvider extends AutoCloseable {
CompletableFuture<LodDataSource> onCreateDataFile(DataMetaFile file);
LodDataSource onDataFileLoaded(LodDataSource source, Consumer<LodDataSource> updater);
LodDataSource onDataFileRefresh(LodDataSource source, Consumer<LodDataSource> updater);
CompletableFuture<LodDataSource> onDataFileRefresh(LodDataSource source, Consumer<LodDataSource> updater);
File computeDataFilePath(DhSectionPos pos);
Executor getIOExecutor();