tmf: Allow attaching messages to GSS exceptions
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / statesystem / StateSystem.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
13package org.eclipse.linuxtools.tmf.core.statesystem;
14
15import java.io.PrintWriter;
f94a0bac 16import java.util.LinkedList;
a52fde77
AM
17import java.util.List;
18
19import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
20import org.eclipse.linuxtools.tmf.core.statevalue.StateValueTypeException;
21import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
22
23/**
24 * This is the base class for the StateHistorySystem. It contains all the
25 * current-state-updating methods.
26 *
27 * It's not abstract, as it can be used by itself: in this case, no History tree
28 * will be built underneath (no information will be saved to disk) and it will
29 * only be able to respond to queries to the current, latest time.
30 *
31 * @author alexmont
32 *
33 */
34public class StateSystem {
35
36 /* References to the inner structures */
37 protected AttributeTree attributeTree;
38 protected TransientState transState;
39
40 /**
41 * Constructor. No configuration needed!
42 */
43 public StateSystem() {
44 attributeTree = new AttributeTree(this);
45
46 /* This will tell the builder to discard the intervals */
47 transState = new TransientState(null);
48 }
49
50 /**
51 * @name Quark-retrieving methods
52 */
53
54 /**
55 * Basic quark-retrieving method. Pass an attribute in parameter as an array
56 * of strings, the matching quark will be returned.
57 *
58 * This version will NOT create any new attributes. If an invalid attribute
59 * is requested, an exception will be thrown. This should ideally be used
60 * for doing read-only operations on the system, like queries for example.
61 *
62 * @param attribute
63 * Attribute given as its full path in the Attribute Tree
64 * @return The quark of the requested attribute, if it existed.
65 * @throws AttributeNotFoundException
66 * This exception is thrown if the requested attribute simply
67 * did not exist in the system.
68 */
69 public int getQuarkAbsolute(String... attribute)
70 throws AttributeNotFoundException {
71 return attributeTree.getQuarkDontAdd(-1, attribute);
72 }
73
74 /**
75 * Basic quark-retrieving method. Pass an attribute in parameter as an array
76 * of strings, the matching quark will be returned.
77 *
78 * This version WILL create new attributes: if the attribute passed in
79 * parameter is new in the system, it will be added and its new quark will
80 * be returned.
81 *
82 * @param attribute
83 * Attribute given as its full path in the Attribute Tree
84 * @return The quark of the attribute (which either existed or just got
85 * created)
86 */
87 public int getQuarkAbsoluteAndAdd(String... attribute) {
88 return attributeTree.getQuarkAndAdd(-1, attribute);
89 }
90
91 /**
92 * "Relative path" quark-getting method. Instead of specifying a full path,
93 * if you know the path is relative to another attribute for which you
94 * already have the quark, use this for better performance.
95 *
96 * This is useful for cases where a lot of modifications or queries will
97 * originate from the same branch of the attribute tree : the common part of
98 * the path won't have to be re-hashed for every access.
99 *
100 * This version will NOT create any new attributes. If an invalid attribute
101 * is requested, an exception will be thrown. This should ideally be used
102 * for doing read-only operations on the system, like queries for example.
103 *
104 * @param startingNodeQuark
105 * The quark of the attribute from which 'subPath' originates.
106 * @param subPath
107 * "Rest" of the path to get to the final attribute
108 * @return The matching quark, if it existed
109 * @throws AttributeNotFoundException
110 */
111 public int getQuarkRelative(int startingNodeQuark, String... subPath)
112 throws AttributeNotFoundException {
113 return attributeTree.getQuarkDontAdd(startingNodeQuark, subPath);
114 }
115
116 /**
117 * "Relative path" quark-getting method. Instead of specifying a full path,
118 * if you know the path is relative to another attribute for which you
119 * already have the quark, use this for better performance.
120 *
121 * This is useful for cases where a lot of modifications or queries will
122 * originate from the same branch of the attribute tree : the common part of
123 * the path won't have to be re-hashed for every access.
124 *
125 * This version WILL create new attributes: if the attribute passed in
126 * parameter is new in the system, it will be added and its new quark will
127 * be returned.
128 *
129 * @param startingNodeQuark
130 * The quark of the attribute from which 'subPath' originates.
131 * @param subPath
132 * "Rest" of the path to get to the final attribute
133 * @return The matching quark, either if it's new of just got created.
134 */
135 public int getQuarkRelativeAndAdd(int startingNodeQuark, String... subPath) {
136 return attributeTree.getQuarkAndAdd(startingNodeQuark, subPath);
137 }
138
0a9de3d2
AM
139 /**
140 * Return the sub-attributes of the target attribute, as a List of quarks.
141 *
142 * @param quark
143 * The attribute of which you want to sub-attributes. You can use
144 * "-1" here to specify the root node.
c66426fd
AM
145 * @param recursive
146 * True if you want all recursive sub-attributes, false if you
147 * only want the first level.
0a9de3d2
AM
148 * @return A List of integers, matching the quarks of the sub-attributes.
149 * @throws AttributeNotFoundException
150 * If the quark was not existing or invalid.
151 */
c66426fd 152 public List<Integer> getSubAttributes(int quark, boolean recursive)
0a9de3d2 153 throws AttributeNotFoundException {
c66426fd 154 return attributeTree.getSubAttributes(quark, recursive);
0a9de3d2
AM
155 }
156
f94a0bac
AM
157 /**
158 * Batch quark-retrieving method. This method allows you to specify a path
159 * pattern which includes a wildcard "*" somewhere. It will check all the
160 * existing attributes in the attribute tree and return those who match the
161 * pattern.
162 *
163 * For example, passing ("Threads", "*", "Exec_mode") will return the list
164 * of quarks for attributes "Threads/1000/Exec_mode",
165 * "Threads/1500/Exec_mode", and so on, depending on what exists at this
166 * time in the attribute tree.
167 *
168 * If no wildcard is specified, the behavior is the same as
169 * getQuarkAbsolute() (except it will return a List with one entry). This
170 * method will never create new attributes.
171 *
172 * Only one wildcard "*" is supported at this time.
173 *
174 * @param pattern
175 * The array of strings representing the pattern to look for. It
176 * should ideally contain one entry that is only a "*".
177 * @return A List of attribute quarks, representing attributes that matched
178 * the pattern. If no attribute matched, the list will be empty (but
179 * not null).
180 */
181 public List<Integer> getQuarks(String... pattern) {
182 List<Integer> quarks = new LinkedList<Integer>();
183 List<String> prefix = new LinkedList<String>();
184 List<String> suffix = new LinkedList<String>();
185 boolean split = false;
186 String[] prefixStr;
187 String[] suffixStr;
188 List<Integer> directChildren;
189 int startingAttribute;
190
191 /* Fill the "prefix" and "suffix" parts of the pattern around the '*' */
192 for (String entry : pattern) {
193 if (entry.equals("*")) { //$NON-NLS-1$
194 if (split) {
195 /*
196 * Split was already true? This means there was more than
197 * one wildcard. This is not supported, return an empty
198 * list.
199 */
200 return quarks;
201 }
202 split = true;
203 continue;
204 }
205
206 if (split) {
207 suffix.add(entry);
208 } else {
209 prefix.add(entry);
210 }
211 }
212 prefixStr = prefix.toArray(new String[prefix.size()]);
213 suffixStr = suffix.toArray(new String[suffix.size()]);
214
215 /*
216 * If there was no wildcard, we'll only return the one matching
217 * attribute, if there is one.
218 */
219 if (split == false) {
220 int quark;
221 try {
222 quark = getQuarkAbsolute(prefixStr);
223 } catch (AttributeNotFoundException e) {
224 /* It's fine, we'll just return the empty List */
225 return quarks;
226 }
227 quarks.add(quark);
228 return quarks;
229 }
230
231 try {
232 if (prefix.size() == 0) {
233 /*
234 * If 'prefix' is empty, this means the wildcard was the first
235 * element. Look for the root node's sub-attributes.
236 */
237 startingAttribute = -1;
238 } else {
239 startingAttribute = getQuarkAbsolute(prefixStr);
240 }
241 directChildren = attributeTree.getSubAttributes(startingAttribute,
242 false);
243 } catch (AttributeNotFoundException e) {
244 /* That attribute path did not exist, return the empty array */
245 return quarks;
246 }
247
248 /*
249 * Iterate of all the sub-attributes, and only keep those who match the
250 * 'suffix' part of the initial pattern.
251 */
252 for (int childQuark : directChildren) {
253 int matchingQuark;
254 try {
255 matchingQuark = getQuarkRelative(childQuark, suffixStr);
256 } catch (AttributeNotFoundException e) {
257 continue;
258 }
259 quarks.add(matchingQuark);
260 }
261
262 return quarks;
263 }
264
a52fde77
AM
265 /**
266 * @name External methods related to insertions in the history -
267 */
268
269 /**
270 * Basic attribute modification method, we simply specify a new value, for a
271 * given attribute, effective at the given timestamp.
272 *
273 * @param t
274 * Timestamp of the state change
275 * @param value
276 * The State Value we want to assign to the attribute
277 * @param attributeQuark
278 * Integer value of the quark corresponding to the attribute we
279 * want to modify
280 * @throws TimeRangeException
281 * If the requested time is outside of the trace's range
282 * @throws AttributeNotFoundException
283 * If the requested attribute quark is invalid
284 */
285 public void modifyAttribute(long t, ITmfStateValue value, int attributeQuark)
286 throws TimeRangeException, AttributeNotFoundException {
287 transState.processStateChange(t, value, attributeQuark);
288 }
289
290 /**
291 * Increment attribute method. Reads the current value of a given integer
292 * attribute (this value is right now in the Transient State), and increment
293 * it by 1. Useful for statistics.
294 *
295 * @param t
296 * Timestamp of the state change
297 * @param attributeQuark
298 * Attribute to increment. If it doesn't exist it will be added,
299 * with a new value of 1.
300 * @throws StateValueTypeException
301 * If the attribute already exists but is not of type Integer
302 * @throws TimeRangeException
303 * If the given timestamp is invalid
304 * @throws AttributeNotFoundException
305 * If the quark is invalid
306 */
307 public void incrementAttribute(long t, int attributeQuark)
308 throws StateValueTypeException, TimeRangeException,
309 AttributeNotFoundException {
310 int prevValue = queryOngoingState(attributeQuark).unboxInt();
311 /* prevValue should be == 0 if the attribute wasn't existing before */
312 modifyAttribute(t, TmfStateValue.newValueInt(prevValue + 1),
313 attributeQuark);
314 }
315
316 /**
317 * "Push" helper method. This uses the given integer attribute as a stack:
318 * The value of that attribute will represent the stack depth (always >= 1).
319 * Sub-attributes will be created, their base-name will be the position in
320 * the stack (1, 2, etc.) and their value will be the state value 'value'
321 * that was pushed to this position.
322 *
323 * @param t
324 * Timestamp of the state change
325 * @param value
326 * State value to assign to this stack position.
327 * @param attributeQuark
328 * The base attribute to use as a stack. If it does not exist if
329 * will be created (with depth = 1)
330 * @throws TimeRangeException
331 * If the requested timestamp is invalid
332 * @throws AttributeNotFoundException
333 * If the attribute is invalid
334 * @throws StateValueTypeException
335 * If the attribute 'attributeQuark' already exists, but is not
336 * of integer type.
337 */
338 public void pushAttribute(long t, ITmfStateValue value, int attributeQuark)
339 throws TimeRangeException, AttributeNotFoundException,
340 StateValueTypeException {
341 assert (attributeQuark >= 0);
342 Integer stackDepth = 0;
343 int subAttributeQuark;
344 ITmfStateValue previousSV = transState.getOngoingStateValue(attributeQuark);
345
346 if (previousSV.isNull()) {
347 /*
348 * If the StateValue was null, this means this is the first time we
349 * use this attribute. Leave stackDepth at 0.
350 */
351 } else if (previousSV.getType() == 0) {
352 /* Previous value was an integer, all is good, use it */
353 stackDepth = previousSV.unboxInt();
354 if (stackDepth >= 10) {
355 /*
356 * Limit stackDepth to 10, to avoid having Attribute Trees grow
357 * out of control due to buggy insertions
358 */
359 assert (false);
360 }
361 } else {
362 /* Previous state of this attribute was another type? Not good! */
363 assert (false);
364 }
365
366 stackDepth++;
367 subAttributeQuark = getQuarkRelativeAndAdd(attributeQuark,
368 stackDepth.toString());
369
370 modifyAttribute(t, TmfStateValue.newValueInt(stackDepth),
371 attributeQuark);
372 transState.processStateChange(t, value, subAttributeQuark);
373 }
374
375 /**
376 * Antagonist of the pushAttribute(), pops the top-most attribute on the
377 * stack-attribute. If this brings it back to depth = 0, the attribute is
378 * kept with depth = 0. If the value is already 0, or if the attribute
379 * doesn't exist, nothing is done.
380 *
381 * @param t
382 * Timestamp of the state change
383 * @param attributeQuark
384 * Quark of the stack-attribute to pop
385 * @throws AttributeNotFoundException
386 * If the attribute is invalid
387 * @throws TimeRangeException
388 * If the timestamp is invalid
389 * @throws StateValueTypeException
390 * If the target attribute already exists, but its state value
391 * type is invalid (not an integer)
392 */
393 public void popAttribute(long t, int attributeQuark)
394 throws AttributeNotFoundException, TimeRangeException,
395 StateValueTypeException {
396 assert (attributeQuark >= 0);
397 Integer stackDepth;
398 int subAttributeQuark;
399 ITmfStateValue previousSV = transState.getOngoingStateValue(attributeQuark);
400
401 if (previousSV.isNull()) {
402 /*
403 * If the StateValue was null, this means this is the first time we
404 * use this attribute.
405 */
406 stackDepth = 0;
407 } else {
408 assert (previousSV.getType() == 0);
409 stackDepth = previousSV.unboxInt();
410 }
411
412 if (stackDepth == 0) {
413 /*
414 * Trying to pop an empty stack. This often happens at the start of
415 * traces, for example when we see a syscall_exit, without having
416 * the corresponding syscall_entry in the trace. Just ignore
417 * silently.
418 */
419 return;
420 } else if (stackDepth < 0) {
421 /* This on the other hand should not happen... */
422 assert (false);
423 }
424
425 /* The attribute should already exist... */
426 subAttributeQuark = getQuarkRelative(attributeQuark,
427 stackDepth.toString());
428
429 stackDepth--;
430 modifyAttribute(t, TmfStateValue.newValueInt(stackDepth),
431 attributeQuark);
432 removeAttribute(t, subAttributeQuark);
433 }
434
435 /**
436 * Remove attribute method. Similar to the above modify- methods, with value
437 * = 0 / null, except we will also "nullify" all the sub-contents of the
438 * requested path (a bit like "rm -rf")
439 *
440 * @param t
441 * Timestamp of the state change
442 * @param attributeQuark
443 * Attribute to remove
444 * @throws TimeRangeException
445 * If the timestamp is invalid
446 * @throws AttributeNotFoundException
447 * If the quark is invalid
448 */
449 public void removeAttribute(long t, int attributeQuark)
450 throws TimeRangeException, AttributeNotFoundException {
451 assert (attributeQuark >= 0);
c66426fd
AM
452 List<Integer> childAttributes;
453
454 /*
455 * "Nullify our children first, recursively. We pass 'false' because we
456 * handle the recursion ourselves.
457 */
458 childAttributes = attributeTree.getSubAttributes(attributeQuark, false);
a52fde77
AM
459 for (Integer childNodeQuark : childAttributes) {
460 assert (attributeQuark != childNodeQuark);
461 removeAttribute(t, childNodeQuark);
462 }
463 /* Nullify ourselves */
464 transState.processStateChange(t, TmfStateValue.nullValue(),
465 attributeQuark);
466 }
467
468 /**
469 * @name "Current" query/update methods -
470 */
471
472 /**
473 * Returns the current state value we have (in the Transient State) for the
474 * given attribute.
475 *
476 * This is useful even for a StateHistorySystem, as we are guaranteed it
477 * will only do a memory access and not go look on disk (and we don't even
478 * have to provide a timestamp!)
479 *
480 * @param attributeQuark
481 * For which attribute we want the current state
482 * @return The State value that's "current" for this attribute
483 * @throws AttributeNotFoundException
484 * If the requested attribute is invalid
485 */
486 public ITmfStateValue queryOngoingState(int attributeQuark)
487 throws AttributeNotFoundException {
488 return transState.getOngoingStateValue(attributeQuark);
489 }
490
491 /**
492 * Modify a current "ongoing" state (instead of inserting a state change,
493 * like modifyAttribute() and others).
494 *
495 * This can be used to update the value of a previous state change, for
496 * example when we get information at the end of the state and not at the
497 * beginning. (return values of system calls, etc.)
498 *
499 * Note that past states can only be modified while they are still in
500 * memory, so only the "current state" can be updated. Once they get
501 * committed to disk (by inserting a new state change) it becomes too late.
502 *
503 * @param newValue
504 * The new value that will overwrite the "current" one.
505 * @param attributeQuark
506 * For which attribute in the system
507 * @throws AttributeNotFoundException
508 * If the requested attribute is invalid
509 */
510 public void updateOngoingState(ITmfStateValue newValue, int attributeQuark)
511 throws AttributeNotFoundException {
512 transState.changeOngoingStateValue(attributeQuark, newValue);
513 }
514
515 /**
516 * @name Debugging methods
517 */
518
519 /**
520 * This returns the slash-separated path of an attribute by providing its
521 * quark
522 *
523 * @param attributeQuark
524 * The quark of the attribute we want
525 * @return One single string separated with '/', like a filesystem path
526 */
527 public String getFullAttributePath(int attributeQuark) {
528 return attributeTree.getFullAttributeName(attributeQuark);
529 }
530
531 /**
532 * Print out the contents of the inner structures.
533 *
534 * @param writer
535 * The PrintWriter in which to print the output
536 */
537 public void debugPrint(PrintWriter writer) {
538 attributeTree.debugPrint(writer);
539 transState.debugPrint(writer);
540 }
541
542}
This page took 0.044453 seconds and 5 git commands to generate.