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