aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Wininger2014-04-10 18:36:31 (EDT)
committerGenevieve Bastien2014-04-24 10:30:05 (EDT)
commit621aa074a1e4fcf9360f5ed5a39289741679bdbc (patch)
tree427d055948973d61f404a534ddd33099cf0211cf
parent57cfd3eb8ed44ca50e13b6607e6d2c1f69ed5cdc (diff)
downloadorg.eclipse.linuxtools-621aa074a1e4fcf9360f5ed5a39289741679bdbc.zip
org.eclipse.linuxtools-621aa074a1e4fcf9360f5ed5a39289741679bdbc.tar.gz
org.eclipse.linuxtools-621aa074a1e4fcf9360f5ed5a39289741679bdbc.tar.bz2
tmf : Add Leaf nodes to the History Treerefs/changes/91/24791/6
This patch allows the use of leaf nodes in the History Tree. A leaf node cannot contain children, so we can save 50 x (int + long) = 600 bytes for each node (64k). Note that this patch changes the on-disk file format of the history tree. FILE_VERSION is bumped accordingly. Change-Id: I4d99727a23fcdfbdd911fd27c621354864ebfde1 Signed-off-by: Florian Wininger <florian.wininger@polymtl.ca> Signed-off-by: Alexandre Montplaisir <alexmonthy@voxpopuli.im> Reviewed-on: https://git.eclipse.org/r/24791 Tested-by: Hudson CI Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com> Reviewed-by: Genevieve Bastien <gbastien+lttng@versatic.net> Tested-by: Genevieve Bastien <gbastien+lttng@versatic.net>
-rw-r--r--lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/CoreNode.java18
-rw-r--r--lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HTNode.java99
-rw-r--r--lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTree.java147
-rw-r--r--lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTreeBackend.java16
-rw-r--r--lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/LeafNode.java71
5 files changed, 271 insertions, 80 deletions
diff --git a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/CoreNode.java b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/CoreNode.java
index de7737f..9677090 100644
--- a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/CoreNode.java
+++ b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/CoreNode.java
@@ -1,13 +1,14 @@
/*******************************************************************************
- * Copyright (c) 2012, 2014 Ericsson
- * Copyright (c) 2010, 2011 École Polytechnique de Montréal
- * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
+ * Copyright (c) 2010, 2014 Ericsson, École Polytechnique de Montréal, and others
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
+ * Contributors:
+ * Alexandre Montplaisir - Initial API and implementation
+ * Florian Wininger - Add Extension and Leaf Node
*******************************************************************************/
package org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.historytree;
@@ -21,9 +22,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
* It extends HTNode by adding support for child nodes, and also extensions.
*
* @author Alexandre Montplaisir
- *
*/
-public class CoreNode extends HTNode {
+public final class CoreNode extends HTNode {
/** Number of bytes in a int */
private static final int SIZE_INT = 4;
@@ -61,7 +61,7 @@ public class CoreNode extends HTNode {
* @param start
* The earliest timestamp stored in this node
*/
- protected CoreNode(HTConfig config, int seqNumber, int parentSeqNumber,
+ public CoreNode(HTConfig config, int seqNumber, int parentSeqNumber,
long start) {
super(config, seqNumber, parentSeqNumber, start);
this.nbChildren = 0;
@@ -212,7 +212,7 @@ public class CoreNode extends HTNode {
* @param childNode
* The SHTNode object of the new child
*/
- public void linkNewChild(CoreNode childNode) {
+ public void linkNewChild(HTNode childNode) {
rwl.writeLock().lock();
try {
assert (nbChildren < getConfig().getMaxChildren());
@@ -227,8 +227,8 @@ public class CoreNode extends HTNode {
}
@Override
- public byte getNodeType() {
- return 1;
+ public NodeType getNodeType() {
+ return NodeType.CORE;
}
@Override
diff --git a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HTNode.java b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HTNode.java
index 37c70e2..c15d729 100644
--- a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HTNode.java
+++ b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HTNode.java
@@ -1,13 +1,14 @@
/*******************************************************************************
- * Copyright (c) 2012, 2014 Ericsson
- * Copyright (c) 2010, 2011 École Polytechnique de Montréal
- * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
+ * Copyright (c) 2010, 2014 Ericsson, École Polytechnique de Montréal, and others
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
+ * Contributors:
+ * Alexandre Montplaisir - Initial API and implementation
+ * Florian Wininger - Add Extension and Leaf Node
*******************************************************************************/
package org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.historytree;
@@ -33,6 +34,67 @@ import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
*/
public abstract class HTNode {
+ // ------------------------------------------------------------------------
+ // Class fields
+ // ------------------------------------------------------------------------
+
+ /**
+ * The type of node
+ */
+ public static enum NodeType {
+ /**
+ * Core node, which is a "front" node, at any level of the tree except
+ * the bottom-most one. It has children, and may have extensions.
+ */
+ CORE,
+ /**
+ * Leaf node, which is a node at the last bottom level of the tree. It
+ * cannot have any children or extensions.
+ */
+ LEAF;
+
+ /**
+ * Determine a node type by reading a serialized byte.
+ *
+ * @param rep
+ * The byte representation of the node type
+ * @return The corresponding NodeType
+ * @throws IOException
+ * If the NodeType is unrecognized
+ */
+ public static NodeType fromByte(byte rep) throws IOException {
+ switch (rep) {
+ case 1:
+ return CORE;
+ case 2:
+ return LEAF;
+ default:
+ throw new IOException();
+ }
+ }
+
+ /**
+ * Get the byte representation of this node type. It can then be read
+ * with {@link #fromByte}.
+ *
+ * @return The byte matching this node type
+ */
+ public byte toByte() {
+ switch (this) {
+ case CORE:
+ return 1;
+ case LEAF:
+ return 2;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
/* Configuration of the History Tree to which belongs this node */
private final HTConfig config;
@@ -109,7 +171,8 @@ public abstract class HTNode {
buffer.flip();
/* Read the common header part */
- byte type = buffer.get();
+ byte typeByte = buffer.get();
+ NodeType type = NodeType.fromByte(typeByte);
long start = buffer.getLong();
long end = buffer.getLong();
int seqNb = buffer.getInt();
@@ -120,21 +183,17 @@ public abstract class HTNode {
/* Now the rest of the header depends on the node type */
switch (type) {
- case 1:
+ case CORE:
/* Core nodes */
newNode = new CoreNode(config, seqNb, parentSeqNb, start);
newNode.readSpecificHeader(buffer);
break;
- // TODO implement other node types
- // case 2:
- // /* Leaf nodes */
- //
- //
- //
- // case 3:
- // /* "Claudette" (extended) nodes */
- //
+ case LEAF:
+ /* Leaf nodes */
+ newNode = new LeafNode(config, seqNb, parentSeqNb, start);
+ newNode.readSpecificHeader(buffer);
+ break;
default:
/* Unrecognized node type */
@@ -181,7 +240,7 @@ public abstract class HTNode {
buffer.clear();
/* Write the common header part */
- buffer.put(this.getNodeType());
+ buffer.put(this.getNodeType().toByte());
buffer.putLong(nodeStart);
buffer.putLong(nodeEnd);
buffer.putInt(sequenceNumber);
@@ -254,7 +313,7 @@ public abstract class HTNode {
/**
* Get the end time of this node.
*
- * @return The end time of this node
+ * @return The end time of this node
*/
public long getNodeEnd() {
if (this.isOnDisk) {
@@ -409,7 +468,8 @@ public abstract class HTNode {
* The timestamp
* @return The Interval containing the information we want, or null if it
* wasn't found
- * @throws TimeRangeException If 't' is invalid
+ * @throws TimeRangeException
+ * If 't' is invalid
*/
public HTInterval getRelevantInterval(int key, long t) throws TimeRangeException {
rwl.readLock().lock();
@@ -478,7 +538,6 @@ public abstract class HTNode {
return index;
}
-
/**
* <pre>
* 1 - byte (type)
@@ -575,7 +634,7 @@ public abstract class HTNode {
writer.println("Node #" + sequenceNumber + ":");
/* Array of children */
- if (this.getNodeType() == 1) { /* Only Core Nodes can have children */
+ if (this.getNodeType() == NodeType.CORE) { /* Only Core Nodes can have children */
CoreNode thisNode = (CoreNode) this;
writer.print(" " + thisNode.getNbChildren() + " children");
if (thisNode.getNbChildren() >= 1) {
@@ -605,7 +664,7 @@ public abstract class HTNode {
*
* @return The node type
*/
- public abstract byte getNodeType();
+ public abstract NodeType getNodeType();
/**
* Return the specific header size of this node. This means the size
diff --git a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTree.java b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTree.java
index 47c2ba1..3072d83 100644
--- a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTree.java
+++ b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTree.java
@@ -1,13 +1,14 @@
/*******************************************************************************
- * Copyright (c) 2012, 2014 Ericsson
- * Copyright (c) 2010, 2011 École Polytechnique de Montréal
- * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
+ * Copyright (c) 2010, 2014 Ericsson, École Polytechnique de Montréal, and others
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
+ * Contributors:
+ * Alexandre Montplaisir - Initial API and implementation
+ * Florian Wininger - Add Extension and Leaf Node
*******************************************************************************/
package org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.historytree;
@@ -24,6 +25,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.eclipse.linuxtools.internal.tmf.core.Activator;
import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateProvider;
@@ -45,7 +47,7 @@ public class HistoryTree {
private static final int HISTORY_FILE_MAGIC_NUMBER = 0x05FFA900;
/** File format version. Increment when breaking compatibility. */
- private static final int FILE_VERSION = 3;
+ private static final int FILE_VERSION = 4;
// ------------------------------------------------------------------------
// Tree-specific configuration
@@ -68,7 +70,7 @@ public class HistoryTree {
private int nodeCount;
/** "Cache" to keep the active nodes in memory */
- private final List<CoreNode> latestBranch;
+ private final List<HTNode> latestBranch;
// ------------------------------------------------------------------------
// Constructors/"Destructors"
@@ -86,8 +88,8 @@ public class HistoryTree {
*/
public HistoryTree(HTConfig conf) throws IOException {
/*
- * Simple check to make sure we have enough place in the 0th block
- * for the tree configuration
+ * Simple check to make sure we have enough place in the 0th block for
+ * the tree configuration
*/
if (conf.getBlockSize() < TREE_HEADER_SIZE) {
throw new IllegalArgumentException();
@@ -96,13 +98,13 @@ public class HistoryTree {
config = conf;
treeEnd = conf.getTreeStart();
nodeCount = 0;
- latestBranch = Collections.synchronizedList(new ArrayList<CoreNode>());
+ latestBranch = Collections.synchronizedList(new ArrayList<HTNode>());
/* Prepare the IO object */
treeIO = new HT_IO(config, true);
/* Add the first node to the tree */
- CoreNode firstNode = initNewCoreNode(-1, conf.getTreeStart());
+ LeafNode firstNode = initNewLeafNode(-1, conf.getTreeStart());
latestBranch.add(firstNode);
}
@@ -211,16 +213,16 @@ public class HistoryTree {
* start
* @throws ClosedChannelException
*/
- private List<CoreNode> buildLatestBranch(int rootNodeSeqNb) throws ClosedChannelException {
- HTNode nextChildNode;
+ private List<HTNode> buildLatestBranch(int rootNodeSeqNb) throws ClosedChannelException {
+ List<HTNode> list = new ArrayList<>();
- List<CoreNode> list = new ArrayList<>();
+ HTNode nextChildNode = treeIO.readNode(rootNodeSeqNb);
+ list.add(nextChildNode);
- nextChildNode = treeIO.readNode(rootNodeSeqNb);
- list.add((CoreNode) nextChildNode);
- while (list.get(list.size() - 1).getNbChildren() > 0) {
- nextChildNode = treeIO.readNode(list.get(list.size() - 1).getLatestChild());
- list.add((CoreNode) nextChildNode);
+ /* Follow the last branch up to the leaf */
+ while (nextChildNode.getNodeType() == HTNode.NodeType.CORE) {
+ nextChildNode = treeIO.readNode(((CoreNode) nextChildNode).getLatestChild());
+ list.add(nextChildNode);
}
return Collections.synchronizedList(list);
}
@@ -328,7 +330,7 @@ public class HistoryTree {
*
* @return The root node
*/
- public CoreNode getRootNode() {
+ public HTNode getRootNode() {
return latestBranch.get(0);
}
@@ -487,7 +489,13 @@ public class HistoryTree {
synchronized (latestBranch) {
final long splitTime = treeEnd;
- assert (indexOfNode < latestBranch.size());
+ if (indexOfNode >= latestBranch.size()) {
+ /*
+ * We need to make sure (indexOfNode - 1) doesn't get the last
+ * node in the branch, because that one is a Leaf Node.
+ */
+ throw new IllegalStateException();
+ }
/* Check if we need to add a new root node */
if (indexOfNode == 0) {
@@ -496,7 +504,7 @@ public class HistoryTree {
}
/* Check if we can indeed add a child to the target parent */
- if (latestBranch.get(indexOfNode - 1).getNbChildren() == config.getMaxChildren()) {
+ if (((CoreNode) latestBranch.get(indexOfNode - 1)).getNbChildren() == config.getMaxChildren()) {
/* If not, add a branch starting one level higher instead */
addSiblingNode(indexOfNode - 1);
return;
@@ -507,11 +515,21 @@ public class HistoryTree {
latestBranch.get(i).closeThisNode(splitTime);
treeIO.writeNode(latestBranch.get(i));
- CoreNode prevNode = latestBranch.get(i - 1);
- CoreNode newNode = initNewCoreNode(prevNode.getSequenceNumber(),
- splitTime + 1);
- prevNode.linkNewChild(newNode);
+ CoreNode prevNode = (CoreNode) latestBranch.get(i - 1);
+ HTNode newNode;
+
+ switch (latestBranch.get(i).getNodeType()) {
+ case CORE:
+ newNode = initNewCoreNode(prevNode.getSequenceNumber(), splitTime + 1);
+ break;
+ case LEAF:
+ newNode = initNewLeafNode(prevNode.getSequenceNumber(), splitTime + 1);
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ prevNode.linkNewChild(newNode);
latestBranch.set(i, newNode);
}
}
@@ -524,7 +542,7 @@ public class HistoryTree {
private void addNewRootNode() {
final long splitTime = this.treeEnd;
- CoreNode oldRootNode = latestBranch.get(0);
+ HTNode oldRootNode = latestBranch.get(0);
CoreNode newRootNode = initNewCoreNode(-1, config.getTreeStart());
/* Tell the old root node that it isn't root anymore */
@@ -544,17 +562,25 @@ public class HistoryTree {
int depth = latestBranch.size();
latestBranch.clear();
latestBranch.add(newRootNode);
+
+ // Create new coreNode
for (int i = 1; i < depth + 1; i++) {
- CoreNode prevNode = latestBranch.get(i - 1);
+ CoreNode prevNode = (CoreNode) latestBranch.get(i - 1);
CoreNode newNode = initNewCoreNode(prevNode.getParentSequenceNumber(),
splitTime + 1);
prevNode.linkNewChild(newNode);
latestBranch.add(newNode);
}
+
+ // Create the new leafNode
+ CoreNode prevNode = (CoreNode) latestBranch.get(depth);
+ LeafNode newNode = initNewLeafNode(prevNode.getParentSequenceNumber(), splitTime + 1);
+ prevNode.linkNewChild(newNode);
+ latestBranch.add(newNode);
}
/**
- * Add a new empty node to the tree.
+ * Add a new empty core node to the tree.
*
* @param parentSeqNumber
* Sequence number of this node's parent
@@ -575,6 +601,27 @@ public class HistoryTree {
}
/**
+ * Add a new empty leaf node to the tree.
+ *
+ * @param parentSeqNumber
+ * Sequence number of this node's parent
+ * @param startTime
+ * Start time of the new node
+ * @return The newly created node
+ */
+ private LeafNode initNewLeafNode(int parentSeqNumber, long startTime) {
+ LeafNode newNode = new LeafNode(config, this.nodeCount, parentSeqNumber,
+ startTime);
+ this.nodeCount++;
+
+ /* Update the treeEnd if needed */
+ if (startTime >= this.treeEnd) {
+ this.treeEnd = startTime + 1;
+ }
+ return newNode;
+ }
+
+ /**
* Inner method to select the next child of the current node intersecting
* the given timestamp. Useful for moving down the tree following one
* branch.
@@ -681,8 +728,8 @@ public class HistoryTree {
}
/*
- * Test that the childStartTimes[] array matches the real nodes' start
- * times
+ * Test that the childStartTimes[] array matches the real nodes'
+ * start times
*/
for (int i = 0; i < node.getNbChildren(); i++) {
otherNode = treeIO.readNode(node.getChild(i));
@@ -745,26 +792,44 @@ public class HistoryTree {
/* Only used for debugging, shouldn't be externalized */
@SuppressWarnings("nls")
private void preOrderPrint(PrintWriter writer, boolean printIntervals,
- CoreNode currentNode, int curDepth) {
+ HTNode currentNode, int curDepth) {
writer.println(currentNode.toString());
if (printIntervals) {
currentNode.debugPrintIntervals(writer);
}
- try {
- for (int i = 0; i < currentNode.getNbChildren(); i++) {
- HTNode nextNode = treeIO.readNode(currentNode.getChild(i));
- assert (nextNode instanceof CoreNode); // TODO temporary
- for (int j = 0; j < curDepth; j++) {
- writer.print(" ");
+ switch (currentNode.getNodeType()) {
+ case LEAF:
+ /* Stop if it's the leaf node */
+ return;
+
+ case CORE:
+ try {
+ final CoreNode node = (CoreNode) currentNode;
+ /* Print the extensions, if any */
+ int extension = node.getExtensionSequenceNumber();
+ while (extension != -1) {
+ HTNode nextNode = treeIO.readNode(extension);
+ preOrderPrint(writer, printIntervals, nextNode, curDepth);
+ }
+
+ /* Print the child nodes */
+ for (int i = 0; i < node.getNbChildren(); i++) {
+ HTNode nextNode = treeIO.readNode(node.getChild(i));
+ for (int j = 0; j < curDepth; j++) {
+ writer.print(" ");
+ }
+ writer.print("+-");
+ preOrderPrint(writer, printIntervals, nextNode, curDepth + 1);
}
- writer.print("+-");
- preOrderPrint(writer, printIntervals, (CoreNode) nextNode,
- curDepth + 1);
+ } catch (ClosedChannelException e) {
+ Activator.logError(e.getMessage());
}
- } catch (ClosedChannelException e) {
- e.printStackTrace();
+ break;
+
+ default:
+ break;
}
}
diff --git a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTreeBackend.java b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTreeBackend.java
index 7268a48..b85a463 100644
--- a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTreeBackend.java
+++ b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTreeBackend.java
@@ -178,15 +178,13 @@ public class HistoryTreeBackend implements IStateHistoryBackend {
}
/* We start by reading the information in the root node */
- // FIXME using CoreNode for now, we'll have to redo this part to handle
- // different node types
- CoreNode currentNode = sht.getRootNode();
+ HTNode currentNode = sht.getRootNode();
currentNode.writeInfoFromNode(stateInfo, t);
/* Then we follow the branch down in the relevant children */
try {
- while (currentNode.getNbChildren() > 0) {
- currentNode = (CoreNode) sht.selectNextChild(currentNode, t);
+ while (currentNode.getNodeType() == HTNode.NodeType.CORE) {
+ currentNode = sht.selectNextChild((CoreNode) currentNode, t);
currentNode.writeInfoFromNode(stateInfo, t);
}
} catch (ClosedChannelException e) {
@@ -225,14 +223,12 @@ public class HistoryTreeBackend implements IStateHistoryBackend {
throw new TimeRangeException();
}
- // FIXME using CoreNode for now, we'll have to redo this part to handle
- // different node types
- CoreNode currentNode = sht.getRootNode();
+ HTNode currentNode = sht.getRootNode();
HTInterval interval = currentNode.getRelevantInterval(key, t);
try {
- while (interval == null && currentNode.getNbChildren() > 0) {
- currentNode = (CoreNode) sht.selectNextChild(currentNode, t);
+ while (interval == null && currentNode.getNodeType() == HTNode.NodeType.CORE) {
+ currentNode = sht.selectNextChild((CoreNode)currentNode, t);
interval = currentNode.getRelevantInterval(key, t);
}
} catch (ClosedChannelException e) {
diff --git a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/LeafNode.java b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/LeafNode.java
new file mode 100644
index 0000000..88abc36
--- /dev/null
+++ b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/LeafNode.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2014 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Florian Wininger - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.tmf.core.statesystem.backends.historytree;
+
+import java.nio.ByteBuffer;
+
+/**
+ * A Leaf node is a last-level node of a History Tree.
+ *
+ * A leaf node cannot have children, so it extends HTNode without adding
+ * anything in particular.
+ *
+ * @author Florian Wininger
+ */
+public final class LeafNode extends HTNode {
+
+ /**
+ * Initial constructor. Use this to initialize a new EMPTY node.
+ *
+ * @param config
+ * Configuration of the History Tree
+ * @param seqNumber
+ * The (unique) sequence number assigned to this particular node
+ * @param parentSeqNumber
+ * The sequence number of this node's parent node
+ * @param start
+ * The earliest timestamp stored in this node
+ */
+ public LeafNode(HTConfig config, int seqNumber, int parentSeqNumber,
+ long start) {
+ super(config, seqNumber, parentSeqNumber, start);
+ }
+
+ @Override
+ protected void readSpecificHeader(ByteBuffer buffer) {
+ /* No specific header part */
+ }
+
+ @Override
+ protected void writeSpecificHeader(ByteBuffer buffer) {
+ /* No specific header part */
+ }
+
+ @Override
+ public NodeType getNodeType() {
+ return NodeType.LEAF;
+ }
+
+ @Override
+ protected int getSpecificHeaderSize() {
+ /* Empty */
+ return 0;
+ }
+
+ @Override
+ public String toStringSpecific() {
+ /* Only used for debugging, shouldn't be externalized */
+ return "Leaf Node, "; //$NON-NLS-1$;
+ }
+
+}