1 /*******************************************************************************
2 * Copyright (c) 2010, 2016 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
.tracecompass
.internal
.statesystem
.core
.backend
.historytree
;
16 import java
.nio
.ByteBuffer
;
17 import java
.util
.Arrays
;
18 import java
.util
.concurrent
.locks
.ReentrantReadWriteLock
;
21 * A Core node is a first-level node of a History Tree which is not a leaf node.
23 * It extends HTNode by adding support for child nodes, and also extensions.
25 * @author Alexandre Montplaisir
27 public final class CoreNode
extends HTNode
{
29 /** Nb. of children this node has */
30 private int nbChildren
;
32 /** Seq. numbers of the children nodes (size = MAX_NB_CHILDREN) */
33 private int[] children
;
35 /** Start times of each of the children (size = MAX_NB_CHILDREN) */
36 private long[] childStart
;
38 /** Seq number of this node's extension. -1 if none */
39 private volatile int extension
= -1;
42 * Lock used to gate the accesses to the children arrays. Meant to be a
43 * different lock from the one in {@link HTNode}.
45 private final ReentrantReadWriteLock rwl
= new ReentrantReadWriteLock(false);
48 * Initial constructor. Use this to initialize a new EMPTY node.
51 * Configuration of the History Tree
53 * The (unique) sequence number assigned to this particular node
54 * @param parentSeqNumber
55 * The sequence number of this node's parent node
57 * The earliest timestamp stored in this node
59 public CoreNode(HTConfig config
, int seqNumber
, int parentSeqNumber
,
61 super(config
, seqNumber
, parentSeqNumber
, start
);
63 int size
= config
.getMaxChildren();
66 * We instantiate the two following arrays at full size right away,
67 * since we want to reserve that space in the node's header.
68 * "this.nbChildren" will tell us how many relevant entries there are in
71 this.children
= new int[size
];
72 this.childStart
= new long[size
];
76 protected void readSpecificHeader(ByteBuffer buffer
) {
77 int size
= getConfig().getMaxChildren();
79 extension
= buffer
.getInt();
80 nbChildren
= buffer
.getInt();
82 children
= new int[size
];
83 for (int i
= 0; i
< nbChildren
; i
++) {
84 children
[i
] = buffer
.getInt();
86 for (int i
= nbChildren
; i
< size
; i
++) {
90 this.childStart
= new long[size
];
91 for (int i
= 0; i
< nbChildren
; i
++) {
92 childStart
[i
] = buffer
.getLong();
94 for (int i
= nbChildren
; i
< size
; i
++) {
100 protected void writeSpecificHeader(ByteBuffer buffer
) {
101 int size
= getConfig().getMaxChildren();
103 buffer
.putInt(extension
);
104 buffer
.putInt(nbChildren
);
106 /* Write the "children's seq number" array */
107 for (int i
= 0; i
< nbChildren
; i
++) {
108 buffer
.putInt(children
[i
]);
110 for (int i
= nbChildren
; i
< size
; i
++) {
114 /* Write the "children's start times" array */
115 for (int i
= 0; i
< nbChildren
; i
++) {
116 buffer
.putLong(childStart
[i
]);
118 for (int i
= nbChildren
; i
< size
; i
++) {
124 * Return the number of child nodes this node has.
126 * @return The number of child nodes
128 public int getNbChildren() {
129 rwl
.readLock().lock();
130 int ret
= nbChildren
;
131 rwl
.readLock().unlock();
136 * Get the child node corresponding to the specified index
138 * @param index The index of the child to lookup
139 * @return The child node
141 public int getChild(int index
) {
142 rwl
.readLock().lock();
144 return children
[index
];
146 rwl
.readLock().unlock();
151 * Get the latest (right-most) child node of this node.
153 * @return The latest child node
155 public int getLatestChild() {
156 rwl
.readLock().lock();
158 return children
[nbChildren
- 1];
160 rwl
.readLock().unlock();
165 * Get the start time of the specified child node.
168 * The index of the child node
169 * @return The start time of the that child node.
171 public long getChildStart(int index
) {
172 rwl
.readLock().lock();
174 return childStart
[index
];
176 rwl
.readLock().unlock();
181 * Get the start time of the latest (right-most) child node.
183 * @return The start time of the latest child
185 public long getLatestChildStart() {
186 rwl
.readLock().lock();
188 return childStart
[nbChildren
- 1];
190 rwl
.readLock().unlock();
195 * Get the sequence number of the extension to this node (if there is one).
197 * @return The sequence number of the extended node. '-1' is returned if
198 * there is no extension node.
200 public int getExtensionSequenceNumber() {
205 * Tell this node that it has a new child (Congrats!)
208 * The SHTNode object of the new child
210 public void linkNewChild(HTNode childNode
) {
211 rwl
.writeLock().lock();
213 assert (nbChildren
< getConfig().getMaxChildren());
215 children
[nbChildren
] = childNode
.getSequenceNumber();
216 childStart
[nbChildren
] = childNode
.getNodeStart();
220 rwl
.writeLock().unlock();
225 public NodeType
getNodeType() {
226 return NodeType
.CORE
;
230 protected int getSpecificHeaderSize() {
231 int maxChildren
= getConfig().getMaxChildren();
233 Integer
.BYTES
/* 1x int (extension node) */
234 + Integer
.BYTES
/* 1x int (nbChildren) */
236 /* MAX_NB * int ('children' table) */
237 + Integer
.BYTES
* maxChildren
239 /* MAX_NB * Timevalue ('childStart' table) */
240 + Long
.BYTES
* maxChildren
;
246 public String
toStringSpecific() {
247 /* Only used for debugging, shouldn't be externalized */
248 return String
.format("Core Node, %d children %s", //$NON-NLS-1$
249 nbChildren
, Arrays
.toString(Arrays
.copyOf(children
, nbChildren
)));