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