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 /* prevValue should be == 0 if the attribute wasn't existing before */
184 modifyAttribute(t
, TmfStateValue
.newValueInt(prevValue
+ 1),
188 public void pushAttribute(long t
, ITmfStateValue value
, int attributeQuark
)
189 throws TimeRangeException
, AttributeNotFoundException
,
190 StateValueTypeException
{
191 Integer stackDepth
= 0;
192 int subAttributeQuark
;
193 ITmfStateValue previousSV
= transState
.getOngoingStateValue(attributeQuark
);
195 if (previousSV
.isNull()) {
197 * If the StateValue was null, this means this is the first time we
198 * use this attribute. Leave stackDepth at 0.
200 } else if (previousSV
.getType() == 0) {
201 /* Previous value was an integer, all is good, use it */
202 stackDepth
= previousSV
.unboxInt();
204 /* Previous state of this attribute was another type? Not good! */
205 throw new StateValueTypeException();
208 if (stackDepth
>= 10) {
210 * Limit stackDepth to 10, to avoid having Attribute Trees grow out
211 * of control due to buggy insertions
213 String message
= "Stack limit reached, not pushing"; //$NON-NLS-1$
214 throw new AttributeNotFoundException(message
);
218 subAttributeQuark
= getQuarkRelativeAndAdd(attributeQuark
,
219 stackDepth
.toString());
221 modifyAttribute(t
, TmfStateValue
.newValueInt(stackDepth
),
223 modifyAttribute(t
, value
, subAttributeQuark
);
226 public void popAttribute(long t
, int attributeQuark
)
227 throws AttributeNotFoundException
, TimeRangeException
,
228 StateValueTypeException
{
230 int subAttributeQuark
;
231 ITmfStateValue previousSV
= transState
.getOngoingStateValue(attributeQuark
);
233 if (previousSV
.isNull()) {
234 /* Same as if stackDepth == 0, see below */
237 if (previousSV
.getType() != 0) {
239 * The existing value was a string, this doesn't look like a valid
242 throw new StateValueTypeException();
245 stackDepth
= previousSV
.unboxInt();
247 if (stackDepth
== 0) {
249 * Trying to pop an empty stack. This often happens at the start of
250 * traces, for example when we see a syscall_exit, without having
251 * the corresponding syscall_entry in the trace. Just ignore
257 if (stackDepth
< 0) {
258 /* This on the other hand should not happen... */
259 String message
= "A top-level stack attribute " + //$NON-NLS-1$
260 "cannot have a negative integer value."; //$NON-NLS-1$
261 throw new StateValueTypeException(message
);
264 /* The attribute should already exist... */
265 subAttributeQuark
= getQuarkRelative(attributeQuark
,
266 stackDepth
.toString());
269 modifyAttribute(t
, TmfStateValue
.newValueInt(stackDepth
),
271 removeAttribute(t
, subAttributeQuark
);
274 public void removeAttribute(long t
, int attributeQuark
)
275 throws TimeRangeException
, AttributeNotFoundException
{
276 assert (attributeQuark
>= 0);
277 List
<Integer
> childAttributes
;
280 * "Nullify our children first, recursively. We pass 'false' because we
281 * handle the recursion ourselves.
283 childAttributes
= attributeTree
.getSubAttributes(attributeQuark
, false);
284 for (Integer childNodeQuark
: childAttributes
) {
285 assert (attributeQuark
!= childNodeQuark
);
286 removeAttribute(t
, childNodeQuark
);
288 /* Nullify ourselves */
290 transState
.processStateChange(t
, TmfStateValue
.nullValue(),
292 } catch (StateValueTypeException e
) {
294 * Will not happen since we're inserting null values only, but poor
295 * compiler has no way of knowing this...
302 * @name "Current" query/update methods -
305 public ITmfStateValue
queryOngoingState(int attributeQuark
)
306 throws AttributeNotFoundException
{
307 return transState
.getOngoingStateValue(attributeQuark
);
310 public void updateOngoingState(ITmfStateValue newValue
, int attributeQuark
)
311 throws AttributeNotFoundException
{
312 transState
.changeOngoingStateValue(attributeQuark
, newValue
);
315 public String
getAttributeName(int attributeQuark
) {
316 return attributeTree
.getAttributeName(attributeQuark
);
319 public String
getFullAttributePath(int attributeQuark
) {
320 return attributeTree
.getFullAttributeName(attributeQuark
);
324 * Print out the contents of the inner structures.
327 * The PrintWriter in which to print the output
329 public void debugPrint(PrintWriter writer
) {
330 attributeTree
.debugPrint(writer
);
331 transState
.debugPrint(writer
);