package org.warp.cowdb.database; import org.warp.cowdb.BlockInfo; import org.warp.cowdb.IBlocksMetadata; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SeekableByteChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; public class DatabaseBlocksMetadata implements IBlocksMetadata { private final SeekableByteChannel metaFileChannel; private final int BLOCK_META_BYTES_COUNT = Long.BYTES + Integer.BYTES; private long firstFreeBlock; public DatabaseBlocksMetadata(Path metaFile) throws IOException { metaFileChannel = Files.newByteChannel(metaFile, StandardOpenOption.READ, StandardOpenOption.WRITE); firstFreeBlock = metaFileChannel.size() / BLOCK_META_BYTES_COUNT; } @Override public BlockInfo getBlockInfo(long blockId) throws IOException { if (blockId == EMPTY_BLOCK_ID) { return EMPTY_BLOCK_INFO; } ByteBuffer buffer = ByteBuffer.allocate(BLOCK_META_BYTES_COUNT); metaFileChannel.position(blockId * BLOCK_META_BYTES_COUNT).read(buffer); buffer.flip(); long index = buffer.getLong(); int size = buffer.getInt(); return new BlockInfo(index, size); } @Override public long newBlock(long index, int size) throws IOException { long newBlockId = firstFreeBlock++; ByteBuffer data = ByteBuffer.allocate(BLOCK_META_BYTES_COUNT); data.putLong(index); data.putInt(size); data.flip(); metaFileChannel.position(newBlockId * BLOCK_META_BYTES_COUNT).write(data); return newBlockId; } @Override public void close() throws IOException { metaFileChannel.close(); } }