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