package it.cavallium.strangedb.database.references; import it.cavallium.strangedb.database.IReferencesIO; import it.cavallium.strangedb.database.blocks.DatabaseBlocksIO; import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.locks.ReentrantReadWriteLock; import static it.cavallium.strangedb.database.IBlocksMetadata.EMPTY_BLOCK_ID; public class DatabaseReferencesIO implements IReferencesIO { private final DatabaseBlocksIO blocksIO; private final DatabaseReferencesMetadata referencesMetadata; private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false); public DatabaseReferencesIO(DatabaseBlocksIO blocksIO, DatabaseReferencesMetadata referencesMetadata) { this.blocksIO = blocksIO; this.referencesMetadata = referencesMetadata; } @Override public long allocateReference() throws IOException { return referencesMetadata.newReference(EMPTY_BLOCK_ID); } @Override public long allocateReference(int size, ByteBuffer data) throws IOException { long blockId = (size == 0) ? EMPTY_BLOCK_ID : blocksIO.newBlock(size, data); return referencesMetadata.newReference(blockId); } @Override public void writeToReference(long reference, byte cleanerId, int size, ByteBuffer data) throws IOException { long blockId = (size == 0) ? EMPTY_BLOCK_ID : blocksIO.newBlock(size, data); lock.writeLock().lock(); try { referencesMetadata.editReference(reference, cleanerId, blockId); } finally { lock.writeLock().unlock(); } } @Override public ByteBuffer readFromReference(long reference) throws IOException { long blockId; lock.readLock().lock(); try { blockId = referencesMetadata.getReferenceBlockId(reference); } finally { lock.readLock().unlock(); } return blocksIO.readBlock(blockId); } public ByteBuffer readFromReferenceSizeAndLastElementOfReferencesList(long reference) throws IOException { long blockId; lock.readLock().lock(); try { blockId = referencesMetadata.getReferenceBlockId(reference); } finally { lock.readLock().unlock(); } return blocksIO.readBlockSizeAndLastElementOfReferencesList(blockId); } }