Fix references to linuxtools in comments, examples and unused code
[deliverable/tracecompass.git] / org.eclipse.tracecompass.statesystem.core / src / org / eclipse / tracecompass / internal / statesystem / core / TransientState.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>
97042f0a 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
97042f0a 10 *
a52fde77
AM
11 *******************************************************************************/
12
e894a508 13package org.eclipse.tracecompass.internal.statesystem.core;
a52fde77
AM
14
15import java.io.PrintWriter;
16import java.util.ArrayList;
17import java.util.List;
09e6fd9b 18import java.util.concurrent.locks.ReentrantReadWriteLock;
a52fde77 19
feea3b3c 20import org.eclipse.jdt.annotation.NonNullByDefault;
09e6fd9b 21import org.eclipse.jdt.annotation.Nullable;
e894a508
AM
22import org.eclipse.tracecompass.statesystem.core.backend.IStateHistoryBackend;
23import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
24import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
25import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
26import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
27import org.eclipse.tracecompass.statesystem.core.interval.TmfStateInterval;
28import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
e894a508 29import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type;
feea3b3c 30import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
a52fde77
AM
31
32/**
a6917276
AM
33 * The Transient State is used to build intervals from punctual state changes.
34 * It contains a "state info" vector similar to the "current state", except here
35 * we also record the start time of every state stored in it.
97042f0a 36 *
a6917276
AM
37 * We can then build {@link ITmfStateInterval}'s, to be inserted in a
38 * {@link IStateHistoryBackend} when we detect state changes : the "start time"
39 * of the interval will be the recorded time we have here, and the "end time"
40 * will be the timestamp of the new state-changing event we just read.
97042f0a 41 *
a6917276 42 * @author Alexandre Montplaisir
a52fde77 43 */
feea3b3c 44@NonNullByDefault
a6917276 45public class TransientState {
a52fde77
AM
46
47 /* Indicates where to insert state changes that we generate */
086cd39c 48 private final IStateHistoryBackend fBackend;
a52fde77 49
086cd39c 50 private final ReentrantReadWriteLock fRWLock = new ReentrantReadWriteLock(false);
a52fde77 51
086cd39c
MK
52 private volatile boolean fIsActive;
53 private volatile long fLatestTime;
09e6fd9b
AM
54
55 /* A method accessing these arrays will have to go through the lock */
086cd39c
MK
56 private List<ITmfStateValue> fOngoingStateInfo;
57 private List<Long> fOngoingStateStartTimes;
58 private List<Type> fStateValueTypes;
a52fde77 59
a6917276
AM
60 /**
61 * Constructor
62 *
63 * @param backend
64 * The back-end in which to insert the generated state intervals
65 */
feea3b3c 66 public TransientState(IStateHistoryBackend backend) {
086cd39c
MK
67 fBackend = backend;
68 fIsActive = true;
69 fOngoingStateInfo = new ArrayList<>();
70 fOngoingStateStartTimes = new ArrayList<>();
71 fStateValueTypes = new ArrayList<>();
a52fde77 72
086cd39c 73 fLatestTime = backend.getStartTime();
a52fde77
AM
74 }
75
a6917276
AM
76 /**
77 * Get the latest time we have seen so far.
78 *
79 * @return The latest time seen in the transient state
80 */
81 public long getLatestTime() {
086cd39c 82 return fLatestTime;
a52fde77
AM
83 }
84
a6917276
AM
85 /**
86 * Retrieve the ongoing state value for a given index (attribute quark).
87 *
88 * @param quark
89 * The quark of the attribute to look for
90 * @return The corresponding state value
91 * @throws AttributeNotFoundException
92 * If the quark is invalid
93 */
94 public ITmfStateValue getOngoingStateValue(int quark) throws AttributeNotFoundException {
086cd39c 95 fRWLock.readLock().lock();
09e6fd9b
AM
96 try {
97 checkValidAttribute(quark);
086cd39c 98 ITmfStateValue ret = fOngoingStateInfo.get(quark);
feea3b3c
AM
99 if (ret == null) {
100 throw new IllegalStateException("Null interval stored in transient state"); //$NON-NLS-1$
101 }
102 return ret;
09e6fd9b 103 } finally {
086cd39c 104 fRWLock.readLock().unlock();
09e6fd9b 105 }
a52fde77
AM
106 }
107
a6917276
AM
108 /**
109 * Retrieve the start time of the state in which the given attribute is in.
110 *
111 * @param quark
112 * The quark of the attribute to look for
113 * @return The start time of the current state for this attribute
114 * @throws AttributeNotFoundException
115 * If the quark is invalid
116 */
117 public long getOngoingStartTime(int quark) throws AttributeNotFoundException {
086cd39c 118 fRWLock.readLock().lock();
09e6fd9b
AM
119 try {
120 checkValidAttribute(quark);
086cd39c 121 return fOngoingStateStartTimes.get(quark);
09e6fd9b 122 } finally {
086cd39c 123 fRWLock.readLock().unlock();
09e6fd9b 124 }
602c0697
AM
125 }
126
a6917276
AM
127 /**
128 * Modify the current state for a given attribute. This will not update the
129 * "ongoing state start time" in any way, so be careful when using this.
130 *
131 * @param quark
132 * The quark of the attribute to modify
133 * @param newValue
134 * The state value the attribute should have
135 * @throws AttributeNotFoundException
136 * If the quark is invalid
137 */
138 public void changeOngoingStateValue(int quark, ITmfStateValue newValue)
a52fde77 139 throws AttributeNotFoundException {
086cd39c 140 fRWLock.writeLock().lock();
09e6fd9b
AM
141 try {
142 checkValidAttribute(quark);
086cd39c 143 fOngoingStateInfo.set(quark, newValue);
09e6fd9b 144 } finally {
086cd39c 145 fRWLock.writeLock().unlock();
09e6fd9b 146 }
a52fde77
AM
147 }
148
149 /**
a6917276 150 * Convenience method to return the "ongoing" value for a given attribute as
c3c783f6 151 * a dummy interval whose end time = the current latest time.
97042f0a 152 *
a52fde77 153 * @param quark
a6917276
AM
154 * The quark of the attribute
155 * @return An interval representing the current state (but whose end time is
c3c783f6 156 * the current one, and probably not the "final" one)
a52fde77 157 * @throws AttributeNotFoundException
a6917276 158 * If the quark is invalid
a52fde77 159 */
a6917276 160 public ITmfStateInterval getOngoingInterval(int quark) throws AttributeNotFoundException {
086cd39c 161 fRWLock.readLock().lock();
09e6fd9b
AM
162 try {
163 checkValidAttribute(quark);
086cd39c
MK
164 return new TmfStateInterval(fOngoingStateStartTimes.get(quark), fLatestTime,
165 quark, fOngoingStateInfo.get(quark));
09e6fd9b 166 } finally {
086cd39c 167 fRWLock.readLock().unlock();
09e6fd9b
AM
168 }
169 }
170
171 /**
172 * Try to get the state interval valid for time/quark, if it is present in
173 * this transient state. If it is not (for example, a new value is active
174 * since after the specified timestamp) then null will be returned.
175 *
176 * @param time
177 * The timestamp to look for
178 * @param quark
179 * The quark of the attribute to look for
180 * @return The corresponding TmfStateInterval object if we could find it in
181 * this transient state, or null if we couldn't.
182 */
feea3b3c 183 public @Nullable ITmfStateInterval getIntervalAt(long time, int quark) {
086cd39c 184 fRWLock.readLock().lock();
09e6fd9b
AM
185 try {
186 checkValidAttribute(quark);
086cd39c 187 if (!isActive() || time < fOngoingStateStartTimes.get(quark)) {
09e6fd9b
AM
188 return null;
189 }
086cd39c
MK
190 return new TmfStateInterval(fOngoingStateStartTimes.get(quark),
191 fLatestTime, quark, fOngoingStateInfo.get(quark));
09e6fd9b
AM
192 } catch (AttributeNotFoundException e) {
193 return null;
194 } finally {
086cd39c 195 fRWLock.readLock().unlock();
09e6fd9b 196 }
a52fde77
AM
197 }
198
602c0697 199 private void checkValidAttribute(int quark) throws AttributeNotFoundException {
086cd39c 200 if (quark > fOngoingStateInfo.size() - 1 || quark < 0) {
a52fde77
AM
201 throw new AttributeNotFoundException();
202 }
203 }
204
205 /**
66866869 206 * More advanced version of {@link #changeOngoingStateValue}. Replaces the
a6917276
AM
207 * complete ongoingStateInfo in one go, and updates the
208 * ongoingStateStartTimes and #stateValuesTypes accordingly. BE VERY CAREFUL
209 * WITH THIS!
97042f0a 210 *
66866869
AM
211 * @param newStateIntervals
212 * The List of intervals that will represent the new
213 * "ongoing state". Their end times don't matter, we will only
214 * check their value and start times.
a52fde77 215 */
09e6fd9b
AM
216 public void replaceOngoingState(List<ITmfStateInterval> newStateIntervals) {
217 final int size = newStateIntervals.size();
218
086cd39c 219 fRWLock.writeLock().lock();
09e6fd9b 220 try {
086cd39c
MK
221 fOngoingStateInfo = new ArrayList<>(size);
222 fOngoingStateStartTimes = new ArrayList<>(size);
223 fStateValueTypes = new ArrayList<>(size);
09e6fd9b
AM
224
225 for (ITmfStateInterval interval : newStateIntervals) {
086cd39c
MK
226 fOngoingStateInfo.add(interval.getStateValue());
227 fOngoingStateStartTimes.add(interval.getStartTime());
228 fStateValueTypes.add(interval.getStateValue().getType());
09e6fd9b
AM
229 }
230 } finally {
086cd39c 231 fRWLock.writeLock().unlock();
66866869 232 }
a52fde77
AM
233 }
234
235 /**
236 * Add an "empty line" to both "ongoing..." vectors. This is needed so the
237 * Ongoing... tables can stay in sync with the number of attributes in the
238 * attribute tree, namely when we add sub-path attributes.
239 */
09e6fd9b 240 public void addEmptyEntry() {
086cd39c 241 fRWLock.writeLock().lock();
09e6fd9b
AM
242 try {
243 /*
244 * Since this is a new attribute, we suppose it was in the
245 * "null state" since the beginning (so we can have intervals
246 * covering for all timestamps). A null interval will then get added
247 * at the first state change.
248 */
086cd39c
MK
249 fOngoingStateInfo.add(TmfStateValue.nullValue());
250 fStateValueTypes.add(Type.NULL);
a52fde77 251
086cd39c 252 fOngoingStateStartTimes.add(fBackend.getStartTime());
09e6fd9b 253 } finally {
086cd39c 254 fRWLock.writeLock().unlock();
09e6fd9b 255 }
a52fde77
AM
256 }
257
258 /**
a6917276 259 * Process a state change to be inserted in the history.
97042f0a 260 *
a52fde77
AM
261 * @param eventTime
262 * The timestamp associated with this state change
a6917276
AM
263 * @param value
264 * The new StateValue associated to this attribute
265 * @param quark
266 * The quark of the attribute that is being modified
a52fde77 267 * @throws TimeRangeException
a6917276 268 * If 'eventTime' is invalid
a52fde77 269 * @throws AttributeNotFoundException
a6917276 270 * IF 'quark' does not represent an existing attribute
97042f0a 271 * @throws StateValueTypeException
a6917276
AM
272 * If the state value to be inserted is of a different type of
273 * what was inserted so far for this attribute.
a52fde77 274 */
09e6fd9b
AM
275 public void processStateChange(long eventTime, ITmfStateValue value, int quark)
276 throws TimeRangeException, AttributeNotFoundException, StateValueTypeException {
086cd39c 277 if (!this.fIsActive) {
feea3b3c
AM
278 return;
279 }
97042f0a 280
086cd39c 281 fRWLock.writeLock().lock();
09e6fd9b 282 try {
086cd39c 283 Type expectedSvType = fStateValueTypes.get(quark);
09e6fd9b 284 checkValidAttribute(quark);
97042f0a 285
97042f0a 286 /*
09e6fd9b
AM
287 * Make sure the state value type we're inserting is the same as the
288 * one registered for this attribute.
7e0b2b56 289 */
09e6fd9b
AM
290 if (expectedSvType == Type.NULL) {
291 /*
292 * The value hasn't been used yet, set it to the value we're
293 * currently inserting (which might be null/-1 again).
294 */
086cd39c 295 fStateValueTypes.set(quark, value.getType());
09e6fd9b
AM
296 } else if ((value.getType() != Type.NULL) && (value.getType() != expectedSvType)) {
297 /*
298 * We authorize inserting null values in any type of attribute,
299 * but for every other types, it needs to match our
300 * expectations!
301 */
302 throw new StateValueTypeException();
303 }
a52fde77 304
086cd39c 305 if (fOngoingStateInfo.get(quark).equals(value)) {
09e6fd9b
AM
306 /*
307 * This is the case where the new value and the one already
308 * present in the Builder are the same. We do not need to create
309 * an interval, we'll just keep the current one going.
310 */
311 return;
312 }
a52fde77 313
086cd39c 314 if (fOngoingStateStartTimes.get(quark) < eventTime) {
09e6fd9b
AM
315 /*
316 * These two conditions are necessary to create an interval and
317 * update ongoingStateInfo.
318 */
086cd39c 319 fBackend.insertPastState(fOngoingStateStartTimes.get(quark),
09e6fd9b
AM
320 eventTime - 1, /* End Time */
321 quark, /* attribute quark */
086cd39c 322 fOngoingStateInfo.get(quark)); /* StateValue */
a52fde77 323
086cd39c 324 fOngoingStateStartTimes.set(quark, eventTime);
09e6fd9b 325 }
086cd39c 326 fOngoingStateInfo.set(quark, value);
09e6fd9b
AM
327
328 /* Update the Transient State's lastestTime, if needed */
086cd39c
MK
329 if (fLatestTime < eventTime) {
330 fLatestTime = eventTime;
09e6fd9b 331 }
a52fde77 332
09e6fd9b 333 } finally {
086cd39c 334 fRWLock.writeLock().unlock();
a52fde77 335 }
a52fde77
AM
336 }
337
338 /**
339 * Run a "get state at time" query on the Transient State only.
97042f0a 340 *
a52fde77
AM
341 * @param stateInfo
342 * The stateInfo object in which we will put our relevant
343 * information
344 * @param t
345 * The requested timestamp
346 */
a6917276 347 public void doQuery(List<ITmfStateInterval> stateInfo, long t) {
086cd39c 348 fRWLock.readLock().lock();
09e6fd9b 349 try {
086cd39c 350 if (!this.fIsActive) {
09e6fd9b
AM
351 return;
352 }
086cd39c 353 if (stateInfo.size() > fOngoingStateInfo.size()) {
7f0344d8
GB
354 throw new IllegalArgumentException();
355 }
a52fde77 356
7f0344d8 357 for (int i = 0; i < stateInfo.size(); i++) {
09e6fd9b 358 /*
feea3b3c
AM
359 * We build a dummy interval whose end time =
360 * "current transient state end time" to put in the answer to
361 * the query.
09e6fd9b
AM
362 */
363 final ITmfStateInterval interval = getIntervalAt(t, i);
364 if (interval != null) {
365 stateInfo.set(i, interval);
366 }
a52fde77 367 }
09e6fd9b 368 } finally {
086cd39c 369 fRWLock.readLock().unlock();
a52fde77
AM
370 }
371 }
372
373 /**
a6917276
AM
374 * Close off the Transient State, used for example when we are done reading
375 * a static trace file. All the information currently contained in it will
376 * be converted to intervals and "flushed" to the state history.
377 *
378 * @param endTime
379 * The timestamp to use as end time for the state history (since
380 * it may be different than the timestamp of the last state
381 * change)
a52fde77 382 */
a6917276 383 public void closeTransientState(long endTime) {
086cd39c 384 if (!this.fIsActive) {
feea3b3c
AM
385 return;
386 }
387
086cd39c 388 fRWLock.writeLock().lock();
09e6fd9b 389 try {
086cd39c
MK
390 for (int i = 0; i < fOngoingStateInfo.size(); i++) {
391 if (fOngoingStateStartTimes.get(i) > endTime) {
09e6fd9b
AM
392 /*
393 * Handle the cases where trace end > timestamp of last
394 * state change. This can happen when inserting "future"
395 * changes.
396 */
397 continue;
398 }
399 try {
086cd39c 400 fBackend.insertPastState(fOngoingStateStartTimes.get(i),
09e6fd9b
AM
401 endTime, /* End Time */
402 i, /* attribute quark */
086cd39c 403 fOngoingStateInfo.get(i)); /* StateValue */
09e6fd9b
AM
404
405 } catch (TimeRangeException e) {
406 /*
407 * This shouldn't happen, since we control where the
408 * interval's start time comes from
409 */
410 throw new IllegalStateException(e);
411 }
a52fde77 412 }
a52fde77 413
086cd39c
MK
414 fOngoingStateInfo.clear();
415 fOngoingStateStartTimes.clear();
416 this.fIsActive = false;
a52fde77 417
09e6fd9b 418 } finally {
086cd39c 419 fRWLock.writeLock().unlock();
09e6fd9b 420 }
a52fde77
AM
421 }
422
423 /**
424 * Simply returns if this Transient State is currently being used or not
97042f0a 425 *
a6917276 426 * @return True if this transient state is active
a52fde77 427 */
a6917276 428 public boolean isActive() {
086cd39c 429 return this.fIsActive;
a52fde77
AM
430 }
431
a6917276
AM
432 /**
433 * Mark this transient state as inactive
434 */
435 public void setInactive() {
086cd39c 436 fIsActive = false;
a52fde77
AM
437 }
438
439 /**
a6917276 440 * Debugging method that prints the contents of the transient state
97042f0a 441 *
a52fde77 442 * @param writer
a6917276 443 * The writer to which the output should be written
a52fde77 444 */
a6917276 445 public void debugPrint(PrintWriter writer) {
a52fde77
AM
446 /* Only used for debugging, shouldn't be externalized */
447 writer.println("------------------------------"); //$NON-NLS-1$
448 writer.println("Info stored in the Builder:"); //$NON-NLS-1$
086cd39c 449 if (!this.fIsActive) {
a52fde77
AM
450 writer.println("Builder is currently inactive"); //$NON-NLS-1$
451 writer.println('\n');
452 return;
453 }
454 writer.println("\nAttribute\tStateValue\tValid since time"); //$NON-NLS-1$
086cd39c 455 for (int i = 0; i < fOngoingStateInfo.size(); i++) {
a52fde77 456 writer.format("%d\t\t", i); //$NON-NLS-1$
086cd39c
MK
457 writer.print(fOngoingStateInfo.get(i).toString() + "\t\t"); //$NON-NLS-1$
458 writer.println(fOngoingStateStartTimes.get(i).toString());
a52fde77
AM
459 }
460 writer.println('\n');
461 return;
462 }
463
faa38350 464}
This page took 0.083891 seconds and 5 git commands to generate.