package org.warp.cowdb.database; import org.warp.cowdb.IReferencesMetadata; import org.warp.jcwdb.ann.DBClass; 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; import static org.warp.cowdb.IBlocksMetadata.EMPTY_BLOCK_ID; public class DatabaseReferencesMetadata implements IReferencesMetadata { private final SeekableByteChannel metaFileChannel; private final int REF_META_BYTES_COUNT = Long.BYTES; private long firstFreeReference; public DatabaseReferencesMetadata(Path refMetaFile) throws IOException { metaFileChannel = Files.newByteChannel(refMetaFile, StandardOpenOption.READ, StandardOpenOption.WRITE); firstFreeReference = metaFileChannel.size() / REF_META_BYTES_COUNT; } @Override public long getReference(long reference) throws IOException { ByteBuffer buffer = ByteBuffer.allocate(REF_META_BYTES_COUNT); if (reference >= firstFreeReference) { return EMPTY_BLOCK_ID; } SeekableByteChannel currentFileChannel = metaFileChannel.position(reference * REF_META_BYTES_COUNT); currentFileChannel.read(buffer); buffer.flip(); long block = buffer.getLong(); if (buffer.limit() == 0 || block == 0xFFFFFFFFFFFFFFFFL) { return EMPTY_BLOCK_ID; } return block; } @Override public long newReference(long blockId) throws IOException { long newReference = firstFreeReference++; editReference(newReference, blockId); return newReference; } @Override public void editReference(long reference, long blockId) throws IOException { ByteBuffer data = ByteBuffer.allocate(REF_META_BYTES_COUNT); data.putLong(blockId); SeekableByteChannel currentFileChannel = metaFileChannel.position(reference * REF_META_BYTES_COUNT); data.flip(); currentFileChannel.write(data); } @Override public void close() throws IOException { metaFileChannel.close(); } @Override public long getFirstFreeReference() { return firstFreeReference; } }