/** * Writes a buffer that was allocated by calling either {@link * #allocateBlock} or {@link #readBlock} to the specified block. The buffer * may only be written to the same block as was specified when the buffer was * allocated. * * @param block the buffer to write to the file. */ public void writeBlock(Block block) { assert(block.getBlockId() >= 0) && (block.getBlockId() < nrBlocks); // NO-OP - this is because mapped buffers are automatically written }
/** * Gets the Id attribute of the AVLNode object * * @return The Id value */ public long getId() { return block.getBlockId(); }
/** * Determines if the contents of this block are equal to the specified block. * * @param o the block to compare to. * @return <code>true</code> if the blocks compare equal, both in ID and in content. */ public boolean equals(Object o) { if (!(o instanceof Block)) { return false; } Block block = (Block) o; if (blockSize != block.blockSize) { return false; } if (block.bb == bb && block.getBlockId() == blockId) { return true; } ByteBuffer bb1 = bb.asReadOnlyBuffer(); bb1.limit(byteOffset + blockSize); bb1.position(byteOffset); ByteBuffer bb2 = block.bb.asReadOnlyBuffer(); bb2.limit(block.byteOffset + blockSize); bb2.position(block.byteOffset); return bb1.equals(bb2); }
if ( (headBlock != null) && ( (int) headBlock.getBlockId() == blockId)) { writeHeadBlock(); ( (int) reallocateBlock.getBlockId() == blockId)) { writeReallocateBlock(); if ( (tailBlock != null) && ( (int) tailBlock.getBlockId() == blockId)) { Block block = tailBlock; tailBlock = null;
/** * Allocates a new block for dstBlockId, copies the contents of srcBlock to * it, releases srcBlock and returns the new Block. * * @param block The block to copy data from. This block will be set to the * destination block before returning, and acts as the return value. * @param dstBlockId the ID of the new Block to be allocated. */ public void copyBlock(Block block, long dstBlockId) { assert(block.getBlockId() >= 0) && (block.getBlockId() < nrBlocks); assert(dstBlockId >= 0) && (dstBlockId < nrBlocks); assert block.getBlockId() != dstBlockId; int byteOffset = block.getByteOffset(); ByteBuffer srcBuffer = block.getSourceBuffer(); srcBuffer.limit(byteOffset + blockSize); srcBuffer.position(byteOffset); long dstFileOffset = dstBlockId * blockSize; int dstRegionNr = (int) (dstFileOffset / stride); int dstByteOffset = (int) (dstFileOffset % stride); ByteBuffer dstBuffer = mappedByteBuffers[dstRegionNr]; dstBuffer.position(dstByteOffset); // Copy the bytes. dstBuffer.put(srcBuffer); block.init( dstBlockId, dstByteOffset, dstBuffer, srcByteBuffers[dstRegionNr], intBuffers[dstRegionNr], longBuffers[dstRegionNr] ); }
/** * Writes a buffer that was allocated by calling either {@link * #allocateBlock} or {@link #readBlock} to the specified block. The buffer * may only be written to the same block as was specified when the buffer was * allocated. * * @param block the buffer to write to the file. * @throws IOException if an I/O error occurs. */ public void writeBlock(Block block) throws IOException { long blockId = block.getBlockId(); assert(blockId >= 0) && (blockId < nrBlocks); ByteBuffer byteBuffer = block.getByteBuffer(); for (;;) { try { // Reset the position. byteBuffer.rewind(); // Write the buffer to the file. fc.write(byteBuffer, blockId * blockSize); break; } catch (ClosedChannelException ex) { // The Channel may have been inadvertently closed by another thread // being interrupted. Attempt to reopen the channel. if (!ensureOpen()) { throw ex; } // Loop back and retry the write. } } }
/** * Gets a new block from the file to write block data to. * The block data to write is a modified version of an existing block. * * @param block The block to be copied into the new "modified" block. * @throws IOException if an I/O error occurs. */ public void modifyBlock(Block block) throws IOException { assert this == currentPhase; if (freeList.isSharedItem(block.getBlockId())) { // Allocate a new block and copy block to it. long newBlockId = freeList.allocate(); blockFile.setNrBlocks(freeList.getNextItem()); // Although we use block after the block is freed, the block can't // be reused (by a later phase) until the current phase is committed. freeList.free(block.getBlockId()); blockFile.copyBlock(block, newBlockId); } }
long id = block.getBlockId(); block.modify(); writable = true; dirty = true; long newId = block.getBlockId();
/** * Reads the reallocate block from blockFile. If the current reallocate buffer * already holds the reallocate block then nothing is done. If the reallocate * buffer contains a different block then it is released first. * * @param blockId The block number of the reallocate block. * @throws IOException if an I/O error occurs. */ private void readReallocateBlock(int blockId) throws IOException { if (reallocateBlock != null) { if (blockId == (int) reallocateBlock.getBlockId()) { return; } releaseReallocateBlock(); } reallocateBlock = findBlock(blockId); if (reallocateBlock == null) { reallocateBlock = blockFile.readBlock(objectPool, blockId); } reallocateBlockDirty = false; }
/** * Reads the tail block from blockFile. If the current tail buffer already * holds the tail block then nothing is done. If the tail buffer contains a * different block then it is freed first. * * @param blockId The block number to use as the tail buffer. * @throws IOException if an I/O error occurs. */ private void readTailBlock(int blockId) throws IOException { if (tailBlock != null) { if (blockId == (int) tailBlock.getBlockId()) { return; } releaseTailBlock(); } tailBlock = findBlock(blockId); if (tailBlock == null) { tailBlock = blockFile.readBlock(objectPool, blockId); } }
/** * Reads the head block from blockFile. If the current head buffer already * holds the head block then nothing is done. If the head buffer contains a * different block then it is freed first (writing it to the file). This is * similar to {@link #allocateHeadBlock} only it will not allocate a new * block from the file, and always reads the contents of the existing block * in the file. * * @param blockId The block number of the head block. * @throws IOException if an I/O error occurs. */ private void readHeadBlock(int blockId) throws IOException { if (headBlock != null) { if (blockId == (int) headBlock.getBlockId()) { return; } releaseHeadBlock(); } headBlock = findBlock(blockId); if (headBlock == null) { headBlock = blockFile.readBlock(objectPool, blockId); } headBlockDirty = false; }
/** * Allocates a buffer from blockFile to hold the head block. If the current * head buffer already holds the head block then nothing is done. If the head * buffer contains a different block then it is released first (writing the * head block to the file). This method uses a previous version of the * block, unless no block with that ID exists yet, in which case a new block * is read in, or allocated if it does not exist in the file either. If the * block existed in the file, then its contents will be ignored. Contrast * this to {@link #readHeadBlock} where the contents of the block on the disk * are always read. * * @param blockId The block number of the head block. * @throws IOException if an I/O error occurs. */ private void allocateHeadBlock(int blockId) throws IOException { if (headBlock != null) { if (blockId == (int) headBlock.getBlockId()) { headBlockDirty = false; return; } releaseHeadBlock(); } headBlock = findBlock(blockId); if (headBlock == null) { headBlock = blockFile.allocateBlock(objectPool, blockId); } headBlockDirty = false; }
block.write(); blockId = block.getBlockId();
/** * Changes the block ID of the specified Block. This method is called * copyBlock because a call to copyBlock() followed by a call to * writeBlock() can be used to copy the contents of a block to a new * location in the block file. * * @param block the Block to be copied. * @param dstBlockId the ID of the block to which the Block will be written * when writeBlock() is called. * @throws IOException if an I/O error occurs. */ public void copyBlock(Block block, long dstBlockId) throws IOException { assert this == currentPhase; assert block.getBlockId() != dstBlockId; if (freeList.isSharedItem(dstBlockId)) { // Choose an alternative destination block since this one is shared // with another phase. freeList.free(dstBlockId); dstBlockId = freeList.allocate(); blockFile.setNrBlocks(freeList.getNextItem()); } blockFile.copyBlock(block, dstBlockId); }
allocateHeadBlock(newHeadBlockId); headBlock.putInt(IDX_NEXT, nextHeadBlockId); headBlock.putInt(IDX_PREV, (int) prevHeadBlock.getBlockId()); headBlockDirty = true; force();