tmf: Provide a way to get the number of attributes in a system
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / internal / tmf / core / statesystem / StateSystem.java
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
13 package org.eclipse.linuxtools.internal.tmf.core.statesystem;
14
15 import java.io.PrintWriter;
16 import java.util.LinkedList;
17 import java.util.List;
18
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;
24
25 /**
26 * This is the base class for the StateHistorySystem. It contains all the
27 * current-state-updating methods.
28 *
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.
32 *
33 * (See IStateSystemQuerier and IStateSystemBuilder for the Javadoc.)
34 *
35 * @author alexmont
36 *
37 */
38 public class StateSystem {
39
40 /* References to the inner structures */
41 protected AttributeTree attributeTree;
42 protected TransientState transState;
43
44 /**
45 * Constructor. No configuration needed!
46 */
47 public StateSystem() {
48 attributeTree = new AttributeTree(this);
49
50 /* This will tell the builder to discard the intervals */
51 transState = new TransientState(null);
52 }
53
54 public int getNbAttributes() {
55 return attributeTree.getNbAttributes();
56 }
57
58 /**
59 * @name Quark-retrieving methods
60 */
61
62 public int getQuarkAbsolute(String... attribute)
63 throws AttributeNotFoundException {
64 return attributeTree.getQuarkDontAdd(-1, attribute);
65 }
66
67 public int getQuarkAbsoluteAndAdd(String... attribute) {
68 return attributeTree.getQuarkAndAdd(-1, attribute);
69 }
70
71 public int getQuarkRelative(int startingNodeQuark, String... subPath)
72 throws AttributeNotFoundException {
73 return attributeTree.getQuarkDontAdd(startingNodeQuark, subPath);
74 }
75
76 public int getQuarkRelativeAndAdd(int startingNodeQuark, String... subPath) {
77 return attributeTree.getQuarkAndAdd(startingNodeQuark, subPath);
78 }
79
80 public List<Integer> getSubAttributes(int quark, boolean recursive)
81 throws AttributeNotFoundException {
82 return attributeTree.getSubAttributes(quark, recursive);
83 }
84
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;
90 String[] prefixStr;
91 String[] suffixStr;
92 List<Integer> directChildren;
93 int startingAttribute;
94
95 /* Fill the "prefix" and "suffix" parts of the pattern around the '*' */
96 for (String entry : pattern) {
97 if (entry.equals("*")) { //$NON-NLS-1$
98 if (split) {
99 /*
100 * Split was already true? This means there was more than
101 * one wildcard. This is not supported, return an empty
102 * list.
103 */
104 return quarks;
105 }
106 split = true;
107 continue;
108 }
109
110 if (split) {
111 suffix.add(entry);
112 } else {
113 prefix.add(entry);
114 }
115 }
116 prefixStr = prefix.toArray(new String[prefix.size()]);
117 suffixStr = suffix.toArray(new String[suffix.size()]);
118
119 /*
120 * If there was no wildcard, we'll only return the one matching
121 * attribute, if there is one.
122 */
123 if (split == false) {
124 int quark;
125 try {
126 quark = getQuarkAbsolute(prefixStr);
127 } catch (AttributeNotFoundException e) {
128 /* It's fine, we'll just return the empty List */
129 return quarks;
130 }
131 quarks.add(quark);
132 return quarks;
133 }
134
135 try {
136 if (prefix.size() == 0) {
137 /*
138 * If 'prefix' is empty, this means the wildcard was the first
139 * element. Look for the root node's sub-attributes.
140 */
141 startingAttribute = -1;
142 } else {
143 startingAttribute = getQuarkAbsolute(prefixStr);
144 }
145 directChildren = attributeTree.getSubAttributes(startingAttribute,
146 false);
147 } catch (AttributeNotFoundException e) {
148 /* That attribute path did not exist, return the empty array */
149 return quarks;
150 }
151
152 /*
153 * Iterate of all the sub-attributes, and only keep those who match the
154 * 'suffix' part of the initial pattern.
155 */
156 for (int childQuark : directChildren) {
157 int matchingQuark;
158 try {
159 matchingQuark = getQuarkRelative(childQuark, suffixStr);
160 } catch (AttributeNotFoundException e) {
161 continue;
162 }
163 quarks.add(matchingQuark);
164 }
165
166 return quarks;
167 }
168
169 /**
170 * @name External methods related to insertions in the history -
171 */
172
173 public void modifyAttribute(long t, ITmfStateValue value, int attributeQuark)
174 throws TimeRangeException, AttributeNotFoundException,
175 StateValueTypeException {
176 transState.processStateChange(t, value, attributeQuark);
177 }
178
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),
185 attributeQuark);
186 }
187
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);
194
195 if (previousSV.isNull()) {
196 /*
197 * If the StateValue was null, this means this is the first time we
198 * use this attribute. Leave stackDepth at 0.
199 */
200 } else if (previousSV.getType() == 0) {
201 /* Previous value was an integer, all is good, use it */
202 stackDepth = previousSV.unboxInt();
203 } else {
204 /* Previous state of this attribute was another type? Not good! */
205 throw new StateValueTypeException();
206 }
207
208 if (stackDepth >= 10) {
209 /*
210 * Limit stackDepth to 10, to avoid having Attribute Trees grow out
211 * of control due to buggy insertions
212 */
213 String message = "Stack limit reached, not pushing"; //$NON-NLS-1$
214 throw new AttributeNotFoundException(message);
215 }
216
217 stackDepth++;
218 subAttributeQuark = getQuarkRelativeAndAdd(attributeQuark,
219 stackDepth.toString());
220
221 modifyAttribute(t, TmfStateValue.newValueInt(stackDepth),
222 attributeQuark);
223 modifyAttribute(t, value, subAttributeQuark);
224 }
225
226 public void popAttribute(long t, int attributeQuark)
227 throws AttributeNotFoundException, TimeRangeException,
228 StateValueTypeException {
229 Integer stackDepth;
230 int subAttributeQuark;
231 ITmfStateValue previousSV = transState.getOngoingStateValue(attributeQuark);
232
233 if (previousSV.isNull()) {
234 /* Same as if stackDepth == 0, see below */
235 return;
236 }
237 if (previousSV.getType() != 0) {
238 /*
239 * The existing value was a string, this doesn't look like a valid
240 * stack attribute.
241 */
242 throw new StateValueTypeException();
243 }
244
245 stackDepth = previousSV.unboxInt();
246
247 if (stackDepth == 0) {
248 /*
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
252 * silently.
253 */
254 return;
255 }
256
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);
262 }
263
264 /* The attribute should already exist... */
265 subAttributeQuark = getQuarkRelative(attributeQuark,
266 stackDepth.toString());
267
268 stackDepth--;
269 modifyAttribute(t, TmfStateValue.newValueInt(stackDepth),
270 attributeQuark);
271 removeAttribute(t, subAttributeQuark);
272 }
273
274 public void removeAttribute(long t, int attributeQuark)
275 throws TimeRangeException, AttributeNotFoundException {
276 assert (attributeQuark >= 0);
277 List<Integer> childAttributes;
278
279 /*
280 * "Nullify our children first, recursively. We pass 'false' because we
281 * handle the recursion ourselves.
282 */
283 childAttributes = attributeTree.getSubAttributes(attributeQuark, false);
284 for (Integer childNodeQuark : childAttributes) {
285 assert (attributeQuark != childNodeQuark);
286 removeAttribute(t, childNodeQuark);
287 }
288 /* Nullify ourselves */
289 try {
290 transState.processStateChange(t, TmfStateValue.nullValue(),
291 attributeQuark);
292 } catch (StateValueTypeException e) {
293 /*
294 * Will not happen since we're inserting null values only, but poor
295 * compiler has no way of knowing this...
296 */
297 e.printStackTrace();
298 }
299 }
300
301 /**
302 * @name "Current" query/update methods -
303 */
304
305 public ITmfStateValue queryOngoingState(int attributeQuark)
306 throws AttributeNotFoundException {
307 return transState.getOngoingStateValue(attributeQuark);
308 }
309
310 public void updateOngoingState(ITmfStateValue newValue, int attributeQuark)
311 throws AttributeNotFoundException {
312 transState.changeOngoingStateValue(attributeQuark, newValue);
313 }
314
315 public String getAttributeName(int attributeQuark) {
316 return attributeTree.getAttributeName(attributeQuark);
317 }
318
319 public String getFullAttributePath(int attributeQuark) {
320 return attributeTree.getFullAttributeName(attributeQuark);
321 }
322
323 /**
324 * Print out the contents of the inner structures.
325 *
326 * @param writer
327 * The PrintWriter in which to print the output
328 */
329 public void debugPrint(PrintWriter writer) {
330 attributeTree.debugPrint(writer);
331 transState.debugPrint(writer);
332 }
333
334 }
This page took 0.037562 seconds and 5 git commands to generate.