package it.cavallium.strangedb.database.blocks; import it.cavallium.strangedb.database.DatabaseFileIO; import it.cavallium.strangedb.database.IBlocksIO; import it.cavallium.strangedb.database.IBlocksMetadata; import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import static it.cavallium.strangedb.database.IBlocksMetadata.EMPTY_BLOCK_ID; import static it.cavallium.strangedb.database.IBlocksMetadata.ERROR_BLOCK_ID; public class DatabaseBlocksIO implements IBlocksIO { private final DatabaseFileIO fileIO; private final IBlocksMetadata blocksMetadata; public DatabaseBlocksIO(DatabaseFileIO fileIO, IBlocksMetadata blocksMetadata) { this.fileIO = fileIO; this.blocksMetadata = blocksMetadata; } @Override public long newBlock(int size, ByteBuffer data) throws IOException { if (size == 0) { return EMPTY_BLOCK_ID; } if (size < 0) { throw new IOException("Trying to create a block with size " + size); } if (data.limit() < size) { throw new IOException("Trying to create a block with size " + size + " but with a buffer of size " + data.limit()); } long index = fileIO.writeAtEnd(size, data); return blocksMetadata.newBlock(index, size); } @Override public ByteBuffer readBlock(long blockId) throws IOException { if (blockId == EMPTY_BLOCK_ID) { return ByteBuffer.wrap(new byte[0]); } if (blockId == ERROR_BLOCK_ID) { throw new IOException("Errored block id"); } if (blockId < 0) { throw new IOException("Block id " + blockId + " is not valid"); } BlockInfo blockInfo = blocksMetadata.getBlockInfo(blockId); return fileIO.readAt(blockInfo.getIndex(), blockInfo.getSize()); } public ByteBuffer readBlockSizeAndLastElementOfReferencesList(long blockId) throws IOException { if (blockId == EMPTY_BLOCK_ID) { return ByteBuffer.wrap(new byte[0]); } if (blockId == ERROR_BLOCK_ID) { throw new IOException("Errored block id"); } if (blockId < 0) { throw new IOException("Block id " + blockId + " is not valid"); } BlockInfo blockInfo = blocksMetadata.getBlockInfo(blockId); if (blockInfo.getSize() >= Integer.BYTES * 2 + Long.BYTES) { return fileIO.readAt(blockInfo.getIndex() + blockInfo.getSize() - (Integer.BYTES + Long.BYTES), Integer.BYTES + Long.BYTES); } else { return fileIO.readAt(blockInfo.getIndex(), blockInfo.getSize()); } } @Override public void close() { } }