tmf : Add Leaf nodes to the History Tree
authorFlorian Wininger <florian.wininger@polymtl.ca>
Thu, 10 Apr 2014 22:36:31 +0000 (18:36 -0400)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Thu, 24 Apr 2014 14:30:05 +0000 (10:30 -0400)
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>
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/CoreNode.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HTNode.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTree.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/HistoryTreeBackend.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/LeafNode.java [new file with mode: 0644]

index de7737f43335d0949abbcbabbb498af325c426df..9677090d89bd903631b1c04a6de85ea49c4d4e0b 100644 (file)
@@ -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
index 37c70e296455f7b53a5354bd56138cafbabc6371..c15d7299919fdf0c8f291b689fa9294a107168d0 100644 (file)
@@ -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
index 47c2ba18513a00d81e33082d8da141f791d56f44..3072d83f2168500b9751fca7b8d8c273346d4d08 100644 (file)
@@ -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
@@ -574,6 +600,27 @@ public class HistoryTree {
         return newNode;
     }
 
+    /**
+     * 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
@@ -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;
         }
     }
 
index 7268a489b30cc3504633aa1dd842f4de226ba59e..b85a4639fba233397dc3386a745c791bde0e8b4d 100644 (file)
@@ -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/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/LeafNode.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/backends/historytree/LeafNode.java
new file mode 100644 (file)
index 0000000..88abc36
--- /dev/null
@@ -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$;
+    }
+
+}
This page took 0.035619 seconds and 5 git commands to generate.