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
.Collection
;
19 import java
.util
.Collections
;
20 import java
.util
.concurrent
.locks
.ReentrantReadWriteLock
;
22 import org
.eclipse
.tracecompass
.internal
.statesystem
.core
.backend
.historytree
.HTConfig
;
23 import org
.eclipse
.tracecompass
.internal
.statesystem
.core
.backend
.historytree
.HTNode
;
24 import org
.eclipse
.tracecompass
.internal
.statesystem
.core
.backend
.historytree
.ParentNode
;
25 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
28 * A Core node is a first-level node of a History Tree which is not a leaf node.
30 * It extends HTNode by adding support for child nodes, and also extensions.
32 * @author Alexandre Montplaisir
34 public final class CoreNode
extends ParentNode
{
36 /** Nb. of children this node has */
37 private int nbChildren
;
39 /** Seq. numbers of the children nodes (size = MAX_NB_CHILDREN) */
40 private int[] children
;
42 /** Start times of each of the children (size = MAX_NB_CHILDREN) */
43 private long[] childStart
;
45 /** Seq number of this node's extension. -1 if none */
46 private volatile int extension
= -1;
49 * Lock used to gate the accesses to the children arrays. Meant to be a
50 * different lock from the one in {@link HTNode}.
52 private final ReentrantReadWriteLock rwl
= new ReentrantReadWriteLock(false);
55 * Initial constructor. Use this to initialize a new EMPTY node.
58 * Configuration of the History Tree
60 * The (unique) sequence number assigned to this particular node
61 * @param parentSeqNumber
62 * The sequence number of this node's parent node
64 * The earliest timestamp stored in this node
66 public CoreNode(HTConfig config
, int seqNumber
, int parentSeqNumber
,
68 super(config
, seqNumber
, parentSeqNumber
, start
);
70 int size
= config
.getMaxChildren();
73 * We instantiate the two following arrays at full size right away,
74 * since we want to reserve that space in the node's header.
75 * "this.nbChildren" will tell us how many relevant entries there are in
78 this.children
= new int[size
];
79 this.childStart
= new long[size
];
83 protected void readSpecificHeader(ByteBuffer buffer
) {
84 int size
= getConfig().getMaxChildren();
86 extension
= buffer
.getInt();
87 nbChildren
= buffer
.getInt();
89 children
= new int[size
];
90 for (int i
= 0; i
< nbChildren
; i
++) {
91 children
[i
] = buffer
.getInt();
93 for (int i
= nbChildren
; i
< size
; i
++) {
97 this.childStart
= new long[size
];
98 for (int i
= 0; i
< nbChildren
; i
++) {
99 childStart
[i
] = buffer
.getLong();
101 for (int i
= nbChildren
; i
< size
; i
++) {
107 protected void writeSpecificHeader(ByteBuffer buffer
) {
108 int size
= getConfig().getMaxChildren();
110 buffer
.putInt(extension
);
111 buffer
.putInt(nbChildren
);
113 /* Write the "children's seq number" array */
114 for (int i
= 0; i
< nbChildren
; i
++) {
115 buffer
.putInt(children
[i
]);
117 for (int i
= nbChildren
; i
< size
; i
++) {
121 /* Write the "children's start times" array */
122 for (int i
= 0; i
< nbChildren
; i
++) {
123 buffer
.putLong(childStart
[i
]);
125 for (int i
= nbChildren
; i
< size
; i
++) {
131 public int getNbChildren() {
132 rwl
.readLock().lock();
136 rwl
.readLock().unlock();
141 public int getChild(int index
) {
142 rwl
.readLock().lock();
144 return children
[index
];
146 rwl
.readLock().unlock();
151 public int getLatestChild() {
152 rwl
.readLock().lock();
154 return children
[nbChildren
- 1];
156 rwl
.readLock().unlock();
161 public long getChildStart(int index
) {
162 rwl
.readLock().lock();
164 return childStart
[index
];
166 rwl
.readLock().unlock();
171 * Get the sequence number of the extension to this node (if there is one).
173 * @return The sequence number of the extended node. '-1' is returned if
174 * there is no extension node.
176 public int getExtensionSequenceNumber() {
177 rwl
.readLock().lock();
181 rwl
.readLock().unlock();
186 public void linkNewChild(HTNode childNode
) {
187 rwl
.writeLock().lock();
189 if (nbChildren
>= getConfig().getMaxChildren()) {
190 throw new IllegalStateException("Asked to link another child but parent already has maximum number of children"); //$NON-NLS-1$
193 children
[nbChildren
] = childNode
.getSequenceNumber();
194 childStart
[nbChildren
] = childNode
.getNodeStart();
198 rwl
.writeLock().unlock();
203 public Collection
<Integer
> selectNextChildren(long t
) throws TimeRangeException
{
204 if (t
< getNodeStart() || (isOnDisk() && t
> getNodeEnd())) {
205 throw new TimeRangeException("Requesting children outside the node's range: " + t
); //$NON-NLS-1$
207 rwl
.readLock().lock();
209 int potentialNextSeqNb
= -1;
210 for (int i
= 0; i
< nbChildren
; i
++) {
211 if (t
>= childStart
[i
]) {
212 potentialNextSeqNb
= children
[i
];
218 if (potentialNextSeqNb
== -1) {
219 throw new IllegalStateException("No next child node found"); //$NON-NLS-1$
221 return Collections
.singleton(potentialNextSeqNb
);
223 rwl
.readLock().unlock();
228 public NodeType
getNodeType() {
229 return NodeType
.CORE
;
233 protected int getSpecificHeaderSize() {
234 int maxChildren
= getConfig().getMaxChildren();
236 Integer
.BYTES
/* 1x int (extension node) */
237 + Integer
.BYTES
/* 1x int (nbChildren) */
239 /* MAX_NB * int ('children' table) */
240 + Integer
.BYTES
* maxChildren
242 /* MAX_NB * Timevalue ('childStart' table) */
243 + Long
.BYTES
* maxChildren
;
249 public String
toStringSpecific() {
250 /* Only used for debugging, shouldn't be externalized */
251 return String
.format("Core Node, %d children %s", //$NON-NLS-1$
252 nbChildren
, Arrays
.toString(Arrays
.copyOf(children
, nbChildren
)));