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>
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
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.internal
.tmf
.core
.statesystem
;
15 import java
.io
.PrintWriter
;
16 import java
.util
.LinkedList
;
17 import java
.util
.List
;
19 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.AttributeNotFoundException
;
20 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateValueTypeException
;
21 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
22 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.ITmfStateValue
;
23 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.TmfStateValue
;
26 * This is the base class for the StateHistorySystem. It contains all the
27 * current-state-updating methods.
29 * It's not abstract, as it can be used by itself: in this case, no History tree
30 * will be built underneath (no information will be saved to disk) and it will
31 * only be able to respond to queries to the current, latest time.
33 * (See IStateSystemQuerier and IStateSystemBuilder for the Javadoc.)
38 public class StateSystem
{
40 /* References to the inner structures */
41 protected AttributeTree attributeTree
;
42 protected TransientState transState
;
45 * Constructor. No configuration needed!
47 public StateSystem() {
48 attributeTree
= new AttributeTree(this);
50 /* This will tell the builder to discard the intervals */
51 transState
= new TransientState(null);
54 public int getNbAttributes() {
55 return attributeTree
.getNbAttributes();
59 * @name Quark-retrieving methods
62 public int getQuarkAbsolute(String
... attribute
)
63 throws AttributeNotFoundException
{
64 return attributeTree
.getQuarkDontAdd(-1, attribute
);
67 public int getQuarkAbsoluteAndAdd(String
... attribute
) {
68 return attributeTree
.getQuarkAndAdd(-1, attribute
);
71 public int getQuarkRelative(int startingNodeQuark
, String
... subPath
)
72 throws AttributeNotFoundException
{
73 return attributeTree
.getQuarkDontAdd(startingNodeQuark
, subPath
);
76 public int getQuarkRelativeAndAdd(int startingNodeQuark
, String
... subPath
) {
77 return attributeTree
.getQuarkAndAdd(startingNodeQuark
, subPath
);
80 public List
<Integer
> getSubAttributes(int quark
, boolean recursive
)
81 throws AttributeNotFoundException
{
82 return attributeTree
.getSubAttributes(quark
, recursive
);
85 public List
<Integer
> getQuarks(String
... pattern
) {
86 List
<Integer
> quarks
= new LinkedList
<Integer
>();
87 List
<String
> prefix
= new LinkedList
<String
>();
88 List
<String
> suffix
= new LinkedList
<String
>();
89 boolean split
= false;
92 List
<Integer
> directChildren
;
93 int startingAttribute
;
95 /* Fill the "prefix" and "suffix" parts of the pattern around the '*' */
96 for (String entry
: pattern
) {
97 if (entry
.equals("*")) { //$NON-NLS-1$
100 * Split was already true? This means there was more than
101 * one wildcard. This is not supported, return an empty
116 prefixStr
= prefix
.toArray(new String
[prefix
.size()]);
117 suffixStr
= suffix
.toArray(new String
[suffix
.size()]);
120 * If there was no wildcard, we'll only return the one matching
121 * attribute, if there is one.
123 if (split
== false) {
126 quark
= getQuarkAbsolute(prefixStr
);
127 } catch (AttributeNotFoundException e
) {
128 /* It's fine, we'll just return the empty List */
136 if (prefix
.size() == 0) {
138 * If 'prefix' is empty, this means the wildcard was the first
139 * element. Look for the root node's sub-attributes.
141 startingAttribute
= -1;
143 startingAttribute
= getQuarkAbsolute(prefixStr
);
145 directChildren
= attributeTree
.getSubAttributes(startingAttribute
,
147 } catch (AttributeNotFoundException e
) {
148 /* That attribute path did not exist, return the empty array */
153 * Iterate of all the sub-attributes, and only keep those who match the
154 * 'suffix' part of the initial pattern.
156 for (int childQuark
: directChildren
) {
159 matchingQuark
= getQuarkRelative(childQuark
, suffixStr
);
160 } catch (AttributeNotFoundException e
) {
163 quarks
.add(matchingQuark
);
170 * @name External methods related to insertions in the history -
173 public void modifyAttribute(long t
, ITmfStateValue value
, int attributeQuark
)
174 throws TimeRangeException
, AttributeNotFoundException
,
175 StateValueTypeException
{
176 transState
.processStateChange(t
, value
, attributeQuark
);
179 public void incrementAttribute(long t
, int attributeQuark
)
180 throws StateValueTypeException
, TimeRangeException
,
181 AttributeNotFoundException
{
182 int prevValue
= queryOngoingState(attributeQuark
).unboxInt();
183 if (prevValue
== -1) {
184 /* if the attribute was previously null, start counting at 0 */
187 modifyAttribute(t
, TmfStateValue
.newValueInt(prevValue
+ 1),
191 public void pushAttribute(long t
, ITmfStateValue value
, int attributeQuark
)
192 throws TimeRangeException
, AttributeNotFoundException
,
193 StateValueTypeException
{
194 Integer stackDepth
= 0;
195 int subAttributeQuark
;
196 ITmfStateValue previousSV
= transState
.getOngoingStateValue(attributeQuark
);
198 if (previousSV
.isNull()) {
200 * If the StateValue was null, this means this is the first time we
201 * use this attribute. Leave stackDepth at 0.
203 } else if (previousSV
.getType() == 0) {
204 /* Previous value was an integer, all is good, use it */
205 stackDepth
= previousSV
.unboxInt();
207 /* Previous state of this attribute was another type? Not good! */
208 throw new StateValueTypeException();
211 if (stackDepth
>= 10) {
213 * Limit stackDepth to 10, to avoid having Attribute Trees grow out
214 * of control due to buggy insertions
216 String message
= "Stack limit reached, not pushing"; //$NON-NLS-1$
217 throw new AttributeNotFoundException(message
);
221 subAttributeQuark
= getQuarkRelativeAndAdd(attributeQuark
,
222 stackDepth
.toString());
224 modifyAttribute(t
, TmfStateValue
.newValueInt(stackDepth
),
226 modifyAttribute(t
, value
, subAttributeQuark
);
229 public void popAttribute(long t
, int attributeQuark
)
230 throws AttributeNotFoundException
, TimeRangeException
,
231 StateValueTypeException
{
233 int subAttributeQuark
;
234 ITmfStateValue previousSV
= transState
.getOngoingStateValue(attributeQuark
);
236 if (previousSV
.isNull()) {
237 /* Same as if stackDepth == 0, see below */
240 if (previousSV
.getType() != 0) {
242 * The existing value was a string, this doesn't look like a valid
245 throw new StateValueTypeException();
248 stackDepth
= previousSV
.unboxInt();
250 if (stackDepth
== 0) {
252 * Trying to pop an empty stack. This often happens at the start of
253 * traces, for example when we see a syscall_exit, without having
254 * the corresponding syscall_entry in the trace. Just ignore
260 if (stackDepth
< 0) {
261 /* This on the other hand should not happen... */
262 String message
= "A top-level stack attribute " + //$NON-NLS-1$
263 "cannot have a negative integer value."; //$NON-NLS-1$
264 throw new StateValueTypeException(message
);
267 /* The attribute should already exist... */
268 subAttributeQuark
= getQuarkRelative(attributeQuark
,
269 stackDepth
.toString());
272 modifyAttribute(t
, TmfStateValue
.newValueInt(stackDepth
),
274 removeAttribute(t
, subAttributeQuark
);
277 public void removeAttribute(long t
, int attributeQuark
)
278 throws TimeRangeException
, AttributeNotFoundException
{
279 assert (attributeQuark
>= 0);
280 List
<Integer
> childAttributes
;
283 * "Nullify our children first, recursively. We pass 'false' because we
284 * handle the recursion ourselves.
286 childAttributes
= attributeTree
.getSubAttributes(attributeQuark
, false);
287 for (Integer childNodeQuark
: childAttributes
) {
288 assert (attributeQuark
!= childNodeQuark
);
289 removeAttribute(t
, childNodeQuark
);
291 /* Nullify ourselves */
293 transState
.processStateChange(t
, TmfStateValue
.nullValue(),
295 } catch (StateValueTypeException e
) {
297 * Will not happen since we're inserting null values only, but poor
298 * compiler has no way of knowing this...
305 * @name "Current" query/update methods -
308 public ITmfStateValue
queryOngoingState(int attributeQuark
)
309 throws AttributeNotFoundException
{
310 return transState
.getOngoingStateValue(attributeQuark
);
313 public void updateOngoingState(ITmfStateValue newValue
, int attributeQuark
)
314 throws AttributeNotFoundException
{
315 transState
.changeOngoingStateValue(attributeQuark
, newValue
);
318 public String
getAttributeName(int attributeQuark
) {
319 return attributeTree
.getAttributeName(attributeQuark
);
322 public String
getFullAttributePath(int attributeQuark
) {
323 return attributeTree
.getFullAttributeName(attributeQuark
);
327 * Print out the contents of the inner structures.
330 * The PrintWriter in which to print the output
332 public void debugPrint(PrintWriter writer
) {
333 attributeTree
.debugPrint(writer
);
334 transState
.debugPrint(writer
);