* Meta-container for the History Tree. This structure contains all the
* high-level data relevant to the tree.
*
- * @author alexmont
+ * @author Alexandre Montplaisir
*
*/
class HistoryTree {
/** Latest timestamp found in the tree (at any given moment) */
private long treeEnd;
- /** How many nodes exist in this tree, total */
+ /** The total number of nodes that exists in this tree */
private int nodeCount;
/** "Cache" to keep the active nodes in memory */
latestBranch = new ArrayList<CoreNode>();
/* Prepare the IO object */
- treeIO = new HT_IO(this, true);
+ treeIO = new HT_IO(config, true);
/* Add the first node to the tree */
CoreNode firstNode = initNewCoreNode(-1, conf.getTreeStart());
buffer.flip();
/*
- * Check the magic number,to make sure we're opening the right type of
+ * Check the magic number to make sure we're opening the right type of
* file
*/
res = buffer.getInt();
if (res != expProviderVersion &&
expProviderVersion != ITmfStateProvider.IGNORE_PROVIDER_VERSION) {
/*
- * The existing history was built using a event handler that doesn't
- * match the current one in the framework. Information could be all
- * wrong, so we'll force a rebuild of the history file instead.
+ * The existing history was built using an event handler that doesn't
+ * match the current one in the framework.
+ *
+ * Information could be all wrong. Instead of keeping an incorrect
+ * history file, a rebuild is done.
*/
fc.close();
fis.close();
* file, not extremely elegant. But how to pass the information here to
* the SHT otherwise?
*/
- this.treeIO = new HT_IO(this, false);
+ this.treeIO = new HT_IO(config, false);
rebuildLatestBranch(rootNodeSeqNb);
this.treeEnd = latestBranch.get(0).getNodeEnd();
* file.
*
* @param requestedEndTime
+ * The greatest timestamp present in the history tree
*/
void closeTree(long requestedEndTime) {
FileChannel fc;
return nodeCount;
}
- HT_IO getTreeIO() {
- return treeIO;
- }
-
List<CoreNode> getLatestBranch() {
return Collections.unmodifiableList(latestBranch);
}
+ // ------------------------------------------------------------------------
+ // HT_IO interface
+ // ------------------------------------------------------------------------
+
+ File supplyATWriterFile() {
+ return config.getStateFile();
+ }
+
+ FileInputStream supplyATReader() {
+ return treeIO.supplyATReader(getNodeCount());
+ }
+
+ long supplyATWriterFilePos() {
+ return HistoryTree.TREE_HEADER_SIZE
+ + ((long) getNodeCount() * config.getBlockSize());
+ }
+
+ HTNode readNode(int seqNumber) throws ClosedChannelException {
+ /* Try to read the node from memory */
+ for (HTNode node : getLatestBranch()) {
+ if (node.getSequenceNumber() == seqNumber) {
+ return node;
+ }
+ }
+
+ /* Read the node from disk */
+ return treeIO.readNode(seqNumber);
+ }
+
+ void writeNode(HTNode node) {
+ treeIO.writeNode(node);
+ }
+
+ void closeFile() {
+ treeIO.closeFile();
+ }
+
+ void deleteFile() {
+ treeIO.deleteFile();
+ }
+
// ------------------------------------------------------------------------
// Operations
// ------------------------------------------------------------------------
this.latestBranch = new ArrayList<CoreNode>();
- nextChildNode = treeIO.readNodeFromDisk(rootNodeSeqNb);
+ nextChildNode = treeIO.readNode(rootNodeSeqNb);
latestBranch.add((CoreNode) nextChildNode);
while (latestBranch.get(latestBranch.size() - 1).getNbChildren() > 0) {
- nextChildNode = treeIO.readNodeFromDisk(latestBranch.get(latestBranch.size() - 1).getLatestChild());
+ nextChildNode = treeIO.readNode(latestBranch.get(latestBranch.size() - 1).getLatestChild());
latestBranch.add((CoreNode) nextChildNode);
}
}
* Insert an interval in the tree
*
* @param interval
+ * The interval to be inserted
*/
void insertInterval(HTInterval interval) throws TimeRangeException {
if (interval.getStartTime() < config.getTreeStart()) {
if (interval.getEndTime() > this.treeEnd) {
this.treeEnd = interval.getEndTime();
}
- return;
}
/**
latestBranch.set(i, newNode);
}
- return;
}
/**
* @return The newly created node
*/
private CoreNode initNewCoreNode(int parentSeqNumber, long startTime) {
- CoreNode newNode = new CoreNode(this, this.nodeCount, parentSeqNumber,
+ CoreNode newNode = new CoreNode(config, this.nodeCount, parentSeqNumber,
startTime);
this.nodeCount++;
* branch.
*
* @param currentNode
+ * The node on which the request is made
* @param t
+ * The timestamp to choose which child is the next one
* @return The child node intersecting t
* @throws ClosedChannelException
* If the file channel was closed while we were reading the tree
break;
}
}
+
/*
* Once we exit this loop, we should have found a children to follow. If
* we didn't, there's a problem.
* node has to be on disk
*/
if (currentNode.isDone()) {
- return treeIO.readNodeFromDisk(potentialNextSeqNb);
+ return treeIO.readNode(potentialNextSeqNb);
}
return treeIO.readNode(potentialNextSeqNb);
}
+ latestBranch.get(latestBranch.size() - 1).getSequenceNumber();
}
- private int curDepth;
-
/**
* Start at currentNode and print the contents of all its children, in
* pre-order. Give the root node in parameter to visit the whole tree, and
* have a nice overview.
*/
+ /* Only used for debugging, shouldn't be externalized */
@SuppressWarnings("nls")
private void preOrderPrint(PrintWriter writer, boolean printIntervals,
- CoreNode currentNode) {
- /* Only used for debugging, shouldn't be externalized */
- int i, j;
- HTNode nextNode;
+ CoreNode currentNode, int curDepth) {
writer.println(currentNode.toString());
if (printIntervals) {
currentNode.debugPrintIntervals(writer);
}
- curDepth++;
try {
- for (i = 0; i < currentNode.getNbChildren(); i++) {
- nextNode = treeIO.readNode(currentNode.getChild(i));
+ for (int i = 0; i < currentNode.getNbChildren(); i++) {
+ HTNode nextNode = treeIO.readNode(currentNode.getChild(i));
assert (nextNode instanceof CoreNode); // TODO temporary
- for (j = 0; j < curDepth - 1; j++) {
+ for (int j = 0; j < curDepth; j++) {
writer.print(" ");
}
writer.print("+-");
- preOrderPrint(writer, printIntervals, (CoreNode) nextNode);
+ preOrderPrint(writer, printIntervals, (CoreNode) nextNode,
+ curDepth + 1);
}
} catch (ClosedChannelException e) {
e.printStackTrace();
}
- curDepth--;
- return;
}
/**
* @param writer
* PrintWriter in which to write the output
* @param printIntervals
- * Says if you want to output the full interval information
+ * Flag to enable full output of the interval information
*/
void debugPrintFullTree(PrintWriter writer, boolean printIntervals) {
/* Only used for debugging, shouldn't be externalized */
- curDepth = 0;
- this.preOrderPrint(writer, false, latestBranch.get(0));
+
+ this.preOrderPrint(writer, false, latestBranch.get(0), 0);
if (printIntervals) {
writer.println("\nDetails of intervals:"); //$NON-NLS-1$
- curDepth = 0;
- this.preOrderPrint(writer, true, latestBranch.get(0));
+ this.preOrderPrint(writer, true, latestBranch.get(0), 0);
}
writer.println('\n');
}