ss: Rename packages to org.eclipse.tracecompass.*
[deliverable/tracecompass.git] / org.eclipse.tracecompass.statesystem.core / src / org / eclipse / tracecompass / internal / statesystem / core / StateSystem.java
CommitLineData
a52fde77 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2012, 2014 Ericsson
a52fde77
AM
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
5df842b3 5 *
a52fde77
AM
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
5df842b3 10 *
a52fde77
AM
11 *******************************************************************************/
12
e894a508 13package org.eclipse.tracecompass.internal.statesystem.core;
a52fde77 14
8d1346f0
AM
15import java.io.File;
16import java.io.IOException;
a52fde77 17import java.io.PrintWriter;
8d1346f0 18import java.util.ArrayList;
f94a0bac 19import java.util.LinkedList;
a52fde77 20import java.util.List;
16576a7e 21import java.util.concurrent.CountDownLatch;
9287b6a2 22import java.util.concurrent.TimeUnit;
a52fde77 23
8d1346f0
AM
24import org.eclipse.core.runtime.IProgressMonitor;
25import org.eclipse.core.runtime.NullProgressMonitor;
2e21b6d8 26import org.eclipse.jdt.annotation.NonNull;
e894a508
AM
27import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
28import org.eclipse.tracecompass.statesystem.core.backend.IStateHistoryBackend;
29import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
30import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
31import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
32import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
33import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
34import org.eclipse.tracecompass.statesystem.core.interval.TmfStateInterval;
35import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
36import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
37import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type;
a52fde77
AM
38
39/**
8d1346f0
AM
40 * This is the core class of the Generic State System. It contains all the
41 * methods to build and query a state history. It's exposed externally through
42 * the IStateSystemQuerier and IStateSystemBuilder interfaces, depending if the
43 * user needs read-only access or read-write access.
5df842b3 44 *
8d1346f0
AM
45 * When building, DON'T FORGET to call .closeHistory() when you are done
46 * inserting intervals, or the storage backend will have no way of knowing it
47 * can close and write itself to disk, and its thread will keep running.
5df842b3 48 *
a52fde77 49 * @author alexmont
5df842b3 50 *
a52fde77 51 */
f1f86dfb 52public class StateSystem implements ITmfStateSystemBuilder {
a52fde77 53
84a9548a
AM
54 private final String ssid;
55
a52fde77 56 /* References to the inner structures */
8d1346f0
AM
57 private final AttributeTree attributeTree;
58 private final TransientState transState;
59 private final IStateHistoryBackend backend;
a52fde77 60
16576a7e
AM
61 /* Latch tracking if the state history is done building or not */
62 private final CountDownLatch finishedLatch = new CountDownLatch(1);
63
1a4205d9 64 private boolean buildCancelled = false;
96345c5a 65 private boolean isDisposed = false;
1a4205d9 66
f9a76cac
AM
67 /**
68 * New-file constructor. For when you build a state system with a new file,
69 * or if the back-end does not require a file on disk.
70 *
84a9548a
AM
71 * @param ssid
72 * The ID of this statesystem. It should be unique.
f9a76cac
AM
73 * @param backend
74 * Back-end plugin to use
75 */
84a9548a
AM
76 public StateSystem(@NonNull String ssid, @NonNull IStateHistoryBackend backend) {
77 this.ssid = ssid;
f9a76cac
AM
78 this.backend = backend;
79 this.transState = new TransientState(backend);
80 this.attributeTree = new AttributeTree(this);
81 }
82
a52fde77 83 /**
8d1346f0
AM
84 * General constructor
85 *
84a9548a
AM
86 * @param ssid
87 * The ID of this statesystem. It should be unique.
8d1346f0 88 * @param backend
f9a76cac 89 * The "state history storage" back-end to use.
8d1346f0
AM
90 * @param newFile
91 * Put true if this is a new history started from scratch. It is
92 * used to tell the state system where to get its attribute tree.
93 * @throws IOException
94 * If there was a problem creating the new history file
a52fde77 95 */
84a9548a 96 public StateSystem(@NonNull String ssid, @NonNull IStateHistoryBackend backend, boolean newFile)
8d1346f0 97 throws IOException {
84a9548a 98 this.ssid = ssid;
8d1346f0
AM
99 this.backend = backend;
100 this.transState = new TransientState(backend);
a52fde77 101
8d1346f0
AM
102 if (newFile) {
103 attributeTree = new AttributeTree(this);
104 } else {
105 /* We're opening an existing file */
106 this.attributeTree = new AttributeTree(this, backend.supplyAttributeTreeReader());
107 transState.setInactive();
16576a7e
AM
108 finishedLatch.countDown(); /* The history is already built */
109 }
110 }
111
84a9548a
AM
112 @Override
113 public String getSSID() {
114 return ssid;
115 }
116
16576a7e 117 @Override
2002c638
AM
118 public boolean isCancelled() {
119 return buildCancelled;
120 }
121
122 @Override
123 public void waitUntilBuilt() {
16576a7e
AM
124 try {
125 finishedLatch.await();
126 } catch (InterruptedException e) {
127 e.printStackTrace();
8d1346f0 128 }
1a4205d9
AM
129 }
130
9287b6a2
AM
131 @Override
132 public boolean waitUntilBuilt(long timeout) {
133 boolean ret = false;
134 try {
135 ret = finishedLatch.await(timeout, TimeUnit.MILLISECONDS);
136 } catch (InterruptedException e) {
137 e.printStackTrace();
138 }
139 return ret;
140 }
141
1a4205d9
AM
142 @Override
143 public synchronized void dispose() {
96345c5a 144 isDisposed = true;
1a4205d9
AM
145 if (transState.isActive()) {
146 transState.setInactive();
147 buildCancelled = true;
148 }
149 backend.dispose();
a52fde77
AM
150 }
151
8d1346f0
AM
152 //--------------------------------------------------------------------------
153 // General methods related to the attribute tree
154 //--------------------------------------------------------------------------
155
339d27b4
AM
156 /**
157 * Get the attribute tree associated with this state system. This should be
158 * the only way of accessing it (and if subclasses want to point to a
159 * different attribute tree than their own, they should only need to
160 * override this).
161 *
162 * @return The attribute tree
163 */
164 public AttributeTree getAttributeTree() {
165 return attributeTree;
166 }
167
8d1346f0
AM
168 /**
169 * Method used by the attribute tree when creating new attributes, to keep
170 * the attribute count in the transient state in sync.
171 */
bcec0116 172 public void addEmptyAttribute() {
8d1346f0
AM
173 transState.addEmptyEntry();
174 }
175
176 @Override
4623f57f 177 public int getNbAttributes() {
339d27b4 178 return getAttributeTree().getNbAttributes();
4623f57f
AM
179 }
180
8d1346f0
AM
181 @Override
182 public String getAttributeName(int attributeQuark) {
339d27b4 183 return getAttributeTree().getAttributeName(attributeQuark);
8d1346f0
AM
184 }
185
186 @Override
187 public String getFullAttributePath(int attributeQuark) {
339d27b4 188 return getAttributeTree().getFullAttributeName(attributeQuark);
8d1346f0
AM
189 }
190
191 //--------------------------------------------------------------------------
192 // Methods related to the storage backend
193 //--------------------------------------------------------------------------
a52fde77 194
8d1346f0
AM
195 @Override
196 public long getStartTime() {
197 return backend.getStartTime();
198 }
199
200 @Override
201 public long getCurrentEndTime() {
202 return backend.getEndTime();
203 }
204
205 @Override
206 public void closeHistory(long endTime) throws TimeRangeException {
207 File attributeTreeFile;
208 long attributeTreeFilePos;
209 long realEndTime = endTime;
210
211 if (realEndTime < backend.getEndTime()) {
212 /*
213 * This can happen (empty nodes pushing the border further, etc.)
214 * but shouldn't be too big of a deal.
215 */
216 realEndTime = backend.getEndTime();
217 }
218 transState.closeTransientState(realEndTime);
219 backend.finishedBuilding(realEndTime);
220
221 attributeTreeFile = backend.supplyAttributeTreeWriterFile();
222 attributeTreeFilePos = backend.supplyAttributeTreeWriterFilePosition();
223 if (attributeTreeFile != null) {
224 /*
225 * If null was returned, we simply won't save the attribute tree,
226 * too bad!
227 */
339d27b4 228 getAttributeTree().writeSelf(attributeTreeFile, attributeTreeFilePos);
8d1346f0 229 }
16576a7e 230 finishedLatch.countDown(); /* Mark the history as finished building */
8d1346f0
AM
231 }
232
233 //--------------------------------------------------------------------------
234 // Quark-retrieving methods
235 //--------------------------------------------------------------------------
236
237 @Override
a52fde77
AM
238 public int getQuarkAbsolute(String... attribute)
239 throws AttributeNotFoundException {
339d27b4 240 return getAttributeTree().getQuarkDontAdd(-1, attribute);
a52fde77
AM
241 }
242
8d1346f0 243 @Override
a52fde77 244 public int getQuarkAbsoluteAndAdd(String... attribute) {
339d27b4 245 return getAttributeTree().getQuarkAndAdd(-1, attribute);
a52fde77
AM
246 }
247
8d1346f0 248 @Override
a52fde77
AM
249 public int getQuarkRelative(int startingNodeQuark, String... subPath)
250 throws AttributeNotFoundException {
339d27b4 251 return getAttributeTree().getQuarkDontAdd(startingNodeQuark, subPath);
a52fde77
AM
252 }
253
8d1346f0 254 @Override
a52fde77 255 public int getQuarkRelativeAndAdd(int startingNodeQuark, String... subPath) {
339d27b4 256 return getAttributeTree().getQuarkAndAdd(startingNodeQuark, subPath);
a52fde77
AM
257 }
258
8d1346f0 259 @Override
c66426fd 260 public List<Integer> getSubAttributes(int quark, boolean recursive)
0a9de3d2 261 throws AttributeNotFoundException {
339d27b4 262 return getAttributeTree().getSubAttributes(quark, recursive);
0a9de3d2
AM
263 }
264
5206c858
AM
265 @Override
266 public List<Integer> getSubAttributes(int quark, boolean recursive, String pattern)
267 throws AttributeNotFoundException {
268 List<Integer> all = getSubAttributes(quark, recursive);
269 List<Integer> ret = new LinkedList<>();
270 for (Integer attQuark : all) {
271 String name = getAttributeName(attQuark.intValue());
272 if (name.matches(pattern)) {
273 ret.add(attQuark);
274 }
275 }
276 return ret;
277 }
278
0fdd2c45
FG
279 @Override
280 public int getParentAttributeQuark(int quark) {
281 return getAttributeTree().getParentAttributeQuark(quark);
282 }
283
8d1346f0 284 @Override
f94a0bac 285 public List<Integer> getQuarks(String... pattern) {
a4524c1b
AM
286 List<Integer> quarks = new LinkedList<>();
287 List<String> prefix = new LinkedList<>();
288 List<String> suffix = new LinkedList<>();
f94a0bac
AM
289 boolean split = false;
290 String[] prefixStr;
291 String[] suffixStr;
292 List<Integer> directChildren;
293 int startingAttribute;
294
295 /* Fill the "prefix" and "suffix" parts of the pattern around the '*' */
296 for (String entry : pattern) {
297 if (entry.equals("*")) { //$NON-NLS-1$
298 if (split) {
299 /*
300 * Split was already true? This means there was more than
301 * one wildcard. This is not supported, return an empty
302 * list.
303 */
304 return quarks;
305 }
306 split = true;
307 continue;
308 }
309
310 if (split) {
311 suffix.add(entry);
312 } else {
313 prefix.add(entry);
314 }
315 }
316 prefixStr = prefix.toArray(new String[prefix.size()]);
317 suffixStr = suffix.toArray(new String[suffix.size()]);
318
319 /*
320 * If there was no wildcard, we'll only return the one matching
321 * attribute, if there is one.
322 */
cb42195c 323 if (!split) {
f94a0bac
AM
324 int quark;
325 try {
326 quark = getQuarkAbsolute(prefixStr);
327 } catch (AttributeNotFoundException e) {
328 /* It's fine, we'll just return the empty List */
329 return quarks;
330 }
331 quarks.add(quark);
332 return quarks;
333 }
334
335 try {
336 if (prefix.size() == 0) {
337 /*
338 * If 'prefix' is empty, this means the wildcard was the first
339 * element. Look for the root node's sub-attributes.
340 */
341 startingAttribute = -1;
342 } else {
343 startingAttribute = getQuarkAbsolute(prefixStr);
344 }
339d27b4 345 directChildren = getSubAttributes(startingAttribute, false);
f94a0bac
AM
346 } catch (AttributeNotFoundException e) {
347 /* That attribute path did not exist, return the empty array */
348 return quarks;
349 }
350
351 /*
352 * Iterate of all the sub-attributes, and only keep those who match the
353 * 'suffix' part of the initial pattern.
354 */
355 for (int childQuark : directChildren) {
356 int matchingQuark;
357 try {
358 matchingQuark = getQuarkRelative(childQuark, suffixStr);
359 } catch (AttributeNotFoundException e) {
360 continue;
361 }
362 quarks.add(matchingQuark);
363 }
364
365 return quarks;
366 }
367
8d1346f0
AM
368 //--------------------------------------------------------------------------
369 // Methods related to insertions in the history
370 //--------------------------------------------------------------------------
a52fde77 371
8d1346f0 372 @Override
a52fde77 373 public void modifyAttribute(long t, ITmfStateValue value, int attributeQuark)
7e0b2b56
AM
374 throws TimeRangeException, AttributeNotFoundException,
375 StateValueTypeException {
a52fde77
AM
376 transState.processStateChange(t, value, attributeQuark);
377 }
378
8d1346f0 379 @Override
a52fde77
AM
380 public void incrementAttribute(long t, int attributeQuark)
381 throws StateValueTypeException, TimeRangeException,
382 AttributeNotFoundException {
359eeba0
PT
383 ITmfStateValue stateValue = queryOngoingState(attributeQuark);
384 int prevValue = 0;
385 /* if the attribute was previously null, start counting at 0 */
386 if (!stateValue.isNull()) {
387 prevValue = stateValue.unboxInt();
280bbdbb 388 }
a52fde77
AM
389 modifyAttribute(t, TmfStateValue.newValueInt(prevValue + 1),
390 attributeQuark);
391 }
392
8d1346f0 393 @Override
a52fde77
AM
394 public void pushAttribute(long t, ITmfStateValue value, int attributeQuark)
395 throws TimeRangeException, AttributeNotFoundException,
396 StateValueTypeException {
0126a8ca 397 int stackDepth;
a52fde77
AM
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. Leave stackDepth at 0.
405 */
cb42195c 406 stackDepth = 0;
b67a2540 407 } else if (previousSV.getType() == Type.INTEGER) {
a52fde77
AM
408 /* Previous value was an integer, all is good, use it */
409 stackDepth = previousSV.unboxInt();
a52fde77
AM
410 } else {
411 /* Previous state of this attribute was another type? Not good! */
90a25ebe
AM
412 throw new StateValueTypeException();
413 }
414
e8251298 415 if (stackDepth >= 100000) {
90a25ebe 416 /*
a0f8fb9b
FW
417 * Limit stackDepth to 100000, to avoid having Attribute Trees grow
418 * out of control due to buggy insertions
90a25ebe
AM
419 */
420 String message = "Stack limit reached, not pushing"; //$NON-NLS-1$
421 throw new AttributeNotFoundException(message);
a52fde77
AM
422 }
423
424 stackDepth++;
0126a8ca 425 subAttributeQuark = getQuarkRelativeAndAdd(attributeQuark, String.valueOf(stackDepth));
a52fde77 426
5896eb76 427 modifyAttribute(t, TmfStateValue.newValueInt(stackDepth), attributeQuark);
90a25ebe 428 modifyAttribute(t, value, subAttributeQuark);
a52fde77
AM
429 }
430
8d1346f0 431 @Override
5896eb76 432 public ITmfStateValue popAttribute(long t, int attributeQuark)
a52fde77
AM
433 throws AttributeNotFoundException, TimeRangeException,
434 StateValueTypeException {
e2eac108 435 /* These are the state values of the stack-attribute itself */
5896eb76 436 ITmfStateValue previousSV = queryOngoingState(attributeQuark);
a52fde77
AM
437
438 if (previousSV.isNull()) {
e2eac108
AM
439 /*
440 * Trying to pop an empty stack. This often happens at the start of
441 * traces, for example when we see a syscall_exit, without having
442 * the corresponding syscall_entry in the trace. Just ignore
443 * silently.
444 */
5896eb76 445 return null;
90a25ebe 446 }
b67a2540 447 if (previousSV.getType() != Type.INTEGER) {
a52fde77 448 /*
b67a2540
AM
449 * The existing value was not an integer (which is expected for
450 * stack tops), this doesn't look like a valid stack attribute.
a52fde77 451 */
90a25ebe 452 throw new StateValueTypeException();
a52fde77
AM
453 }
454
0126a8ca 455 int stackDepth = previousSV.unboxInt();
90a25ebe 456
e2eac108 457 if (stackDepth <= 0) {
a52fde77 458 /* This on the other hand should not happen... */
e2eac108 459 String message = "A top-level stack attribute cannot " + //$NON-NLS-1$
359eeba0 460 "have a value of 0 or less."; //$NON-NLS-1$
90a25ebe 461 throw new StateValueTypeException(message);
a52fde77
AM
462 }
463
e2eac108 464 /* The attribute should already exist at this point */
0126a8ca 465 int subAttributeQuark = getQuarkRelative(attributeQuark, String.valueOf(stackDepth));
5896eb76 466 ITmfStateValue poppedValue = queryOngoingState(subAttributeQuark);
a52fde77 467
e2eac108
AM
468 /* Update the state value of the stack-attribute */
469 ITmfStateValue nextSV;
a0f8fb9b 470 if (--stackDepth == 0) {
359eeba0 471 /* Store a null state value */
e2eac108
AM
472 nextSV = TmfStateValue.nullValue();
473 } else {
474 nextSV = TmfStateValue.newValueInt(stackDepth);
475 }
476 modifyAttribute(t, nextSV, attributeQuark);
477
478 /* Delete the sub-attribute that contained the user's state value */
a52fde77 479 removeAttribute(t, subAttributeQuark);
e2eac108 480
5896eb76 481 return poppedValue;
a52fde77
AM
482 }
483
8d1346f0 484 @Override
a52fde77
AM
485 public void removeAttribute(long t, int attributeQuark)
486 throws TimeRangeException, AttributeNotFoundException {
487 assert (attributeQuark >= 0);
c66426fd
AM
488 List<Integer> childAttributes;
489
490 /*
491 * "Nullify our children first, recursively. We pass 'false' because we
492 * handle the recursion ourselves.
493 */
339d27b4 494 childAttributes = getSubAttributes(attributeQuark, false);
0126a8ca 495 for (int childNodeQuark : childAttributes) {
a52fde77
AM
496 assert (attributeQuark != childNodeQuark);
497 removeAttribute(t, childNodeQuark);
498 }
499 /* Nullify ourselves */
7e0b2b56
AM
500 try {
501 transState.processStateChange(t, TmfStateValue.nullValue(),
502 attributeQuark);
503 } catch (StateValueTypeException e) {
50678114
AM
504 /*
505 * Will not happen since we're inserting null values only, but poor
506 * compiler has no way of knowing this...
7e0b2b56 507 */
cb42195c 508 throw new IllegalStateException(e);
7e0b2b56 509 }
a52fde77
AM
510 }
511
8d1346f0
AM
512 //--------------------------------------------------------------------------
513 // "Current" query/update methods
514 //--------------------------------------------------------------------------
a52fde77 515
8d1346f0 516 @Override
a52fde77
AM
517 public ITmfStateValue queryOngoingState(int attributeQuark)
518 throws AttributeNotFoundException {
519 return transState.getOngoingStateValue(attributeQuark);
520 }
521
602c0697
AM
522 @Override
523 public long getOngoingStartTime(int attribute)
524 throws AttributeNotFoundException {
525 return transState.getOngoingStartTime(attribute);
526 }
527
8d1346f0 528 @Override
a52fde77
AM
529 public void updateOngoingState(ITmfStateValue newValue, int attributeQuark)
530 throws AttributeNotFoundException {
531 transState.changeOngoingStateValue(attributeQuark, newValue);
532 }
533
66866869
AM
534 /**
535 * Modify the whole "ongoing state" (state values + start times). This can
536 * be used when "seeking" a state system to a different point in the trace
537 * (and restoring the known stateInfo at this location). Use with care!
538 *
539 * @param newStateIntervals
540 * The new List of state values to use as ongoing state info
541 */
542 protected void replaceOngoingState(List<ITmfStateInterval> newStateIntervals) {
543 transState.replaceOngoingState(newStateIntervals);
a0f8fb9b 544 }
66866869 545
8d1346f0
AM
546 //--------------------------------------------------------------------------
547 // Regular query methods (sent to the back-end)
548 //--------------------------------------------------------------------------
549
550 @Override
551 public synchronized List<ITmfStateInterval> queryFullState(long t)
96345c5a
AM
552 throws TimeRangeException, StateSystemDisposedException {
553 if (isDisposed) {
554 throw new StateSystemDisposedException();
555 }
556
a4524c1b 557 List<ITmfStateInterval> stateInfo = new ArrayList<>(getNbAttributes());
8d1346f0
AM
558
559 /* Bring the size of the array to the current number of attributes */
339d27b4 560 for (int i = 0; i < getNbAttributes(); i++) {
8d1346f0
AM
561 stateInfo.add(null);
562 }
563
564 /* Query the storage backend */
565 backend.doQuery(stateInfo, t);
566
567 /*
568 * If we are currently building the history, also query the "ongoing"
569 * states for stuff that might not yet be written to the history.
570 */
571 if (transState.isActive()) {
572 transState.doQuery(stateInfo, t);
573 }
574
575 /*
576 * We should have previously inserted an interval for every attribute.
577 * If we do happen do see a 'null' object here, just replace it with a a
578 * dummy internal with a null value, to avoid NPE's further up.
579 */
580 for (int i = 0; i < stateInfo.size(); i++) {
581 if (stateInfo.get(i) == null) {
8d1346f0
AM
582 stateInfo.set(i, new TmfStateInterval(t, t, i, TmfStateValue.nullValue()));
583 }
584 }
585 return stateInfo;
50678114
AM
586 }
587
8d1346f0
AM
588 @Override
589 public ITmfStateInterval querySingleState(long t, int attributeQuark)
96345c5a
AM
590 throws AttributeNotFoundException, TimeRangeException,
591 StateSystemDisposedException {
592 if (isDisposed) {
593 throw new StateSystemDisposedException();
594 }
8d1346f0 595
09e6fd9b
AM
596 ITmfStateInterval ret = transState.getIntervalAt(t, attributeQuark);
597 if (ret == null) {
598 /*
599 * The transient state did not have the information, let's look into
600 * the backend next.
601 */
8d1346f0
AM
602 ret = backend.doSingularQuery(t, attributeQuark);
603 }
604
605 /*
606 * Return a fake interval if we could not find anything in the history.
607 * We do NOT want to return 'null' here.
608 */
609 if (ret == null) {
8d1346f0
AM
610 return new TmfStateInterval(t, this.getCurrentEndTime(),
611 attributeQuark, TmfStateValue.nullValue());
612 }
613 return ret;
614 }
615
4bff6e6e
AM
616 @Override
617 public ITmfStateInterval querySingleStackTop(long t, int stackAttributeQuark)
618 throws StateValueTypeException, AttributeNotFoundException,
96345c5a 619 TimeRangeException, StateSystemDisposedException {
359eeba0 620 ITmfStateValue curStackStateValue = querySingleState(t, stackAttributeQuark).getStateValue();
4bff6e6e 621
359eeba0 622 if (curStackStateValue.isNull()) {
4bff6e6e
AM
623 /* There is nothing stored in this stack at this moment */
624 return null;
359eeba0 625 }
0126a8ca 626 int curStackDepth = curStackStateValue.unboxInt();
359eeba0 627 if (curStackDepth <= 0) {
4bff6e6e
AM
628 /*
629 * This attribute is an integer attribute, but it doesn't seem like
630 * it's used as a stack-attribute...
631 */
632 throw new StateValueTypeException();
633 }
634
0126a8ca 635 int subAttribQuark = getQuarkRelative(stackAttributeQuark, String.valueOf(curStackDepth));
cb42195c 636 return querySingleState(t, subAttribQuark);
4bff6e6e
AM
637 }
638
8d1346f0
AM
639 @Override
640 public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
641 long t1, long t2) throws TimeRangeException,
96345c5a
AM
642 AttributeNotFoundException, StateSystemDisposedException {
643 if (isDisposed) {
644 throw new StateSystemDisposedException();
645 }
646
8d1346f0
AM
647 List<ITmfStateInterval> intervals;
648 ITmfStateInterval currentInterval;
649 long ts, tEnd;
650
651 /* Make sure the time range makes sense */
1cf25311 652 if (t2 < t1) {
8d1346f0
AM
653 throw new TimeRangeException();
654 }
655
656 /* Set the actual, valid end time of the range query */
657 if (t2 > this.getCurrentEndTime()) {
658 tEnd = this.getCurrentEndTime();
659 } else {
660 tEnd = t2;
661 }
662
663 /* Get the initial state at time T1 */
a4524c1b 664 intervals = new ArrayList<>();
8d1346f0
AM
665 currentInterval = querySingleState(t1, attributeQuark);
666 intervals.add(currentInterval);
667
668 /* Get the following state changes */
669 ts = currentInterval.getEndTime();
670 while (ts != -1 && ts < tEnd) {
671 ts++; /* To "jump over" to the next state in the history */
672 currentInterval = querySingleState(ts, attributeQuark);
673 intervals.add(currentInterval);
674 ts = currentInterval.getEndTime();
675 }
676 return intervals;
677 }
678
679 @Override
680 public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
b5a8d0cc 681 long t1, long t2, long resolution, IProgressMonitor monitor)
96345c5a
AM
682 throws TimeRangeException, AttributeNotFoundException,
683 StateSystemDisposedException {
684 if (isDisposed) {
685 throw new StateSystemDisposedException();
686 }
687
a0f8fb9b
FW
688 List<ITmfStateInterval> intervals = new LinkedList<>();
689 ITmfStateInterval currentInterval = null;
8d1346f0
AM
690 long ts, tEnd;
691
41b5c37f
AM
692 IProgressMonitor mon = monitor;
693 if (mon == null) {
694 mon = new NullProgressMonitor();
b5a8d0cc
AM
695 }
696
8d1346f0
AM
697 /* Make sure the time range makes sense */
698 if (t2 < t1 || resolution <= 0) {
699 throw new TimeRangeException();
700 }
701
702 /* Set the actual, valid end time of the range query */
703 if (t2 > this.getCurrentEndTime()) {
704 tEnd = this.getCurrentEndTime();
705 } else {
706 tEnd = t2;
707 }
708
8d1346f0
AM
709 /*
710 * Iterate over the "resolution points". We skip unneeded queries in the
711 * case the current interval is longer than the resolution.
712 */
a0f8fb9b
FW
713 for (ts = t1; ts <= tEnd;
714 ts += ((currentInterval.getEndTime() - ts) / resolution + 1) * resolution) {
41b5c37f 715 if (mon.isCanceled()) {
8d1346f0
AM
716 return intervals;
717 }
8d1346f0
AM
718 currentInterval = querySingleState(ts, attributeQuark);
719 intervals.add(currentInterval);
720 }
721
722 /* Add the interval at t2, if it wasn't included already. */
a0f8fb9b 723 if (currentInterval != null && currentInterval.getEndTime() < tEnd) {
8d1346f0
AM
724 currentInterval = querySingleState(tEnd, attributeQuark);
725 intervals.add(currentInterval);
726 }
727 return intervals;
728 }
729
730 //--------------------------------------------------------------------------
731 // Debug methods
732 //--------------------------------------------------------------------------
733
734 static void logMissingInterval(int attribute, long timestamp) {
bcec0116 735 Activator.getDefault().logInfo("No data found in history for attribute " + //$NON-NLS-1$
8d1346f0
AM
736 attribute + " at time " + timestamp + //$NON-NLS-1$
737 ", returning dummy interval"); //$NON-NLS-1$
a52fde77
AM
738 }
739
740 /**
741 * Print out the contents of the inner structures.
5df842b3 742 *
a52fde77
AM
743 * @param writer
744 * The PrintWriter in which to print the output
745 */
746 public void debugPrint(PrintWriter writer) {
339d27b4 747 getAttributeTree().debugPrint(writer);
a52fde77 748 transState.debugPrint(writer);
8d1346f0 749 backend.debugPrint(writer);
a52fde77
AM
750 }
751
8d1346f0 752}
This page took 0.117648 seconds and 5 git commands to generate.