Commit | Line | Data |
---|---|---|
a52fde77 | 1 | /******************************************************************************* |
bb7f92ce | 2 | * Copyright (c) 2010, 2014 Ericsson, École Polytechnique de Montréal, and others |
cb42195c | 3 | * |
a52fde77 AM |
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 | |
cb42195c | 8 | * |
bb7f92ce FW |
9 | * Contributors: |
10 | * Alexandre Montplaisir - Initial API and implementation | |
11 | * Florian Wininger - Add Extension and Leaf Node | |
a52fde77 AM |
12 | *******************************************************************************/ |
13 | ||
e894a508 | 14 | package org.eclipse.tracecompass.internal.statesystem.core.backend.historytree; |
a52fde77 AM |
15 | |
16 | import java.nio.ByteBuffer; | |
62197b87 | 17 | import java.util.concurrent.locks.ReentrantReadWriteLock; |
a52fde77 AM |
18 | |
19 | /** | |
20 | * A Core node is a first-level node of a History Tree which is not a leaf node. | |
cb42195c | 21 | * |
a52fde77 | 22 | * It extends HTNode by adding support for child nodes, and also extensions. |
cb42195c | 23 | * |
ffd0aa67 | 24 | * @author Alexandre Montplaisir |
a52fde77 | 25 | */ |
bb7f92ce | 26 | public final class CoreNode extends HTNode { |
a52fde77 | 27 | |
cb42195c AM |
28 | /** Number of bytes in a int */ |
29 | private static final int SIZE_INT = 4; | |
30 | ||
31 | /** Number of bytes in a long */ | |
32 | private static final int SIZE_LONG = 8; | |
33 | ||
34 | /** Nb. of children this node has */ | |
a52fde77 AM |
35 | private int nbChildren; |
36 | ||
cb42195c | 37 | /** Seq. numbers of the children nodes (size = MAX_NB_CHILDREN) */ |
a52fde77 AM |
38 | private int[] children; |
39 | ||
cb42195c | 40 | /** Start times of each of the children (size = MAX_NB_CHILDREN) */ |
a52fde77 AM |
41 | private long[] childStart; |
42 | ||
cb42195c | 43 | /** Seq number of this node's extension. -1 if none */ |
62197b87 AM |
44 | private volatile int extension = -1; |
45 | ||
46 | /** | |
47 | * Lock used to gate the accesses to the children arrays. Meant to be a | |
48 | * different lock from the one in {@link HTNode}. | |
49 | */ | |
50 | private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(false); | |
a52fde77 AM |
51 | |
52 | /** | |
53 | * Initial constructor. Use this to initialize a new EMPTY node. | |
cb42195c | 54 | * |
ffd0aa67 EB |
55 | * @param config |
56 | * Configuration of the History Tree | |
a52fde77 AM |
57 | * @param seqNumber |
58 | * The (unique) sequence number assigned to this particular node | |
59 | * @param parentSeqNumber | |
60 | * The sequence number of this node's parent node | |
61 | * @param start | |
62 | * The earliest timestamp stored in this node | |
63 | */ | |
bb7f92ce | 64 | public CoreNode(HTConfig config, int seqNumber, int parentSeqNumber, |
a52fde77 | 65 | long start) { |
ffd0aa67 | 66 | super(config, seqNumber, parentSeqNumber, start); |
a52fde77 | 67 | this.nbChildren = 0; |
ffd0aa67 | 68 | int size = config.getMaxChildren(); |
a52fde77 AM |
69 | |
70 | /* | |
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 | |
74 | * those tables. | |
75 | */ | |
cb42195c AM |
76 | this.children = new int[size]; |
77 | this.childStart = new long[size]; | |
a52fde77 AM |
78 | } |
79 | ||
80 | @Override | |
62197b87 | 81 | protected void readSpecificHeader(ByteBuffer buffer) { |
ffd0aa67 | 82 | int size = getConfig().getMaxChildren(); |
a52fde77 AM |
83 | |
84 | extension = buffer.getInt(); | |
85 | nbChildren = buffer.getInt(); | |
86 | ||
cb42195c AM |
87 | children = new int[size]; |
88 | for (int i = 0; i < nbChildren; i++) { | |
a52fde77 AM |
89 | children[i] = buffer.getInt(); |
90 | } | |
cb42195c | 91 | for (int i = nbChildren; i < size; i++) { |
a52fde77 AM |
92 | buffer.getInt(); |
93 | } | |
94 | ||
cb42195c AM |
95 | this.childStart = new long[size]; |
96 | for (int i = 0; i < nbChildren; i++) { | |
a52fde77 AM |
97 | childStart[i] = buffer.getLong(); |
98 | } | |
cb42195c | 99 | for (int i = nbChildren; i < size; i++) { |
a52fde77 AM |
100 | buffer.getLong(); |
101 | } | |
102 | } | |
103 | ||
104 | @Override | |
62197b87 | 105 | protected void writeSpecificHeader(ByteBuffer buffer) { |
ffd0aa67 | 106 | int size = getConfig().getMaxChildren(); |
a52fde77 AM |
107 | |
108 | buffer.putInt(extension); | |
109 | buffer.putInt(nbChildren); | |
110 | ||
111 | /* Write the "children's seq number" array */ | |
cb42195c | 112 | for (int i = 0; i < nbChildren; i++) { |
a52fde77 AM |
113 | buffer.putInt(children[i]); |
114 | } | |
cb42195c | 115 | for (int i = nbChildren; i < size; i++) { |
a52fde77 AM |
116 | buffer.putInt(0); |
117 | } | |
118 | ||
119 | /* Write the "children's start times" array */ | |
cb42195c | 120 | for (int i = 0; i < nbChildren; i++) { |
a52fde77 AM |
121 | buffer.putLong(childStart[i]); |
122 | } | |
cb42195c | 123 | for (int i = nbChildren; i < size; i++) { |
a52fde77 AM |
124 | buffer.putLong(0); |
125 | } | |
126 | } | |
127 | ||
8d47cc34 AM |
128 | /** |
129 | * Return the number of child nodes this node has. | |
130 | * | |
131 | * @return The number of child nodes | |
132 | */ | |
133 | public int getNbChildren() { | |
62197b87 AM |
134 | rwl.readLock().lock(); |
135 | int ret = nbChildren; | |
136 | rwl.readLock().unlock(); | |
137 | return ret; | |
a52fde77 AM |
138 | } |
139 | ||
8d47cc34 AM |
140 | /** |
141 | * Get the child node corresponding to the specified index | |
142 | * | |
143 | * @param index The index of the child to lookup | |
144 | * @return The child node | |
145 | */ | |
146 | public int getChild(int index) { | |
62197b87 AM |
147 | rwl.readLock().lock(); |
148 | try { | |
149 | return children[index]; | |
150 | } finally { | |
151 | rwl.readLock().unlock(); | |
152 | } | |
a52fde77 AM |
153 | } |
154 | ||
8d47cc34 AM |
155 | /** |
156 | * Get the latest (right-most) child node of this node. | |
157 | * | |
158 | * @return The latest child node | |
159 | */ | |
160 | public int getLatestChild() { | |
62197b87 AM |
161 | rwl.readLock().lock(); |
162 | try { | |
163 | return children[nbChildren - 1]; | |
164 | } finally { | |
165 | rwl.readLock().unlock(); | |
166 | } | |
a52fde77 AM |
167 | } |
168 | ||
8d47cc34 AM |
169 | /** |
170 | * Get the start time of the specified child node. | |
171 | * | |
172 | * @param index | |
173 | * The index of the child node | |
174 | * @return The start time of the that child node. | |
175 | */ | |
176 | public long getChildStart(int index) { | |
62197b87 AM |
177 | rwl.readLock().lock(); |
178 | try { | |
179 | return childStart[index]; | |
180 | } finally { | |
181 | rwl.readLock().unlock(); | |
182 | } | |
a52fde77 AM |
183 | } |
184 | ||
8d47cc34 AM |
185 | /** |
186 | * Get the start time of the latest (right-most) child node. | |
187 | * | |
188 | * @return The start time of the latest child | |
189 | */ | |
190 | public long getLatestChildStart() { | |
62197b87 AM |
191 | rwl.readLock().lock(); |
192 | try { | |
193 | return childStart[nbChildren - 1]; | |
194 | } finally { | |
195 | rwl.readLock().unlock(); | |
196 | } | |
a52fde77 AM |
197 | } |
198 | ||
8d47cc34 AM |
199 | /** |
200 | * Get the sequence number of the extension to this node (if there is one). | |
201 | * | |
202 | * @return The sequence number of the extended node. '-1' is returned if | |
203 | * there is no extension node. | |
204 | */ | |
205 | public int getExtensionSequenceNumber() { | |
a52fde77 AM |
206 | return extension; |
207 | } | |
208 | ||
209 | /** | |
210 | * Tell this node that it has a new child (Congrats!) | |
cb42195c | 211 | * |
a52fde77 AM |
212 | * @param childNode |
213 | * The SHTNode object of the new child | |
214 | */ | |
bb7f92ce | 215 | public void linkNewChild(HTNode childNode) { |
62197b87 AM |
216 | rwl.writeLock().lock(); |
217 | try { | |
218 | assert (nbChildren < getConfig().getMaxChildren()); | |
a52fde77 | 219 | |
62197b87 AM |
220 | children[nbChildren] = childNode.getSequenceNumber(); |
221 | childStart[nbChildren] = childNode.getNodeStart(); | |
222 | nbChildren++; | |
223 | ||
224 | } finally { | |
225 | rwl.writeLock().unlock(); | |
226 | } | |
a52fde77 AM |
227 | } |
228 | ||
229 | @Override | |
bb7f92ce FW |
230 | public NodeType getNodeType() { |
231 | return NodeType.CORE; | |
a52fde77 AM |
232 | } |
233 | ||
234 | @Override | |
62197b87 | 235 | protected int getSpecificHeaderSize() { |
ffd0aa67 | 236 | int maxChildren = getConfig().getMaxChildren(); |
cb42195c AM |
237 | int specificSize = |
238 | SIZE_INT /* 1x int (extension node) */ | |
239 | + SIZE_INT /* 1x int (nbChildren) */ | |
a52fde77 AM |
240 | |
241 | /* MAX_NB * int ('children' table) */ | |
cb42195c | 242 | + SIZE_INT * maxChildren |
a52fde77 AM |
243 | |
244 | /* MAX_NB * Timevalue ('childStart' table) */ | |
cb42195c | 245 | + SIZE_LONG * maxChildren; |
a52fde77 | 246 | |
62197b87 | 247 | return specificSize; |
a52fde77 AM |
248 | } |
249 | ||
250 | @Override | |
8d47cc34 | 251 | public String toStringSpecific() { |
a52fde77 AM |
252 | /* Only used for debugging, shouldn't be externalized */ |
253 | return "Core Node, " + nbChildren + " children, "; //$NON-NLS-1$ //$NON-NLS-2$ | |
254 | } | |
255 | ||
256 | } |