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