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