From c5dfe3d0b7e1679c8263d3bc0e2c3f8460dede31 Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Thu, 9 Sep 2021 16:52:55 -0400 Subject: [PATCH] Saving Modifications -Safer saving, it waits for the file to stop being used to close(still has holes) -If a chunk is too large, it is moved to the end of the file. -Calculates the efficiency of each region file in confirmHeaderHealth -Fixed import warning --- .../server/comms/ClientManager.java | 1 - .../progressia/test/region/Region.java | 39 ++++++++++++++++++- .../test/region/TestWorldDiskIO.java | 27 ++++++++++++- 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java index 095c403..e031c27 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java @@ -31,7 +31,6 @@ import ru.windcorp.progressia.common.comms.CommsChannel.State; import ru.windcorp.progressia.common.comms.packets.Packet; import ru.windcorp.progressia.common.world.PacketSetGravityModel; import ru.windcorp.progressia.common.world.PacketSetLocalPlayer; -import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.Server; diff --git a/src/main/java/ru/windcorp/progressia/test/region/Region.java b/src/main/java/ru/windcorp/progressia/test/region/Region.java index e26396d..8706ae4 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/Region.java +++ b/src/main/java/ru/windcorp/progressia/test/region/Region.java @@ -30,9 +30,12 @@ import java.io.RandomAccessFile; import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; +import org.apache.logging.log4j.LogManager; + import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.world.DecodingException; @@ -52,10 +55,15 @@ public class Region { private static final int SECTORS_BYTES = Short.BYTES; private static final int SECTOR_SIZE = MAX_CHUNK_SIZE >> (SECTORS_BYTES*8); + public int loadedChunks; + private static final int DEFINITION_SIZE = Integer.BYTES + Short.BYTES; private static final int HEADER_SIZE = DEFINITION_SIZE * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; + private AtomicBoolean isUsing = new AtomicBoolean(false); + private AtomicBoolean isClosed = new AtomicBoolean(false); + private final RandomAccessFile file; private final ChunkMap offsets = ChunkMaps.newHashMap(); @@ -90,6 +98,7 @@ public class Region { public void close() throws IOException { this.file.close(); + isClosed.lazySet(true);; } public int getOffset(Vec3i chunkLoc) { @@ -115,10 +124,21 @@ public class Region { public void putLength(Vec3i pos, int length) { lengths.put(pos, length); } + + public AtomicBoolean isClosed() + { + return isClosed; + } + + public AtomicBoolean isUsing() + { + return isUsing; + } private void confirmHeaderHealth() throws IOException { Set used = new HashSet(); + int maxUsed = 0; final int chunksPerRegion = REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; file.seek(0); @@ -142,6 +162,11 @@ public class Region { offsets.put(pos, offset); lengths.put(pos, sectorLength); + + if (offset+sectorLength > maxUsed) + { + maxUsed = offset + sectorLength; + } for (int sector = 0; sector < sectorLength; sector++) { if (!used.add(offset + sector)) { @@ -149,10 +174,11 @@ public class Region { } } } - + LogManager.getLogger("Region").debug("Efficiency of {}", (double) used.size()/maxUsed); } public void save(DefaultChunkData chunk, Server server) throws IOException { + isUsing.set(true); Vec3i pos = TestWorldDiskIO.getInRegionCoords(chunk.getPosition()); int definitionOffset = DEFINITION_SIZE * (pos.z + REGION_DIAMETER * (pos.y + REGION_DIAMETER * pos.x)); @@ -162,7 +188,16 @@ public class Region { int dataOffset = getOffset(pos); byte[] buffer = saveToBuffer(chunk, server); + if (hasLength(pos) && buffer.length > getLength(pos)*SECTOR_SIZE ) + { + byte emptyBuffer[] = new byte[getLength(pos)*SECTOR_SIZE]; + writeBuffer(emptyBuffer, definitionOffset, dataOffset, pos); + allocateChunk(definitionOffset, pos); + dataOffset = getOffset(pos); + } + writeBuffer(buffer, definitionOffset, dataOffset, pos); + isUsing.set(false); } private byte[] saveToBuffer(DefaultChunkData chunk, Server server) throws IOException { @@ -208,6 +243,7 @@ public class Region { public DefaultChunkData load(Vec3i chunkPos, DefaultWorldData world, Server server) throws IOException, DecodingException { + isUsing.set(true); int dataOffset = 0; int sectorLength = 0; @@ -222,6 +258,7 @@ public class Region { byte[] buffer = readBuffer(dataOffset, sectorLength); DefaultChunkData result = loadFromBuffer(buffer, chunkPos, world, server); + isUsing.set(false); return result; } diff --git a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java index 2bc3f50..f8f247f 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java @@ -18,6 +18,8 @@ package ru.windcorp.progressia.test.region; +import java.util.concurrent.atomic.AtomicBoolean; + import glm.vec._3.i.Vec3i; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -227,8 +229,29 @@ public class TestWorldDiskIO implements WorldContainer { @Override public void close() { try { - for (Region region : regions.values()) { - region.close(); + ChunkMap isCloseds = ChunkMaps.newHashMap(); + ChunkMap isUsings = ChunkMaps.newHashMap(); + + for (Vec3i region : regions.keys()) + { + isCloseds.put(region, regions.get(region).isClosed()); + isUsings.put(region, regions.get(region).isUsing()); + } + + boolean stillOpen = true; + while (stillOpen) + { + stillOpen = false; + for (Vec3i region : regions.keys()) { + if (!isCloseds.get(region).get() && !isUsings.get(region).get()) + { + regions.get(region).close(); + } + else if (isUsings.get(region).get()) + { + stillOpen = false; + } + } } } catch (IOException e) { throw CrashReports.report(e, "Could not close region files");