strangedb/src/main/java/org/warp/jcwdb/FileAllocator.java
2018-11-19 15:16:12 +01:00

93 lines
2.5 KiB
Java

package org.warp.jcwdb;
import com.esotericsoftware.kryo.io.Output;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.channels.Channels;
import java.nio.channels.SeekableByteChannel;
import java.util.*;
public class FileAllocator {
/**
* Edit this using editIndex()
*/
private final Map<Long, IndexDetails> indicesOffset;
/**
* Edit this using editIndex()
*/
private final Set<Long> dirtyIndices;
private final SeekableByteChannel fileChannel;
public FileAllocator(SeekableByteChannel fileChannel) {
indicesOffset = new HashMap<>();
dirtyIndices = new HashSet<>();
this.fileChannel = fileChannel;
}
public void write(final long index, final int type, final DBWriter w) throws IOException {
IndexDetails indexDetails = indicesOffset.getOrDefault(index, null);
if (indexDetails == null) {
allocateAndWrite(index, type, w);
} else {
write(index, indexDetails, w);
}
}
private ByteArrayOutputStream getBytes(DBWriter w) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
w.write(new Output(baos));
return baos;
}
private void write(final long index, final IndexDetails indexDetails, DBWriter w) throws IOException {
final int size = indexDetails.getSize();
final long offset = indexDetails.getOffset();
final int type = indexDetails.getType();
final ByteArrayOutputStream baos = getBytes(w);
long newOffset;
int newSize = baos.size();
if (newSize > size) {
newOffset = allocate(newSize);
} else {
newOffset = offset;
}
if (size != newSize) {
editIndex(index, newOffset, newSize, type);
}
final Output o = new Output(Channels.newOutputStream(fileChannel.position(newOffset)));
o.write(baos.toByteArray());
o.close();
}
private void allocateAndWrite(final long index, final int type, DBWriter w) throws IOException {
final ByteArrayOutputStream baos = getBytes(w);
final int size = baos.size();
final long offset = allocate(size);
editIndex(index, offset, size, type);
final Output o = new Output(Channels.newOutputStream(fileChannel.position(offset)));
o.write(baos.toByteArray());
o.close();
}
/**
* Get an offset
* @param size
* @return new offset
*/
private long allocate(int size) {
return 0; // TODO: fare
}
private void editIndex(long index, long offset, int size, int type) {
editIndex(index, new IndexDetails(offset, size, type));
}
private void editIndex(long index, IndexDetails details) {
indicesOffset.put(index, details);
dirtyIndices.add(index);
}
}