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