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:
parent
0100c8791d
commit
c5dfe3d0b7
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
@ -116,9 +125,20 @@ public class Region {
|
||||
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);
|
||||
@ -143,16 +163,22 @@ 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)) {
|
||||
throw new IOException("A sector is used twice");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
Reference in New Issue
Block a user