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
This commit is contained in:
opfromthestart 2021-09-09 16:52:55 -04:00
parent 0100c8791d
commit c5dfe3d0b7
3 changed files with 63 additions and 4 deletions

View File

@ -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;

View File

@ -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<Integer> 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<Integer> used = new HashSet<Integer>();
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;
}

View File

@ -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<AtomicBoolean> isCloseds = ChunkMaps.newHashMap();
ChunkMap<AtomicBoolean> 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");