93 lines
2.5 KiB
Java
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);
|
|
}
|
|
}
|