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
.classic
;
16 import java
.nio
.ByteBuffer
;
17 import java
.util
.Arrays
;
18 import java
.util
.concurrent
.locks
.ReentrantReadWriteLock
;
20 import org
.eclipse
.tracecompass
.internal
.statesystem
.core
.backend
.historytree
.HTConfig
;
21 import org
.eclipse
.tracecompass
.internal
.statesystem
.core
.backend
.historytree
.HTNode
;
22 import org
.eclipse
.tracecompass
.internal
.statesystem
.core
.backend
.historytree
.ParentNode
;
25 * A Core node is a first-level node of a History Tree which is not a leaf node.
27 * It extends HTNode by adding support for child nodes, and also extensions.
29 * @author Alexandre Montplaisir
31 public final class CoreNode
extends ParentNode
{
33 /** Nb. of children this node has */
34 private int nbChildren
;
36 /** Seq. numbers of the children nodes (size = MAX_NB_CHILDREN) */
37 private int[] children
;
39 /** Start times of each of the children (size = MAX_NB_CHILDREN) */
40 private long[] childStart
;
42 /** Seq number of this node's extension. -1 if none */
43 private volatile int extension
= -1;
46 * Lock used to gate the accesses to the children arrays. Meant to be a
47 * different lock from the one in {@link HTNode}.
49 private final ReentrantReadWriteLock rwl
= new ReentrantReadWriteLock(false);
52 * Initial constructor. Use this to initialize a new EMPTY node.
55 * Configuration of the History Tree
57 * The (unique) sequence number assigned to this particular node
58 * @param parentSeqNumber
59 * The sequence number of this node's parent node
61 * The earliest timestamp stored in this node
63 public CoreNode(HTConfig config
, int seqNumber
, int parentSeqNumber
,
65 super(config
, seqNumber
, parentSeqNumber
, start
);
67 int size
= config
.getMaxChildren();
70 * We instantiate the two following arrays at full size right away,
71 * since we want to reserve that space in the node's header.
72 * "this.nbChildren" will tell us how many relevant entries there are in
75 this.children
= new int[size
];
76 this.childStart
= new long[size
];
80 protected void readSpecificHeader(ByteBuffer buffer
) {
81 int size
= getConfig().getMaxChildren();
83 extension
= buffer
.getInt();
84 nbChildren
= buffer
.getInt();
86 children
= new int[size
];
87 for (int i
= 0; i
< nbChildren
; i
++) {
88 children
[i
] = buffer
.getInt();
90 for (int i
= nbChildren
; i
< size
; i
++) {
94 this.childStart
= new long[size
];
95 for (int i
= 0; i
< nbChildren
; i
++) {
96 childStart
[i
] = buffer
.getLong();
98 for (int i
= nbChildren
; i
< size
; i
++) {
104 protected void writeSpecificHeader(ByteBuffer buffer
) {
105 int size
= getConfig().getMaxChildren();
107 buffer
.putInt(extension
);
108 buffer
.putInt(nbChildren
);
110 /* Write the "children's seq number" array */
111 for (int i
= 0; i
< nbChildren
; i
++) {
112 buffer
.putInt(children
[i
]);
114 for (int i
= nbChildren
; i
< size
; i
++) {
118 /* Write the "children's start times" array */
119 for (int i
= 0; i
< nbChildren
; i
++) {
120 buffer
.putLong(childStart
[i
]);
122 for (int i
= nbChildren
; i
< size
; i
++) {
128 public int getNbChildren() {
129 rwl
.readLock().lock();
130 int ret
= nbChildren
;
131 rwl
.readLock().unlock();
136 public int getChild(int index
) {
137 rwl
.readLock().lock();
139 return children
[index
];
141 rwl
.readLock().unlock();
146 public int getLatestChild() {
147 rwl
.readLock().lock();
149 return children
[nbChildren
- 1];
151 rwl
.readLock().unlock();
156 public long getChildStart(int index
) {
157 rwl
.readLock().lock();
159 return childStart
[index
];
161 rwl
.readLock().unlock();
166 public long getLatestChildStart() {
167 rwl
.readLock().lock();
169 return childStart
[nbChildren
- 1];
171 rwl
.readLock().unlock();
176 * Get the sequence number of the extension to this node (if there is one).
178 * @return The sequence number of the extended node. '-1' is returned if
179 * there is no extension node.
181 public int getExtensionSequenceNumber() {
186 * Tell this node that it has a new child (Congrats!)
189 * The SHTNode object of the new child
192 public void linkNewChild(HTNode childNode
) {
193 rwl
.writeLock().lock();
195 if (nbChildren
>= getConfig().getMaxChildren()) {
196 throw new IllegalStateException("Asked to link another child but parent already has maximum number of children"); //$NON-NLS-1$
199 children
[nbChildren
] = childNode
.getSequenceNumber();
200 childStart
[nbChildren
] = childNode
.getNodeStart();
204 rwl
.writeLock().unlock();
209 public NodeType
getNodeType() {
210 return NodeType
.CORE
;
214 protected int getSpecificHeaderSize() {
215 int maxChildren
= getConfig().getMaxChildren();
217 Integer
.BYTES
/* 1x int (extension node) */
218 + Integer
.BYTES
/* 1x int (nbChildren) */
220 /* MAX_NB * int ('children' table) */
221 + Integer
.BYTES
* maxChildren
223 /* MAX_NB * Timevalue ('childStart' table) */
224 + Long
.BYTES
* maxChildren
;
230 public String
toStringSpecific() {
231 /* Only used for debugging, shouldn't be externalized */
232 return String
.format("Core Node, %d children %s", //$NON-NLS-1$
233 nbChildren
, Arrays
.toString(Arrays
.copyOf(children
, nbChildren
)));