/** * Write this node to the given file channel. * * @param fc The file channel to write to (should be sought to be correct position) * @throws IOException If there was an error writing */ public final void writeSelf(FileChannel fc) throws IOException { /* * Yes, we are taking the *read* lock here, because we are reading the * information in the node to write it to disk. */ fRwl.readLock().lock(); try { final int blockSize = fConfig.getBlockSize(); int curStringsEntryEndPos = blockSize; ByteBuffer buffer = ByteBuffer.allocate(blockSize); buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.clear(); /* Write the common header part */ buffer.put(getNodeType().toByte()); buffer.putLong(fNodeStart); buffer.putLong(fNodeEnd); buffer.putInt(fSequenceNumber); buffer.putInt(fParentSequenceNumber); buffer.putInt(fIntervals.size()); buffer.putInt(fStringSectionOffset); buffer.put((byte) 1); // TODO Used to be "isDone", to be removed from header /* Now call the inner method to write the specific header part */ writeSpecificHeader(buffer); /* Back to us, we write the intervals */ for (HTInterval interval : fIntervals) { int size = interval.writeInterval(buffer, curStringsEntryEndPos); curStringsEntryEndPos -= size; } /* * Write padding between the end of the Data section and the start * of the Strings section (needed to fill the node in case there is * no Strings section) */ while (buffer.position() < fStringSectionOffset) { buffer.put((byte) 0); } /* * If the offsets were right, the size of the Strings section should * be == to the expected size */ assert (curStringsEntryEndPos == fStringSectionOffset); /* Finally, write everything in the Buffer to disk */ // if we don't do this, flip() will lose what's after. buffer.position(blockSize); buffer.flip(); int res = fc.write(buffer); assert (res == blockSize); } finally { fRwl.readLock().unlock(); } fIsOnDisk = true; }