/** * Reader factory method. Build a Node object (of the right type) by reading a block in the file. * * @param config Configuration of the History Tree * @param fc FileChannel to the history file, ALREADY SEEKED at the start of the node. * @return The node object * @throws IOException If there was an error reading from the file channel */ public static final HTNode readNode(HTConfig config, FileChannel fc) throws IOException { HTNode newNode = null; int res, i; ByteBuffer buffer = ByteBuffer.allocate(config.getBlockSize()); buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.clear(); res = fc.read(buffer); assert (res == config.getBlockSize()); buffer.flip(); /* Read the common header part */ byte typeByte = buffer.get(); NodeType type = NodeType.fromByte(typeByte); long start = buffer.getLong(); long end = buffer.getLong(); int seqNb = buffer.getInt(); int parentSeqNb = buffer.getInt(); int intervalCount = buffer.getInt(); int stringSectionOffset = buffer.getInt(); buffer.get(); // TODO Used to be "isDone", to be removed from the header /* Now the rest of the header depends on the node type */ switch (type) { case CORE: /* Core nodes */ newNode = new CoreNode(config, seqNb, parentSeqNb, start); newNode.readSpecificHeader(buffer); break; case LEAF: /* Leaf nodes */ newNode = new LeafNode(config, seqNb, parentSeqNb, start); newNode.readSpecificHeader(buffer); break; default: /* Unrecognized node type */ throw new IOException(); } /* * At this point, we should be done reading the header and 'buffer' * should only have the intervals left */ for (i = 0; i < intervalCount; i++) { HTInterval interval = HTInterval.readFrom(buffer); newNode.fIntervals.add(interval); newNode.fSizeOfIntervalSection += interval.getIntervalSize(); } /* Assign the node's other information we have read previously */ newNode.fNodeEnd = end; newNode.fStringSectionOffset = stringSectionOffset; newNode.fIsOnDisk = true; return newNode; }
/** * Add an interval to this node * * @param newInterval Interval to add to this node */ public void addInterval(HTInterval newInterval) { fRwl.writeLock().lock(); try { /* Just in case, should be checked before even calling this function */ assert (newInterval.getIntervalSize() <= getNodeFreeSpace()); /* Find the insert position to keep the list sorted */ int index = fIntervals.size(); while (index > 0 && newInterval.compareTo(fIntervals.get(index - 1)) < 0) { index--; } fIntervals.add(index, newInterval); fSizeOfIntervalSection += newInterval.getIntervalSize(); /* Update the in-node offset "pointer" */ fStringSectionOffset -= (newInterval.getStringsEntrySize()); } finally { fRwl.writeLock().unlock(); } }