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