tmf: Replace state value types with an enum
[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
f5295294
AM
152 @Override
153 public boolean isLastAttribute(int quark) {
154 return (quark == getNbAttributes() - 1) ? true : false;
155 }
156
8d1346f0
AM
157 @Override
158 public String getAttributeName(int attributeQuark) {
339d27b4 159 return getAttributeTree().getAttributeName(attributeQuark);
8d1346f0
AM
160 }
161
162 @Override
163 public String getFullAttributePath(int attributeQuark) {
339d27b4 164 return getAttributeTree().getFullAttributeName(attributeQuark);
8d1346f0
AM
165 }
166
167 //--------------------------------------------------------------------------
168 // Methods related to the storage backend
169 //--------------------------------------------------------------------------
a52fde77 170
8d1346f0
AM
171 @Override
172 public long getStartTime() {
173 return backend.getStartTime();
174 }
175
176 @Override
177 public long getCurrentEndTime() {
178 return backend.getEndTime();
179 }
180
181 @Override
182 public void closeHistory(long endTime) throws TimeRangeException {
183 File attributeTreeFile;
184 long attributeTreeFilePos;
185 long realEndTime = endTime;
186
187 if (realEndTime < backend.getEndTime()) {
188 /*
189 * This can happen (empty nodes pushing the border further, etc.)
190 * but shouldn't be too big of a deal.
191 */
192 realEndTime = backend.getEndTime();
193 }
194 transState.closeTransientState(realEndTime);
195 backend.finishedBuilding(realEndTime);
196
197 attributeTreeFile = backend.supplyAttributeTreeWriterFile();
198 attributeTreeFilePos = backend.supplyAttributeTreeWriterFilePosition();
199 if (attributeTreeFile != null) {
200 /*
201 * If null was returned, we simply won't save the attribute tree,
202 * too bad!
203 */
339d27b4 204 getAttributeTree().writeSelf(attributeTreeFile, attributeTreeFilePos);
8d1346f0 205 }
16576a7e 206 finishedLatch.countDown(); /* Mark the history as finished building */
8d1346f0
AM
207 }
208
209 //--------------------------------------------------------------------------
210 // Quark-retrieving methods
211 //--------------------------------------------------------------------------
212
213 @Override
a52fde77
AM
214 public int getQuarkAbsolute(String... attribute)
215 throws AttributeNotFoundException {
339d27b4 216 return getAttributeTree().getQuarkDontAdd(-1, attribute);
a52fde77
AM
217 }
218
8d1346f0 219 @Override
a52fde77 220 public int getQuarkAbsoluteAndAdd(String... attribute) {
339d27b4 221 return getAttributeTree().getQuarkAndAdd(-1, attribute);
a52fde77
AM
222 }
223
8d1346f0 224 @Override
a52fde77
AM
225 public int getQuarkRelative(int startingNodeQuark, String... subPath)
226 throws AttributeNotFoundException {
339d27b4 227 return getAttributeTree().getQuarkDontAdd(startingNodeQuark, subPath);
a52fde77
AM
228 }
229
8d1346f0 230 @Override
a52fde77 231 public int getQuarkRelativeAndAdd(int startingNodeQuark, String... subPath) {
339d27b4 232 return getAttributeTree().getQuarkAndAdd(startingNodeQuark, subPath);
a52fde77
AM
233 }
234
8d1346f0 235 @Override
c66426fd 236 public List<Integer> getSubAttributes(int quark, boolean recursive)
0a9de3d2 237 throws AttributeNotFoundException {
339d27b4 238 return getAttributeTree().getSubAttributes(quark, recursive);
0a9de3d2
AM
239 }
240
8d1346f0 241 @Override
f94a0bac
AM
242 public List<Integer> getQuarks(String... pattern) {
243 List<Integer> quarks = new LinkedList<Integer>();
244 List<String> prefix = new LinkedList<String>();
245 List<String> suffix = new LinkedList<String>();
246 boolean split = false;
247 String[] prefixStr;
248 String[] suffixStr;
249 List<Integer> directChildren;
250 int startingAttribute;
251
252 /* Fill the "prefix" and "suffix" parts of the pattern around the '*' */
253 for (String entry : pattern) {
254 if (entry.equals("*")) { //$NON-NLS-1$
255 if (split) {
256 /*
257 * Split was already true? This means there was more than
258 * one wildcard. This is not supported, return an empty
259 * list.
260 */
261 return quarks;
262 }
263 split = true;
264 continue;
265 }
266
267 if (split) {
268 suffix.add(entry);
269 } else {
270 prefix.add(entry);
271 }
272 }
273 prefixStr = prefix.toArray(new String[prefix.size()]);
274 suffixStr = suffix.toArray(new String[suffix.size()]);
275
276 /*
277 * If there was no wildcard, we'll only return the one matching
278 * attribute, if there is one.
279 */
280 if (split == false) {
281 int quark;
282 try {
283 quark = getQuarkAbsolute(prefixStr);
284 } catch (AttributeNotFoundException e) {
285 /* It's fine, we'll just return the empty List */
286 return quarks;
287 }
288 quarks.add(quark);
289 return quarks;
290 }
291
292 try {
293 if (prefix.size() == 0) {
294 /*
295 * If 'prefix' is empty, this means the wildcard was the first
296 * element. Look for the root node's sub-attributes.
297 */
298 startingAttribute = -1;
299 } else {
300 startingAttribute = getQuarkAbsolute(prefixStr);
301 }
339d27b4 302 directChildren = getSubAttributes(startingAttribute, false);
f94a0bac
AM
303 } catch (AttributeNotFoundException e) {
304 /* That attribute path did not exist, return the empty array */
305 return quarks;
306 }
307
308 /*
309 * Iterate of all the sub-attributes, and only keep those who match the
310 * 'suffix' part of the initial pattern.
311 */
312 for (int childQuark : directChildren) {
313 int matchingQuark;
314 try {
315 matchingQuark = getQuarkRelative(childQuark, suffixStr);
316 } catch (AttributeNotFoundException e) {
317 continue;
318 }
319 quarks.add(matchingQuark);
320 }
321
322 return quarks;
323 }
324
8d1346f0
AM
325 //--------------------------------------------------------------------------
326 // Methods related to insertions in the history
327 //--------------------------------------------------------------------------
a52fde77 328
8d1346f0 329 @Override
a52fde77 330 public void modifyAttribute(long t, ITmfStateValue value, int attributeQuark)
7e0b2b56
AM
331 throws TimeRangeException, AttributeNotFoundException,
332 StateValueTypeException {
a52fde77
AM
333 transState.processStateChange(t, value, attributeQuark);
334 }
335
8d1346f0 336 @Override
a52fde77
AM
337 public void incrementAttribute(long t, int attributeQuark)
338 throws StateValueTypeException, TimeRangeException,
339 AttributeNotFoundException {
340 int prevValue = queryOngoingState(attributeQuark).unboxInt();
280bbdbb
AM
341 if (prevValue == -1) {
342 /* if the attribute was previously null, start counting at 0 */
343 prevValue = 0;
344 }
a52fde77
AM
345 modifyAttribute(t, TmfStateValue.newValueInt(prevValue + 1),
346 attributeQuark);
347 }
348
8d1346f0 349 @Override
a52fde77
AM
350 public void pushAttribute(long t, ITmfStateValue value, int attributeQuark)
351 throws TimeRangeException, AttributeNotFoundException,
352 StateValueTypeException {
a52fde77
AM
353 Integer stackDepth = 0;
354 int subAttributeQuark;
355 ITmfStateValue previousSV = transState.getOngoingStateValue(attributeQuark);
356
357 if (previousSV.isNull()) {
358 /*
359 * If the StateValue was null, this means this is the first time we
360 * use this attribute. Leave stackDepth at 0.
361 */
b67a2540 362 } else if (previousSV.getType() == Type.INTEGER) {
a52fde77
AM
363 /* Previous value was an integer, all is good, use it */
364 stackDepth = previousSV.unboxInt();
a52fde77
AM
365 } else {
366 /* Previous state of this attribute was another type? Not good! */
90a25ebe
AM
367 throw new StateValueTypeException();
368 }
369
370 if (stackDepth >= 10) {
371 /*
372 * Limit stackDepth to 10, to avoid having Attribute Trees grow out
373 * of control due to buggy insertions
374 */
375 String message = "Stack limit reached, not pushing"; //$NON-NLS-1$
376 throw new AttributeNotFoundException(message);
a52fde77
AM
377 }
378
379 stackDepth++;
5896eb76 380 subAttributeQuark = getQuarkRelativeAndAdd(attributeQuark, stackDepth.toString());
a52fde77 381
5896eb76 382 modifyAttribute(t, TmfStateValue.newValueInt(stackDepth), attributeQuark);
90a25ebe 383 modifyAttribute(t, value, subAttributeQuark);
a52fde77
AM
384 }
385
8d1346f0 386 @Override
5896eb76 387 public ITmfStateValue popAttribute(long t, int attributeQuark)
a52fde77
AM
388 throws AttributeNotFoundException, TimeRangeException,
389 StateValueTypeException {
e2eac108 390 /* These are the state values of the stack-attribute itself */
5896eb76 391 ITmfStateValue previousSV = queryOngoingState(attributeQuark);
a52fde77
AM
392
393 if (previousSV.isNull()) {
e2eac108
AM
394 /*
395 * Trying to pop an empty stack. This often happens at the start of
396 * traces, for example when we see a syscall_exit, without having
397 * the corresponding syscall_entry in the trace. Just ignore
398 * silently.
399 */
5896eb76 400 return null;
90a25ebe 401 }
b67a2540 402 if (previousSV.getType() != Type.INTEGER) {
a52fde77 403 /*
b67a2540
AM
404 * The existing value was not an integer (which is expected for
405 * stack tops), this doesn't look like a valid stack attribute.
a52fde77 406 */
90a25ebe 407 throw new StateValueTypeException();
a52fde77
AM
408 }
409
5896eb76 410 Integer stackDepth = previousSV.unboxInt();
90a25ebe 411
e2eac108 412 if (stackDepth <= 0) {
a52fde77 413 /* This on the other hand should not happen... */
e2eac108
AM
414 /* the case where == -1 was handled previously by .isNull() */
415 String message = "A top-level stack attribute cannot " + //$NON-NLS-1$
416 "have a value of 0 or less (except -1/null)."; //$NON-NLS-1$
90a25ebe 417 throw new StateValueTypeException(message);
a52fde77
AM
418 }
419
e2eac108 420 /* The attribute should already exist at this point */
5896eb76
AM
421 int subAttributeQuark = getQuarkRelative(attributeQuark, stackDepth.toString());
422 ITmfStateValue poppedValue = queryOngoingState(subAttributeQuark);
a52fde77 423
e2eac108
AM
424 /* Update the state value of the stack-attribute */
425 ITmfStateValue nextSV;
426 if (--stackDepth == 0 ) {
427 /* Jump over "0" and store -1 (a null state value) */
428 nextSV = TmfStateValue.nullValue();
429 } else {
430 nextSV = TmfStateValue.newValueInt(stackDepth);
431 }
432 modifyAttribute(t, nextSV, attributeQuark);
433
434 /* Delete the sub-attribute that contained the user's state value */
a52fde77 435 removeAttribute(t, subAttributeQuark);
e2eac108 436
5896eb76 437 return poppedValue;
a52fde77
AM
438 }
439
8d1346f0 440 @Override
a52fde77
AM
441 public void removeAttribute(long t, int attributeQuark)
442 throws TimeRangeException, AttributeNotFoundException {
443 assert (attributeQuark >= 0);
c66426fd
AM
444 List<Integer> childAttributes;
445
446 /*
447 * "Nullify our children first, recursively. We pass 'false' because we
448 * handle the recursion ourselves.
449 */
339d27b4 450 childAttributes = getSubAttributes(attributeQuark, false);
a52fde77
AM
451 for (Integer childNodeQuark : childAttributes) {
452 assert (attributeQuark != childNodeQuark);
453 removeAttribute(t, childNodeQuark);
454 }
455 /* Nullify ourselves */
7e0b2b56
AM
456 try {
457 transState.processStateChange(t, TmfStateValue.nullValue(),
458 attributeQuark);
459 } catch (StateValueTypeException e) {
50678114
AM
460 /*
461 * Will not happen since we're inserting null values only, but poor
462 * compiler has no way of knowing this...
7e0b2b56
AM
463 */
464 e.printStackTrace();
465 }
a52fde77
AM
466 }
467
8d1346f0
AM
468 //--------------------------------------------------------------------------
469 // "Current" query/update methods
470 //--------------------------------------------------------------------------
a52fde77 471
8d1346f0 472 @Override
a52fde77
AM
473 public ITmfStateValue queryOngoingState(int attributeQuark)
474 throws AttributeNotFoundException {
475 return transState.getOngoingStateValue(attributeQuark);
476 }
477
602c0697
AM
478 @Override
479 public long getOngoingStartTime(int attribute)
480 throws AttributeNotFoundException {
481 return transState.getOngoingStartTime(attribute);
482 }
483
8d1346f0 484 @Override
a52fde77
AM
485 public void updateOngoingState(ITmfStateValue newValue, int attributeQuark)
486 throws AttributeNotFoundException {
487 transState.changeOngoingStateValue(attributeQuark, newValue);
488 }
489
66866869
AM
490 /**
491 * Modify the whole "ongoing state" (state values + start times). This can
492 * be used when "seeking" a state system to a different point in the trace
493 * (and restoring the known stateInfo at this location). Use with care!
494 *
495 * @param newStateIntervals
496 * The new List of state values to use as ongoing state info
497 */
498 protected void replaceOngoingState(List<ITmfStateInterval> newStateIntervals) {
499 transState.replaceOngoingState(newStateIntervals);
500 }
501
8d1346f0
AM
502 //--------------------------------------------------------------------------
503 // Regular query methods (sent to the back-end)
504 //--------------------------------------------------------------------------
505
506 @Override
507 public synchronized List<ITmfStateInterval> queryFullState(long t)
96345c5a
AM
508 throws TimeRangeException, StateSystemDisposedException {
509 if (isDisposed) {
510 throw new StateSystemDisposedException();
511 }
512
339d27b4 513 List<ITmfStateInterval> stateInfo = new ArrayList<ITmfStateInterval>(getNbAttributes());
8d1346f0
AM
514
515 /* Bring the size of the array to the current number of attributes */
339d27b4 516 for (int i = 0; i < getNbAttributes(); i++) {
8d1346f0
AM
517 stateInfo.add(null);
518 }
519
520 /* Query the storage backend */
521 backend.doQuery(stateInfo, t);
522
523 /*
524 * If we are currently building the history, also query the "ongoing"
525 * states for stuff that might not yet be written to the history.
526 */
527 if (transState.isActive()) {
528 transState.doQuery(stateInfo, t);
529 }
530
531 /*
532 * We should have previously inserted an interval for every attribute.
533 * If we do happen do see a 'null' object here, just replace it with a a
534 * dummy internal with a null value, to avoid NPE's further up.
535 */
536 for (int i = 0; i < stateInfo.size(); i++) {
537 if (stateInfo.get(i) == null) {
538 //logMissingInterval(i, t);
539 stateInfo.set(i, new TmfStateInterval(t, t, i, TmfStateValue.nullValue()));
540 }
541 }
542 return stateInfo;
50678114
AM
543 }
544
8d1346f0
AM
545 @Override
546 public ITmfStateInterval querySingleState(long t, int attributeQuark)
96345c5a
AM
547 throws AttributeNotFoundException, TimeRangeException,
548 StateSystemDisposedException {
549 if (isDisposed) {
550 throw new StateSystemDisposedException();
551 }
8d1346f0 552
96345c5a 553 ITmfStateInterval ret;
8d1346f0
AM
554 if (transState.hasInfoAboutStateOf(t, attributeQuark)) {
555 ret = transState.getOngoingInterval(attributeQuark);
556 } else {
557 ret = backend.doSingularQuery(t, attributeQuark);
558 }
559
560 /*
561 * Return a fake interval if we could not find anything in the history.
562 * We do NOT want to return 'null' here.
563 */
564 if (ret == null) {
565 //logMissingInterval(attributeQuark, t);
566 return new TmfStateInterval(t, this.getCurrentEndTime(),
567 attributeQuark, TmfStateValue.nullValue());
568 }
569 return ret;
570 }
571
4bff6e6e
AM
572 @Override
573 public ITmfStateInterval querySingleStackTop(long t, int stackAttributeQuark)
574 throws StateValueTypeException, AttributeNotFoundException,
96345c5a 575 TimeRangeException, StateSystemDisposedException {
4bff6e6e
AM
576 Integer curStackDepth = querySingleState(t, stackAttributeQuark).getStateValue().unboxInt();
577
578 if (curStackDepth == -1) {
579 /* There is nothing stored in this stack at this moment */
580 return null;
581 } else if (curStackDepth < -1 || curStackDepth == 0) {
582 /*
583 * This attribute is an integer attribute, but it doesn't seem like
584 * it's used as a stack-attribute...
585 */
586 throw new StateValueTypeException();
587 }
588
589 int subAttribQuark = getQuarkRelative(stackAttributeQuark, curStackDepth.toString());
590 ITmfStateInterval ret = querySingleState(t, subAttribQuark);
591 return ret;
592 }
593
8d1346f0
AM
594 @Override
595 public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
596 long t1, long t2) throws TimeRangeException,
96345c5a
AM
597 AttributeNotFoundException, StateSystemDisposedException {
598 if (isDisposed) {
599 throw new StateSystemDisposedException();
600 }
601
8d1346f0
AM
602 List<ITmfStateInterval> intervals;
603 ITmfStateInterval currentInterval;
604 long ts, tEnd;
605
606 /* Make sure the time range makes sense */
607 if (t2 <= t1) {
608 throw new TimeRangeException();
609 }
610
611 /* Set the actual, valid end time of the range query */
612 if (t2 > this.getCurrentEndTime()) {
613 tEnd = this.getCurrentEndTime();
614 } else {
615 tEnd = t2;
616 }
617
618 /* Get the initial state at time T1 */
619 intervals = new ArrayList<ITmfStateInterval>();
620 currentInterval = querySingleState(t1, attributeQuark);
621 intervals.add(currentInterval);
622
623 /* Get the following state changes */
624 ts = currentInterval.getEndTime();
625 while (ts != -1 && ts < tEnd) {
626 ts++; /* To "jump over" to the next state in the history */
627 currentInterval = querySingleState(ts, attributeQuark);
628 intervals.add(currentInterval);
629 ts = currentInterval.getEndTime();
630 }
631 return intervals;
632 }
633
634 @Override
635 public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
b5a8d0cc 636 long t1, long t2, long resolution, IProgressMonitor monitor)
96345c5a
AM
637 throws TimeRangeException, AttributeNotFoundException,
638 StateSystemDisposedException {
639 if (isDisposed) {
640 throw new StateSystemDisposedException();
641 }
642
8d1346f0
AM
643 List<ITmfStateInterval> intervals;
644 ITmfStateInterval currentInterval;
645 long ts, tEnd;
646
41b5c37f
AM
647 IProgressMonitor mon = monitor;
648 if (mon == null) {
649 mon = new NullProgressMonitor();
b5a8d0cc
AM
650 }
651
8d1346f0
AM
652 /* Make sure the time range makes sense */
653 if (t2 < t1 || resolution <= 0) {
654 throw new TimeRangeException();
655 }
656
657 /* Set the actual, valid end time of the range query */
658 if (t2 > this.getCurrentEndTime()) {
659 tEnd = this.getCurrentEndTime();
660 } else {
661 tEnd = t2;
662 }
663
664 /* Get the initial state at time T1 */
665 intervals = new ArrayList<ITmfStateInterval>();
666 currentInterval = querySingleState(t1, attributeQuark);
667 intervals.add(currentInterval);
668
669 /*
670 * Iterate over the "resolution points". We skip unneeded queries in the
671 * case the current interval is longer than the resolution.
672 */
673 for (ts = t1; (currentInterval.getEndTime() != -1) && (ts < tEnd);
674 ts += resolution) {
41b5c37f 675 if (mon.isCanceled()) {
8d1346f0
AM
676 return intervals;
677 }
678 if (ts <= currentInterval.getEndTime()) {
679 continue;
680 }
681 currentInterval = querySingleState(ts, attributeQuark);
682 intervals.add(currentInterval);
683 }
684
685 /* Add the interval at t2, if it wasn't included already. */
686 if (currentInterval.getEndTime() < tEnd) {
687 currentInterval = querySingleState(tEnd, attributeQuark);
688 intervals.add(currentInterval);
689 }
690 return intervals;
691 }
692
693 //--------------------------------------------------------------------------
694 // Debug methods
695 //--------------------------------------------------------------------------
696
697 static void logMissingInterval(int attribute, long timestamp) {
5500a7f0 698 Activator.logInfo("No data found in history for attribute " + //$NON-NLS-1$
8d1346f0
AM
699 attribute + " at time " + timestamp + //$NON-NLS-1$
700 ", returning dummy interval"); //$NON-NLS-1$
a52fde77
AM
701 }
702
703 /**
704 * Print out the contents of the inner structures.
5df842b3 705 *
a52fde77
AM
706 * @param writer
707 * The PrintWriter in which to print the output
708 */
709 public void debugPrint(PrintWriter writer) {
339d27b4 710 getAttributeTree().debugPrint(writer);
a52fde77 711 transState.debugPrint(writer);
8d1346f0 712 backend.debugPrint(writer);
a52fde77
AM
713 }
714
8d1346f0 715}
This page took 0.07364 seconds and 5 git commands to generate.