tmf.ui: make methods called by constructor private
[deliverable/tracecompass.git] / org.eclipse.tracecompass.statesystem.core / src / org / eclipse / tracecompass / internal / statesystem / core / AttributeTree.java
CommitLineData
a52fde77 1/*******************************************************************************
e13bd4cd 2 * Copyright (c) 2012, 2015 Ericsson
a52fde77
AM
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
8d1346f0 5 *
a52fde77
AM
6 * All rights reserved. This program and the accompanying materials are
7 * made available under the terms of the Eclipse Public License v1.0 which
8 * accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
8d1346f0 10 *
e13bd4cd
PT
11 * Contributors:
12 * Alexandre Montplaisir - Initial API and implementation
13 * Patrick Tasse - Add message to exceptions
a52fde77
AM
14 *******************************************************************************/
15
e894a508 16package org.eclipse.tracecompass.internal.statesystem.core;
a52fde77 17
04927a83
AM
18import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
19
085a78a8
AM
20import java.io.BufferedInputStream;
21import java.io.DataInputStream;
22import java.io.File;
23import java.io.FileInputStream;
24import java.io.IOException;
25import java.io.PrintWriter;
26import java.io.RandomAccessFile;
a52fde77
AM
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.Collections;
30import java.util.List;
31
50a47aa6 32import org.eclipse.jdt.annotation.NonNull;
e894a508 33import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
6d08acca 34
a52fde77
AM
35/**
36 * The Attribute Tree is the /proc-like filesystem used to organize attributes.
37 * Each node of this tree is both like a file and a directory in the
38 * "file system".
8d1346f0 39 *
a52fde77 40 * @author alexmont
8d1346f0 41 *
a52fde77 42 */
cb42195c 43public final class AttributeTree {
a52fde77
AM
44
45 /* "Magic number" for attribute tree files or file sections */
cb42195c 46 private static final int ATTRIB_TREE_MAGIC_NUMBER = 0x06EC3671;
a52fde77
AM
47
48 private final StateSystem ss;
49 private final List<Attribute> attributeList;
50 private final Attribute attributeTreeRoot;
51
52 /**
53 * Standard constructor, create a new empty Attribute Tree
8d1346f0 54 *
a52fde77
AM
55 * @param ss
56 * The StateSystem to which this AT is attached
57 */
a6917276 58 public AttributeTree(StateSystem ss) {
a52fde77
AM
59 this.ss = ss;
60 this.attributeList = Collections.synchronizedList(new ArrayList<Attribute>());
c3f21a07 61 this.attributeTreeRoot = new Attribute(null, "root", -1); //$NON-NLS-1$
a52fde77
AM
62 }
63
64 /**
6f04e06c
EB
65 * "Existing file" constructor. Builds an attribute tree from a
66 * "mapping file" or mapping section previously saved somewhere.
8d1346f0 67 *
a52fde77
AM
68 * @param ss
69 * StateSystem to which this AT is attached
70 * @param fis
71 * File stream where to read the AT information. Make sure it's
6f04e06c 72 * sought at the right place!
a52fde77 73 * @throws IOException
a6917276 74 * If there is a problem reading from the file stream
a52fde77 75 */
a6917276 76 public AttributeTree(StateSystem ss, FileInputStream fis) throws IOException {
a52fde77
AM
77 this(ss);
78 DataInputStream in = new DataInputStream(new BufferedInputStream(fis));
79
80 /* Message for exceptions, shouldn't be externalized */
81 final String errorMessage = "The attribute tree file section is either invalid or corrupted."; //$NON-NLS-1$
0a9de3d2 82
a4524c1b 83 ArrayList<String[]> list = new ArrayList<>();
a52fde77
AM
84 byte[] curByteArray;
85 String curFullString;
86 String[] curStringArray;
87 int res, remain, size;
88 int expectedSize = 0;
89 int total = 0;
90
91 /* Read the header of the Attribute Tree file (or file section) */
92 res = in.readInt(); /* Magic number */
93 if (res != ATTRIB_TREE_MAGIC_NUMBER) {
94 throw new IOException(errorMessage);
95 }
96
97 /* Expected size of the section */
98 expectedSize = in.readInt();
fe8b47b1 99 if (expectedSize < 12) {
a52fde77
AM
100 throw new IOException(errorMessage);
101 }
102
103 /* How many entries we have to read */
104 remain = in.readInt();
105 total += 12;
106
107 /* Read each entry */
108 for (; remain > 0; remain--) {
109 /* Read the first byte = the size of the entry */
110 size = in.readByte();
111 curByteArray = new byte[size];
ab604305
AM
112 res = in.read(curByteArray);
113 if (res != size) {
114 throw new IOException(errorMessage);
115 }
a52fde77
AM
116
117 /*
118 * Go buffer -> byteArray -> String -> String[] -> insert in list.
119 * bleh
120 */
121 curFullString = new String(curByteArray);
122 curStringArray = curFullString.split("/"); //$NON-NLS-1$
123 list.add(curStringArray);
124
125 /* Read the 0'ed confirmation byte */
126 res = in.readByte();
127 if (res != 0) {
128 throw new IOException(errorMessage);
129 }
130 total += curByteArray.length + 2;
131 }
132
133 if (total != expectedSize) {
134 throw new IOException(errorMessage);
135 }
136
137 /*
138 * Now we have 'list', the ArrayList of String arrays representing all
139 * the attributes. Simply create attributes the normal way from them.
140 */
141 for (String[] attrib : list) {
142 this.getQuarkAndAdd(-1, attrib);
143 }
144 }
145
146 /**
a6917276 147 * Tell the Attribute Tree to write itself somewhere in a file.
8d1346f0 148 *
a6917276
AM
149 * @param file
150 * The file to write to
151 * @param pos
152 * The position (in bytes) in the file where to write
a52fde77
AM
153 * @return The total number of bytes written.
154 */
a6917276 155 public int writeSelf(File file, long pos) {
a52fde77
AM
156 int total = 0;
157 byte[] curByteArray;
158
a4524c1b 159 try (RandomAccessFile raf = new RandomAccessFile(file, "rw");) { //$NON-NLS-1$
a52fde77
AM
160 raf.seek(pos);
161
162 /* Write the almost-magic number */
163 raf.writeInt(ATTRIB_TREE_MAGIC_NUMBER);
164
165 /* Placeholder for the total size of the section... */
166 raf.writeInt(-8000);
167
168 /* Write the number of entries */
169 raf.writeInt(this.attributeList.size());
170 total += 12;
171
172 /* Write the attributes themselves */
173 for (Attribute entry : this.attributeList) {
174 curByteArray = entry.getFullAttributeName().getBytes();
175 if (curByteArray.length > Byte.MAX_VALUE) {
176 throw new IOException("Attribute with name \"" //$NON-NLS-1$
177 + Arrays.toString(curByteArray) + "\" is too long."); //$NON-NLS-1$
178 }
179 /* Write the first byte = size of the array */
180 raf.writeByte((byte) curByteArray.length);
181
182 /* Write the array itself */
183 raf.write(curByteArray);
184
185 /* Write the 0'ed byte */
186 raf.writeByte((byte) 0);
187
188 total += curByteArray.length + 2;
189 }
190
191 /* Now go back and write the actual size of this section */
192 raf.seek(pos + 4);
193 raf.writeInt(total);
194
a52fde77
AM
195 } catch (IOException e) {
196 e.printStackTrace();
197 }
198 return total;
199 }
200
201 /**
202 * Return the number of attributes this system as seen so far. Note that
203 * this also equals the integer value (quark) the next added attribute will
204 * have.
8d1346f0 205 *
a6917276 206 * @return The current number of attributes in the tree
a52fde77 207 */
a6917276 208 public int getNbAttributes() {
a52fde77
AM
209 return attributeList.size();
210 }
211
212 /**
a6917276
AM
213 * Get the quark for a given attribute path. No new attribute will be
214 * created : if the specified path does not exist, throw an error.
8d1346f0 215 *
a6917276
AM
216 * @param startingNodeQuark
217 * The quark of the attribute from which relative queries will
218 * start. Use '-1' to start at the root node.
219 * @param subPath
220 * The path to the attribute, relative to the starting node.
221 * @return The quark of the specified attribute
a52fde77 222 * @throws AttributeNotFoundException
a6917276 223 * If the specified path was not found
a52fde77 224 */
a6917276 225 public int getQuarkDontAdd(int startingNodeQuark, String... subPath)
a52fde77 226 throws AttributeNotFoundException {
a52fde77
AM
227 assert (startingNodeQuark >= -1);
228
229 Attribute prevNode;
230
6abc2d88
AM
231 /* If subPath is empty, simply return the starting quark */
232 if (subPath == null || subPath.length == 0) {
233 return startingNodeQuark;
234 }
235
a52fde77
AM
236 /* Get the "starting node" */
237 if (startingNodeQuark == -1) {
238 prevNode = attributeTreeRoot;
239 } else {
240 prevNode = attributeList.get(startingNodeQuark);
241 }
242
243 int knownQuark = prevNode.getSubAttributeQuark(subPath);
244 if (knownQuark == -1) {
245 /*
246 * The attribute doesn't exist, but we have been specified to NOT
247 * add any new attributes.
248 */
e13bd4cd 249 throw new AttributeNotFoundException(ss.getSSID() + " Quark:" + startingNodeQuark + ", SubPath:" + Arrays.toString(subPath)); //$NON-NLS-1$ //$NON-NLS-2$
a52fde77
AM
250 }
251 /*
252 * The attribute was already existing, return the quark of that
253 * attribute
254 */
255 return knownQuark;
256 }
257
a6917276
AM
258 /**
259 * Get the quark of a given attribute path. If that specified path does not
260 * exist, it will be created (and the quark that was just created will be
261 * returned).
262 *
263 * @param startingNodeQuark
264 * The quark of the attribute from which relative queries will
265 * start. Use '-1' to start at the root node.
266 * @param subPath
267 * The path to the attribute, relative to the starting node.
268 * @return The quark of the attribute represented by the path
269 */
270 public synchronized int getQuarkAndAdd(int startingNodeQuark, String... subPath) {
271 // FIXME synchronized here is probably quite costly... maybe only locking
272 // the "for" would be enough?
a52fde77
AM
273 assert (subPath != null && subPath.length > 0);
274 assert (startingNodeQuark >= -1);
275
276 Attribute nextNode = null;
277 Attribute prevNode;
278
279 /* Get the "starting node" */
280 if (startingNodeQuark == -1) {
281 prevNode = attributeTreeRoot;
282 } else {
283 prevNode = attributeList.get(startingNodeQuark);
284 }
285
286 int knownQuark = prevNode.getSubAttributeQuark(subPath);
287 if (knownQuark == -1) {
288 /*
289 * The attribute was not in the table previously, and we want to add
290 * it
291 */
292 for (String curDirectory : subPath) {
293 nextNode = prevNode.getSubAttributeNode(curDirectory);
294 if (nextNode == null) {
295 /* This is where we need to start adding */
04927a83 296 nextNode = new Attribute(prevNode, checkNotNull(curDirectory), attributeList.size());
a52fde77
AM
297 prevNode.addSubAttribute(nextNode);
298 attributeList.add(nextNode);
8d1346f0 299 ss.addEmptyAttribute();
a52fde77
AM
300 }
301 prevNode = nextNode;
302 }
085a78a8 303 return attributeList.size() - 1;
a52fde77
AM
304 }
305 /*
306 * The attribute was already existing, return the quark of that
307 * attribute
308 */
309 return knownQuark;
310 }
311
0a9de3d2
AM
312 /**
313 * Returns the sub-attributes of the quark passed in parameter
8d1346f0 314 *
0a9de3d2 315 * @param attributeQuark
a6917276 316 * The quark of the attribute to print the sub-attributes of.
c66426fd 317 * @param recursive
a6917276
AM
318 * Should the query be recursive or not? If false, only children
319 * one level deep will be returned. If true, all descendants will
320 * be returned (depth-first search)
321 * @return The list of quarks representing the children attributes
0a9de3d2 322 * @throws AttributeNotFoundException
a6917276
AM
323 * If 'attributeQuark' is invalid, or if there is no attrbiute
324 * associated to it.
0a9de3d2 325 */
50a47aa6 326 public @NonNull List<Integer> getSubAttributes(int attributeQuark, boolean recursive)
0a9de3d2 327 throws AttributeNotFoundException {
a4524c1b 328 List<Integer> listOfChildren = new ArrayList<>();
0a9de3d2 329 Attribute startingAttribute;
c66426fd 330
0a9de3d2 331 /* Check if the quark is valid */
f94a0bac 332 if (attributeQuark < -1 || attributeQuark >= attributeList.size()) {
e13bd4cd 333 throw new AttributeNotFoundException(ss.getSSID() + " Quark:" + attributeQuark); //$NON-NLS-1$
0a9de3d2 334 }
c66426fd 335
0a9de3d2 336 /* Set up the node from which we'll start the search */
c66426fd 337 if (attributeQuark == -1) {
0a9de3d2
AM
338 startingAttribute = attributeTreeRoot;
339 } else {
340 startingAttribute = attributeList.get(attributeQuark);
341 }
c66426fd 342
0a9de3d2 343 /* Iterate through the sub-attributes and add them to the list */
c66426fd 344 addSubAttributes(listOfChildren, startingAttribute, recursive);
0a9de3d2 345
a52fde77
AM
346 return listOfChildren;
347 }
348
0fdd2c45
FG
349 /**
350 * Returns the parent quark of the attribute. The root attribute has no
351 * parent and will return <code>-1</code>
352 *
353 * @param quark
354 * The quark of the attribute
355 * @return Quark of the parent attribute or <code>-1</code> for the root
356 * attribute
357 */
358 public int getParentAttributeQuark(int quark) {
359 if (quark == -1) {
360 return quark;
361 }
362 return attributeList.get(quark).getParentAttributeQuark();
363 }
364
c66426fd
AM
365 private void addSubAttributes(List<Integer> list, Attribute curAttribute,
366 boolean recursive) {
cb42195c 367 for (Attribute childNode : curAttribute.getSubAttributes()) {
c66426fd
AM
368 list.add(childNode.getQuark());
369 if (recursive) {
370 addSubAttributes(list, childNode, true);
371 }
372 }
373 }
374
a6917276
AM
375 /**
376 * Get then base name of an attribute specified by a quark.
377 *
378 * @param quark
379 * The quark of the attribute
380 * @return The (base) name of the attribute
381 */
04927a83 382 public @NonNull String getAttributeName(int quark) {
50678114
AM
383 return attributeList.get(quark).getName();
384 }
385
a6917276
AM
386 /**
387 * Get the full path name of an attribute specified by a quark.
388 *
389 * @param quark
390 * The quark of the attribute
391 * @return The full path name of the attribute
392 */
04927a83 393 public @NonNull String getFullAttributeName(int quark) {
a52fde77
AM
394 return attributeList.get(quark).getFullAttributeName();
395 }
396
34638411
AM
397 /**
398 * Get the full path name (as an array of path elements) of an attribute
399 * specified by a quark.
400 *
401 * @param quark
402 * The quark of the attribute
403 * @return The path elements of the full path
404 */
405 public @NonNull String[] getFullAttributePathArray(int quark) {
406 return attributeList.get(quark).getFullAttribute();
407 }
408
a6917276
AM
409 /**
410 * Debug-print all the attributes in the tree.
411 *
412 * @param writer
413 * The writer where to print the output
414 */
415 public void debugPrint(PrintWriter writer) {
a52fde77
AM
416 attributeTreeRoot.debugPrint(writer);
417 }
418
a6917276 419}
This page took 0.089721 seconds and 5 git commands to generate.