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