package it.cavallium.strangedb.database.references; import it.cavallium.strangedb.database.DatabaseFileIO; import it.cavallium.strangedb.database.IReferencesIO; import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.locks.ReentrantReadWriteLock; public class DatabaseReferencesIO implements IReferencesIO { private final DatabaseFileIO fileIO; private final DatabaseReferencesMetadata referencesMetadata; public DatabaseReferencesIO(DatabaseFileIO fileIO, DatabaseReferencesMetadata referencesMetadata) { this.fileIO = fileIO; this.referencesMetadata = referencesMetadata; } @Override public long allocateReference() throws IOException { return referencesMetadata.newReference(0, 0); } @Override public long allocateReference(int size, ByteBuffer data) throws IOException { long index = writeToFile(size, data); return referencesMetadata.newReference(index, size); } @Override public void writeToReference(long reference, byte cleanerId, int size, ByteBuffer data) throws IOException { long index = writeToFile(size, data); referencesMetadata.editReference(reference, new ReferenceInfo(index, size, cleanerId)); } @Override public ByteBuffer readFromReference(long reference) throws IOException { ReferenceInfo referenceInfo = referencesMetadata.getReferenceInfo(reference); return fileIO.readAt(referenceInfo.getIndex(), referenceInfo.getSize()); } public ByteBuffer readFromReferenceSizeAndLastElementOfReferencesList(long reference) throws IOException { ReferenceInfo referenceInfo = referencesMetadata.getReferenceInfo(reference); if (referenceInfo.getSize() >= Integer.BYTES * 2 + Long.BYTES) { return fileIO.readAt(referenceInfo.getIndex() + referenceInfo.getSize() - (Integer.BYTES + Long.BYTES), Integer.BYTES + Long.BYTES); } else { return fileIO.readAt(referenceInfo.getIndex(), referenceInfo.getSize()); } } /** * * @param size * @param data * @return index * @throws IOException */ private long writeToFile(int size, ByteBuffer data) throws IOException { if (size == 0 && data == null) return 0; 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()); } return fileIO.writeAtEnd(size, data); } }