1 /*******************************************************************************
2 * Copyright (c) 2010, 2014 Ericsson, École Polytechnique de Montréal, and others
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Alexandre Montplaisir - Initial API and implementation
11 * Florian Wininger - Add Extension and Leaf Node
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.internal
.statesystem
.core
.backend
.historytree
;
16 import java
.nio
.ByteBuffer
;
17 import java
.util
.concurrent
.locks
.ReentrantReadWriteLock
;
20 * A Core node is a first-level node of a History Tree which is not a leaf node.
22 * It extends HTNode by adding support for child nodes, and also extensions.
24 * @author Alexandre Montplaisir
26 public final class CoreNode
extends HTNode
{
28 /** Number of bytes in a int */
29 private static final int SIZE_INT
= 4;
31 /** Number of bytes in a long */
32 private static final int SIZE_LONG
= 8;
34 /** Nb. of children this node has */
35 private int nbChildren
;
37 /** Seq. numbers of the children nodes (size = MAX_NB_CHILDREN) */
38 private int[] children
;
40 /** Start times of each of the children (size = MAX_NB_CHILDREN) */
41 private long[] childStart
;
43 /** Seq number of this node's extension. -1 if none */
44 private volatile int extension
= -1;
47 * Lock used to gate the accesses to the children arrays. Meant to be a
48 * different lock from the one in {@link HTNode}.
50 private final ReentrantReadWriteLock rwl
= new ReentrantReadWriteLock(false);
53 * Initial constructor. Use this to initialize a new EMPTY node.
56 * Configuration of the History Tree
58 * The (unique) sequence number assigned to this particular node
59 * @param parentSeqNumber
60 * The sequence number of this node's parent node
62 * The earliest timestamp stored in this node
64 public CoreNode(HTConfig config
, int seqNumber
, int parentSeqNumber
,
66 super(config
, seqNumber
, parentSeqNumber
, start
);
68 int size
= config
.getMaxChildren();
71 * We instantiate the two following arrays at full size right away,
72 * since we want to reserve that space in the node's header.
73 * "this.nbChildren" will tell us how many relevant entries there are in
76 this.children
= new int[size
];
77 this.childStart
= new long[size
];
81 protected void readSpecificHeader(ByteBuffer buffer
) {
82 int size
= getConfig().getMaxChildren();
84 extension
= buffer
.getInt();
85 nbChildren
= buffer
.getInt();
87 children
= new int[size
];
88 for (int i
= 0; i
< nbChildren
; i
++) {
89 children
[i
] = buffer
.getInt();
91 for (int i
= nbChildren
; i
< size
; i
++) {
95 this.childStart
= new long[size
];
96 for (int i
= 0; i
< nbChildren
; i
++) {
97 childStart
[i
] = buffer
.getLong();
99 for (int i
= nbChildren
; i
< size
; i
++) {
105 protected void writeSpecificHeader(ByteBuffer buffer
) {
106 int size
= getConfig().getMaxChildren();
108 buffer
.putInt(extension
);
109 buffer
.putInt(nbChildren
);
111 /* Write the "children's seq number" array */
112 for (int i
= 0; i
< nbChildren
; i
++) {
113 buffer
.putInt(children
[i
]);
115 for (int i
= nbChildren
; i
< size
; i
++) {
119 /* Write the "children's start times" array */
120 for (int i
= 0; i
< nbChildren
; i
++) {
121 buffer
.putLong(childStart
[i
]);
123 for (int i
= nbChildren
; i
< size
; i
++) {
129 * Return the number of child nodes this node has.
131 * @return The number of child nodes
133 public int getNbChildren() {
134 rwl
.readLock().lock();
135 int ret
= nbChildren
;
136 rwl
.readLock().unlock();
141 * Get the child node corresponding to the specified index
143 * @param index The index of the child to lookup
144 * @return The child node
146 public int getChild(int index
) {
147 rwl
.readLock().lock();
149 return children
[index
];
151 rwl
.readLock().unlock();
156 * Get the latest (right-most) child node of this node.
158 * @return The latest child node
160 public int getLatestChild() {
161 rwl
.readLock().lock();
163 return children
[nbChildren
- 1];
165 rwl
.readLock().unlock();
170 * Get the start time of the specified child node.
173 * The index of the child node
174 * @return The start time of the that child node.
176 public long getChildStart(int index
) {
177 rwl
.readLock().lock();
179 return childStart
[index
];
181 rwl
.readLock().unlock();
186 * Get the start time of the latest (right-most) child node.
188 * @return The start time of the latest child
190 public long getLatestChildStart() {
191 rwl
.readLock().lock();
193 return childStart
[nbChildren
- 1];
195 rwl
.readLock().unlock();
200 * Get the sequence number of the extension to this node (if there is one).
202 * @return The sequence number of the extended node. '-1' is returned if
203 * there is no extension node.
205 public int getExtensionSequenceNumber() {
210 * Tell this node that it has a new child (Congrats!)
213 * The SHTNode object of the new child
215 public void linkNewChild(HTNode childNode
) {
216 rwl
.writeLock().lock();
218 assert (nbChildren
< getConfig().getMaxChildren());
220 children
[nbChildren
] = childNode
.getSequenceNumber();
221 childStart
[nbChildren
] = childNode
.getNodeStart();
225 rwl
.writeLock().unlock();
230 public NodeType
getNodeType() {
231 return NodeType
.CORE
;
235 protected int getSpecificHeaderSize() {
236 int maxChildren
= getConfig().getMaxChildren();
238 SIZE_INT
/* 1x int (extension node) */
239 + SIZE_INT
/* 1x int (nbChildren) */
241 /* MAX_NB * int ('children' table) */
242 + SIZE_INT
* maxChildren
244 /* MAX_NB * Timevalue ('childStart' table) */
245 + SIZE_LONG
* maxChildren
;
251 public String
toStringSpecific() {
252 /* Only used for debugging, shouldn't be externalized */
253 return "Core Node, " + nbChildren
+ " children, "; //$NON-NLS-1$ //$NON-NLS-2$