tmf RCP: Rename extracted folder of the trace viewer
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / internal / tmf / core / statesystem / AttributeTree.java
CommitLineData
a52fde77 1/*******************************************************************************
11252342 2 * Copyright (c) 2012, 2013 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 */
49 AttributeTree(StateSystem ss) {
50 this.ss = ss;
51 this.attributeList = Collections.synchronizedList(new ArrayList<Attribute>());
52 this.attributeTreeRoot = new AlphaNumAttribute(null, "root", -1); //$NON-NLS-1$
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
AM
64 * @throws IOException
65 */
66 AttributeTree(StateSystem ss, FileInputStream fis) throws IOException {
67 this(ss);
68 DataInputStream in = new DataInputStream(new BufferedInputStream(fis));
69
70 /* Message for exceptions, shouldn't be externalized */
71 final String errorMessage = "The attribute tree file section is either invalid or corrupted."; //$NON-NLS-1$
0a9de3d2 72
a4524c1b 73 ArrayList<String[]> list = new ArrayList<>();
a52fde77
AM
74 byte[] curByteArray;
75 String curFullString;
76 String[] curStringArray;
77 int res, remain, size;
78 int expectedSize = 0;
79 int total = 0;
80
81 /* Read the header of the Attribute Tree file (or file section) */
82 res = in.readInt(); /* Magic number */
83 if (res != ATTRIB_TREE_MAGIC_NUMBER) {
84 throw new IOException(errorMessage);
85 }
86
87 /* Expected size of the section */
88 expectedSize = in.readInt();
89 if (expectedSize <= 12) {
90 throw new IOException(errorMessage);
91 }
92
93 /* How many entries we have to read */
94 remain = in.readInt();
95 total += 12;
96
97 /* Read each entry */
98 for (; remain > 0; remain--) {
99 /* Read the first byte = the size of the entry */
100 size = in.readByte();
101 curByteArray = new byte[size];
ab604305
AM
102 res = in.read(curByteArray);
103 if (res != size) {
104 throw new IOException(errorMessage);
105 }
a52fde77
AM
106
107 /*
108 * Go buffer -> byteArray -> String -> String[] -> insert in list.
109 * bleh
110 */
111 curFullString = new String(curByteArray);
112 curStringArray = curFullString.split("/"); //$NON-NLS-1$
113 list.add(curStringArray);
114
115 /* Read the 0'ed confirmation byte */
116 res = in.readByte();
117 if (res != 0) {
118 throw new IOException(errorMessage);
119 }
120 total += curByteArray.length + 2;
121 }
122
123 if (total != expectedSize) {
124 throw new IOException(errorMessage);
125 }
126
127 /*
128 * Now we have 'list', the ArrayList of String arrays representing all
129 * the attributes. Simply create attributes the normal way from them.
130 */
131 for (String[] attrib : list) {
132 this.getQuarkAndAdd(-1, attrib);
133 }
134 }
135
136 /**
137 * Tell the Attribute Tree to write itself somewhere. The passed
138 * FileOutputStream defines where (which file/position).
8d1346f0 139 *
a52fde77 140 * @param fos
6f04e06c 141 * Where to write. Make sure it's sought at the right position
a52fde77
AM
142 * you want.
143 * @return The total number of bytes written.
144 */
145 int writeSelf(File file, long pos) {
a52fde77
AM
146 int total = 0;
147 byte[] curByteArray;
148
a4524c1b 149 try (RandomAccessFile raf = new RandomAccessFile(file, "rw");) { //$NON-NLS-1$
a52fde77
AM
150 raf.seek(pos);
151
152 /* Write the almost-magic number */
153 raf.writeInt(ATTRIB_TREE_MAGIC_NUMBER);
154
155 /* Placeholder for the total size of the section... */
156 raf.writeInt(-8000);
157
158 /* Write the number of entries */
159 raf.writeInt(this.attributeList.size());
160 total += 12;
161
162 /* Write the attributes themselves */
163 for (Attribute entry : this.attributeList) {
164 curByteArray = entry.getFullAttributeName().getBytes();
165 if (curByteArray.length > Byte.MAX_VALUE) {
166 throw new IOException("Attribute with name \"" //$NON-NLS-1$
167 + Arrays.toString(curByteArray) + "\" is too long."); //$NON-NLS-1$
168 }
169 /* Write the first byte = size of the array */
170 raf.writeByte((byte) curByteArray.length);
171
172 /* Write the array itself */
173 raf.write(curByteArray);
174
175 /* Write the 0'ed byte */
176 raf.writeByte((byte) 0);
177
178 total += curByteArray.length + 2;
179 }
180
181 /* Now go back and write the actual size of this section */
182 raf.seek(pos + 4);
183 raf.writeInt(total);
184
a52fde77
AM
185 } catch (IOException e) {
186 e.printStackTrace();
187 }
188 return total;
189 }
190
191 /**
192 * Return the number of attributes this system as seen so far. Note that
193 * this also equals the integer value (quark) the next added attribute will
194 * have.
8d1346f0 195 *
a52fde77
AM
196 * @return
197 */
198 int getNbAttributes() {
199 return attributeList.size();
200 }
201
202 /**
203 * This is the version to specifically add missing attributes.
8d1346f0 204 *
a52fde77
AM
205 * If 'numericalNode' is true, all the new attributes created will be of
206 * type 'NumericalNode' instead of 'AlphaNumNode'. Be careful with this, if
207 * you do not want ALL added attributes to be numerical, call this function
208 * first with 'false' to create the parent nodes, then call it again to make
209 * sure only the final node is numerical.
8d1346f0 210 *
a52fde77
AM
211 * @throws AttributeNotFoundException
212 */
213 int getQuarkDontAdd(int startingNodeQuark, String... subPath)
214 throws AttributeNotFoundException {
a52fde77
AM
215 assert (startingNodeQuark >= -1);
216
217 Attribute prevNode;
218
6abc2d88
AM
219 /* If subPath is empty, simply return the starting quark */
220 if (subPath == null || subPath.length == 0) {
221 return startingNodeQuark;
222 }
223
a52fde77
AM
224 /* Get the "starting node" */
225 if (startingNodeQuark == -1) {
226 prevNode = attributeTreeRoot;
227 } else {
228 prevNode = attributeList.get(startingNodeQuark);
229 }
230
231 int knownQuark = prevNode.getSubAttributeQuark(subPath);
232 if (knownQuark == -1) {
233 /*
234 * The attribute doesn't exist, but we have been specified to NOT
235 * add any new attributes.
236 */
237 throw new AttributeNotFoundException();
238 }
239 /*
240 * The attribute was already existing, return the quark of that
241 * attribute
242 */
243 return knownQuark;
244 }
245
246 // FIXME synchronized here is probably quite costly... maybe only locking
247 // the "for" would be enough?
248 synchronized int getQuarkAndAdd(int startingNodeQuark, String... subPath) {
249 assert (subPath != null && subPath.length > 0);
250 assert (startingNodeQuark >= -1);
251
252 Attribute nextNode = null;
253 Attribute prevNode;
254
255 /* Get the "starting node" */
256 if (startingNodeQuark == -1) {
257 prevNode = attributeTreeRoot;
258 } else {
259 prevNode = attributeList.get(startingNodeQuark);
260 }
261
262 int knownQuark = prevNode.getSubAttributeQuark(subPath);
263 if (knownQuark == -1) {
264 /*
265 * The attribute was not in the table previously, and we want to add
266 * it
267 */
268 for (String curDirectory : subPath) {
269 nextNode = prevNode.getSubAttributeNode(curDirectory);
270 if (nextNode == null) {
271 /* This is where we need to start adding */
272 nextNode = new AlphaNumAttribute(prevNode, curDirectory,
273 attributeList.size());
274 prevNode.addSubAttribute(nextNode);
275 attributeList.add(nextNode);
8d1346f0 276 ss.addEmptyAttribute();
a52fde77
AM
277 }
278 prevNode = nextNode;
279 }
25e43749
AM
280 /*
281 * Insert an initial null value for this attribute in the state
282 * system (in case the state provider doesn't set one).
283 */
284 final int newAttrib = attributeList.size() - 1;
285 try {
286 ss.modifyAttribute(ss.getStartTime(), TmfStateValue.nullValue(), newAttrib);
287 } catch (TimeRangeException e) {
288 /* Should not happen, we're inserting at ss's start time */
cb42195c 289 throw new IllegalStateException(e);
25e43749
AM
290 } catch (AttributeNotFoundException e) {
291 /* Should not happen, we just created this attribute! */
cb42195c 292 throw new IllegalStateException(e);
25e43749
AM
293 } catch (StateValueTypeException e) {
294 /* Should not happen, there is no existing state value, and the
295 * one we insert is a null value anyway. */
cb42195c 296 throw new IllegalStateException(e);
25e43749
AM
297 }
298
299 return newAttrib;
a52fde77
AM
300 }
301 /*
302 * The attribute was already existing, return the quark of that
303 * attribute
304 */
305 return knownQuark;
306 }
307
308 int getSubAttributesCount(int quark) {
cb42195c 309 return attributeList.get(quark).getSubAttributes().size();
a52fde77
AM
310 }
311
0a9de3d2
AM
312 /**
313 * Returns the sub-attributes of the quark passed in parameter
8d1346f0 314 *
0a9de3d2 315 * @param attributeQuark
c66426fd 316 * @param recursive
0a9de3d2
AM
317 * @return
318 * @throws AttributeNotFoundException
319 */
c66426fd 320 List<Integer> getSubAttributes(int attributeQuark, boolean recursive)
0a9de3d2 321 throws AttributeNotFoundException {
a4524c1b 322 List<Integer> listOfChildren = new ArrayList<>();
0a9de3d2 323 Attribute startingAttribute;
c66426fd 324
0a9de3d2 325 /* Check if the quark is valid */
f94a0bac 326 if (attributeQuark < -1 || attributeQuark >= attributeList.size()) {
0a9de3d2
AM
327 throw new AttributeNotFoundException();
328 }
c66426fd 329
0a9de3d2 330 /* Set up the node from which we'll start the search */
c66426fd 331 if (attributeQuark == -1) {
0a9de3d2
AM
332 startingAttribute = attributeTreeRoot;
333 } else {
334 startingAttribute = attributeList.get(attributeQuark);
335 }
c66426fd 336
0a9de3d2 337 /* Iterate through the sub-attributes and add them to the list */
c66426fd 338 addSubAttributes(listOfChildren, startingAttribute, recursive);
0a9de3d2 339
a52fde77
AM
340 return listOfChildren;
341 }
342
c66426fd
AM
343 private void addSubAttributes(List<Integer> list, Attribute curAttribute,
344 boolean recursive) {
cb42195c 345 for (Attribute childNode : curAttribute.getSubAttributes()) {
c66426fd
AM
346 list.add(childNode.getQuark());
347 if (recursive) {
348 addSubAttributes(list, childNode, true);
349 }
350 }
351 }
352
50678114
AM
353 String getAttributeName(int quark) {
354 return attributeList.get(quark).getName();
355 }
356
a52fde77
AM
357 String getFullAttributeName(int quark) {
358 if (quark >= attributeList.size() || quark < 0) {
359 return null;
360 }
361 return attributeList.get(quark).getFullAttributeName();
362 }
363
364 void debugPrint(PrintWriter writer) {
365 attributeTreeRoot.debugPrint(writer);
366 }
367
368}
This page took 0.065184 seconds and 5 git commands to generate.