-Better HashableVec3i compare

-Added RandomFileMapped class
	-Made it a wrapper for RandomAccessFile and contains maps of locations
and lengths
-Added confirmHeaderHealth method to made sure the file isnt corrupted
-Changed everything from MappedByteBuffers to RandomFileMappeds.
This commit is contained in:
opfromthestart 2021-08-25 16:15:38 -04:00
parent 0ccc108ddd
commit 9dcb3a7748
2 changed files with 198 additions and 111 deletions

View File

@ -29,7 +29,7 @@ public class HashableVec3i {
return false; return false;
} }
HashableVec3i compareeCast = (HashableVec3i) comparee; HashableVec3i compareeCast = (HashableVec3i) comparee;
return compareeCast.value == value; return compareeCast.value.x == value.x && compareeCast.value.y == value.y && compareeCast.value.z == value.z ;
} }
} }

View File

@ -31,14 +31,13 @@ import java.io.FileNotFoundException;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner; import java.util.Scanner;
import java.util.Set;
import java.util.zip.DeflaterOutputStream; import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream; import java.util.zip.InflaterInputStream;
@ -55,12 +54,78 @@ import ru.windcorp.progressia.common.world.io.ChunkIO;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
public class TestWorldDiskIO { public class TestWorldDiskIO {
private static final boolean resetCorrupted = true;
public static class RandomFileMapped {
public RandomAccessFile file;
public HashMap<HashableVec3i, Integer> offsets;
public HashMap<HashableVec3i, Integer> lengths;
public RandomFileMapped(RandomAccessFile inFile)
{
boolean check = false;
offsets = new HashMap<>();
lengths = new HashMap<>();
try {
check = confirmHeaderHealth(inFile, offsets, lengths);
} catch (IOException e) {
e.printStackTrace();
}
if (!check)
{
LOG.debug("Uh the file broke");
if (resetCorrupted) {
byte headerBytes[] = new byte[4 * chunksPerRegion];
for (int i = 0; i < 4 * chunksPerRegion; i++) {
headerBytes[i] = (byte) 0;
}
try {
inFile.write(headerBytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
file = inFile;
}
public int getOffset(Vec3i chunkLoc)
{
return offsets.get(new HashableVec3i(chunkLoc));
}
public boolean hasOffset(Vec3i pos) {
return offsets.containsKey(new HashableVec3i(pos));
}
public void putOffset(Vec3i pos, int offset)
{
offsets.put(new HashableVec3i(pos), offset);
}
public int getLength(Vec3i chunkLoc)
{
return lengths.get(new HashableVec3i(chunkLoc));
}
public boolean hasLength(Vec3i pos) {
return lengths.containsKey(new HashableVec3i(pos));
}
public void putLength(Vec3i pos, int length)
{
lengths.put(new HashableVec3i(pos), length);
}
}
private static Path SAVE_DIR = Paths.get("tmp_world"); private static Path SAVE_DIR = Paths.get("tmp_world");
private static final String formatFile = "world.format"; private static final String formatFile = "world.format";
private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO");
private static HashMap<HashableVec3i, MappedByteBuffer> mappedByteMap; private static HashMap<HashableVec3i, RandomFileMapped> inOutMap;
private static final boolean ENABLE = true; private static final boolean ENABLE = true;
private static int maxSize = 1048576; private static int maxSize = 1048576;
@ -71,7 +136,6 @@ public class TestWorldDiskIO {
// private Map<Vec3i,Vec3i> regions = new HashMap<Vec3i,Vec3i>(); // private Map<Vec3i,Vec3i> regions = new HashMap<Vec3i,Vec3i>();
private static Vec3i regionSize; private static Vec3i regionSize;
private static int chunksPerRegion; private static int chunksPerRegion;
private static int offsetBytes;
private static int currentFormat = -1; private static int currentFormat = -1;
private static String extension = ".null"; private static String extension = ".null";
@ -149,18 +213,19 @@ public class TestWorldDiskIO {
// regions.put(new Vec3i(0,0,0), new Vec3i(1,1,1)); // regions.put(new Vec3i(0,0,0), new Vec3i(1,1,1));
} }
public static int getAvailableSector(MappedByteBuffer mbb) /*public static int getAvailableSector(MappedByteBuffer mbb)
{ {
int sectorsUsed = 0; int sectorsUsed = 0;
for (int i=offsetBytes; i<(offsetBytes+1)*chunksPerRegion; i+= (offsetBytes+1)) for (int i=offsetBytes; i<(offsetBytes+1)*chunksPerRegion; i+= (offsetBytes+1))
{ {
sectorsUsed += mbb.get(i); sectorsUsed += mbb.get(i);
} }
return sectorsUsed; return sectorsUsed;
} }*/
private static void setRegionSize(int format) { private static void setRegionSize(int format) {
mappedByteMap = new HashMap<HashableVec3i, MappedByteBuffer>(); inOutMap = new HashMap<HashableVec3i, RandomFileMapped>();
switch (format) { switch (format) {
case 0: case 0:
case 1: case 1:
@ -173,15 +238,49 @@ public class TestWorldDiskIO {
regionSize = new Vec3i(16); regionSize = new Vec3i(16);
chunksPerRegion = 16 * 16 * 16; chunksPerRegion = 16 * 16 * 16;
currentFormat = 65536; currentFormat = 65536;
offsetBytes = 3;
extension = ".progressia_region"; extension = ".progressia_region";
break; break;
} }
} }
/*private static void expand(int sectors) { public static boolean confirmHeaderHealth(RandomAccessFile input, HashMap<HashableVec3i, Integer> offsets, HashMap<HashableVec3i, Integer> length) throws IOException
{
}*/ Set<Integer> used = new HashSet<Integer>();
input.seek(0);
if (input.length() < 4*chunksPerRegion)
{
return false;
}
for (int i=0;i<4*chunksPerRegion;i+=4)
{
int offset = 0;
for (int ii = 0; ii < 3; ii++) {
offset *= 256;
offset += input.read();
}
int sectorLength = input.read();
if (sectorLength==0)
{
continue;
}
int headerPos = i/4;
int x = headerPos/regionSize.y/regionSize.z;
int y = (headerPos/regionSize.z)%regionSize.y;
int z = headerPos%regionSize.z;
HashableVec3i key = new HashableVec3i(new Vec3i(x,y,z));
offsets.put(key , offset);
length.put(key, sectorLength);
for (int ii=0;ii<sectorLength;ii++)
{
if (used.contains(offset+ii))
{
return false;
}
used.add(offset+ii);
}
}
return true;
}
public static void saveChunk(DefaultChunkData chunk, Server server) { public static void saveChunk(DefaultChunkData chunk, Server server) {
if (!ENABLE) if (!ENABLE)
@ -266,105 +365,68 @@ public class TestWorldDiskIO {
) )
); );
/*
* if (!dosave)
* {
* return;
* }
* dosave = false;
*/
MappedByteBuffer output = mappedByteMap.get(new HashableVec3i(saveCoords)); RandomFileMapped outputMap = inOutMap.get(new HashableVec3i(saveCoords));
LOG.info("saveCoords {},{},{}", saveCoords.x, saveCoords.y, saveCoords.z); //LOG.info("saveCoords {},{},{}", saveCoords.x, saveCoords.y, saveCoords.z);
if (output == null) if (outputMap == null)
{ {
output = makeNew(path, new HashableVec3i(saveCoords)); outputMap = makeNew(path, new HashableVec3i(saveCoords));
} }
// LOG.debug(output.read()); RandomAccessFile output = outputMap.file;
if (output.get() < 0) {
LOG.info("Making header");
ByteBuffer headerBytes = ByteBuffer.allocate((offsetBytes + 1) * chunksPerRegion);
for (int i=0;i<(offsetBytes + 1) * chunksPerRegion;i++)
{
headerBytes.put(i, (byte) 0);
}
output.put(headerBytes);
}
Vec3i pos = getRegionLoc(chunk.getPosition()); Vec3i pos = getRegionLoc(chunk.getPosition());
int shortOffset = (offsetBytes + 1) * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); int shortOffset = 4 * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x));
int fullOffset = (offsetBytes + 1) * (chunksPerRegion); int fullOffset = 4 * (chunksPerRegion);
output.position(shortOffset);
int offset = 0; int offset = 0;
for (int i = 0; i < offsetBytes; i++) {
offset *= 256; if (outputMap.hasOffset(pos))
offset += output.get(); {
offset = outputMap.getOffset(pos);
} }
ByteBuffer readOffset = ByteBuffer.allocate(offsetBytes); else {
int sectorLength = output.get(); output.seek(shortOffset);
if (sectorLength == 0) { for (int i = 0; i < 3; i++) {
//int outputLen = (int) output.size(); offset *= 256;
//offset = (int) (outputLen - fullOffset) / sectorSize + 1; offset += output.read();
offset = getAvailableSector(output);
output.position(shortOffset);
//readInt.putInt(offset<<8);
for (int i=0;i<offsetBytes;i++)
{
readOffset.put(offsetBytes-i-1, (byte) (offset<<8));
} }
output.put(readOffset); int sectorLength = output.read();
/*output.position(outputLen); if (sectorLength == 0) {
int outputLen = (int) output.length();
while (output.size()<fullOffset+sectorSize*offset) offset = (int) (outputLen - fullOffset) / sectorSize + 1;
{ int tempOffset = offset;
output.write(ByteBuffer.wrap( new byte[]{0} )); output.seek(shortOffset);
}*/
byte readOffset[] = new byte[3];
//output.setLength(fullOffset + offset * sectorSize); for (int i = 0; i < 3; i++) {
// output.write(200); readOffset[2 - i] = (byte) (tempOffset % 256);
tempOffset >>= 8;
}
output.write(readOffset);
output.setLength(fullOffset + offset * sectorSize);
}
outputMap.putOffset(pos, offset);
} }
// int bytestoWrite = output.readInt();
// output.mark(sectorSize*sectorLength);
// BufferedOutputStream counter = new
// BufferedOutputStream(Files.newOutputStream(
// SAVE_DIR.resolve(tempFile)));
ByteArrayOutputStream tempDataStream = new ByteArrayOutputStream(); ByteArrayOutputStream tempDataStream = new ByteArrayOutputStream();
DataOutputStream trueOutput = new DataOutputStream( DataOutputStream trueOutput = new DataOutputStream(
new DeflaterOutputStream( new DeflaterOutputStream(
new BufferedOutputStream(tempDataStream) new BufferedOutputStream(tempDataStream)
) )
); );
// CountingOutputStream countOutput = new
// CountingOutputStream(trueOutput);
// LOG.info("Before: {}",output.);
// trueOutput.writeBytes("uh try this");
// counter.
ChunkIO.save(chunk, trueOutput, IOContext.SAVE); ChunkIO.save(chunk, trueOutput, IOContext.SAVE);
writeGenerationHint(chunk, trueOutput, server); writeGenerationHint(chunk, trueOutput, server);
/*
* while (counter.getCount()%sectorSize != 0) {
* counter.write(0);
* }
*/
// LOG.info("Wrote {} bytes to
// {},{},{}",trueOutput.size(),chunk.getPosition().x,chunk.getPosition().y,chunk.getPosition().z);
trueOutput.close(); trueOutput.close();
byte tempData[] = tempDataStream.toByteArray(); byte tempData[] = tempDataStream.toByteArray();
output.position( fullOffset + sectorSize * offset); output.seek( fullOffset + sectorSize * offset);
output.put(ByteBuffer.wrap( tempData)); output.write(tempData);
output.position(shortOffset + offsetBytes); output.seek(shortOffset + 3);
output.put(ByteBuffer.wrap( new byte[] {(byte) (tempData.length / sectorSize + 1)})); output.write(tempData.length / sectorSize + 1);
outputMap.putLength(pos, tempData.length / sectorSize + 1);
// LOG.info("Used {} sectors",(int) // LOG.info("Used {} sectors",(int)
// tempData.length/sectorSize + 1); // tempData.length/sectorSize + 1);
@ -375,15 +437,16 @@ public class TestWorldDiskIO {
} }
} }
private static MappedByteBuffer makeNew(Path path, Object hashObj) { private static RandomFileMapped makeNew(Path path, Object hashObj) {
try try
{ {
RandomAccessFile raf = new RandomAccessFile(path.toFile(), "rw"); RandomAccessFile raf = new RandomAccessFile(path.toFile(), "rw");
FileChannel fc = raf.getChannel(); //FileChannel fc = raf.getChannel();
MappedByteBuffer output = fc.map(FileChannel.MapMode.READ_WRITE, 0, maxSize*chunksPerRegion); //MappedByteBuffer output = fc.map(FileChannel.MapMode.READ_WRITE, 0, maxSize*chunksPerRegion);
output.limit(maxSize*chunksPerRegion); //output.limit(maxSize*chunksPerRegion);
mappedByteMap.put((HashableVec3i) hashObj, output); RandomFileMapped rfm = new RandomFileMapped(raf);
return output; inOutMap.put((HashableVec3i) hashObj, rfm);
return rfm;
} }
catch (IOException e) catch (IOException e)
{ {
@ -611,37 +674,61 @@ public class TestWorldDiskIO {
private static DefaultChunkData loadRegion(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) private static DefaultChunkData loadRegion(Path path, Vec3i chunkPos, DefaultWorldData world, Server server)
throws IOException, throws IOException,
DecodingException { DecodingException {
int offset = 0;
int sectorLength = 0;
Vec3i pos;
RandomFileMapped inputMap;
int fullOffset = 4 * (chunksPerRegion);
try try
{ {
Vec3i streamCoords = getRegion(chunkPos); Vec3i streamCoords = getRegion(chunkPos);
MappedByteBuffer input = mappedByteMap.get(new HashableVec3i(streamCoords)); inputMap = inOutMap.get(new HashableVec3i(streamCoords));
LOG.info("streamCoords {},{},{}", streamCoords.x,streamCoords.y,streamCoords.z); //LOG.info("streamCoords {},{},{}", streamCoords.x,streamCoords.y,streamCoords.z);
if (input == null) if (inputMap == null)
{ {
//input = new RandomAccessFile(path.toFile(), "rw"); //input = new RandomAccessFile(path.toFile(), "rw");
//input = Files.newByteChannel(path); //input = Files.newByteChannel(path);
input = makeNew(path, new HashableVec3i(streamCoords)); inputMap = makeNew(path, new HashableVec3i(streamCoords));
} }
RandomAccessFile input = inputMap.file;
pos = getRegionLoc(chunkPos);
if (inputMap.hasOffset(pos))
{
offset = inputMap.getOffset(pos);
sectorLength = inputMap.getLength(pos);
//LOG.info("{},{}", offset, sectorLength);
}
else
{
// LOG.info(path.toString()); // LOG.info(path.toString());
Vec3i pos = getRegionLoc(chunkPos);
int shortOffset = (offsetBytes + 1) * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); int shortOffset = 4 * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x));
int fullOffset = (offsetBytes + 1) * (chunksPerRegion);
input.position(shortOffset); input.seek(shortOffset);
int offset = 0; for (int i = 0; i < 3; i++) {
for (int i = 0; i < offsetBytes; i++) {
offset *= 256; offset *= 256;
offset += input.get(); offset += input.read();
} }
int sectorLength = input.get(); sectorLength = input.read();
input.position(fullOffset + sectorSize * offset); if (sectorLength == 0)
{
return null;
}
inputMap.putOffset(pos, offset);
inputMap.putLength(pos, sectorLength);
}
input.seek(fullOffset + sectorSize * offset);
// LOG.info("Read {} sectors", sectorLength); // LOG.info("Read {} sectors", sectorLength);
byte tempData[] = new byte[sectorSize * sectorLength]; byte tempData[] = new byte[sectorSize * sectorLength];
input.get(tempData); input.read(tempData);
DataInputStream trueInput = new DataInputStream( DataInputStream trueInput = new DataInputStream(
new InflaterInputStream(new BufferedInputStream(new ByteArrayInputStream(tempData))) new InflaterInputStream(new BufferedInputStream(new ByteArrayInputStream(tempData)))
@ -652,7 +739,7 @@ public class TestWorldDiskIO {
} }
catch (EOFException e) catch (EOFException e)
{ {
LOG.warn("Reached end of file"); LOG.warn("Reached end of file, offset was {}, sectors was {}", offset, sectorLength);
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;