tmf: Add a method to query an ongoing state's start time
[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;
27
28/**
7e0b2b56 29 * The Transient State is used to build intervals from punctual state changes. It
a52fde77
AM
30 * contains a "state info" vector similar to the "current state", except here we
31 * also record the start time of every state stored in it.
97042f0a 32 *
a52fde77
AM
33 * We can then build StateInterval's, to be inserted in the State History when
34 * we detect state changes : the "start time" of the interval will be the
35 * recorded time we have here, and the "end time" will be the timestamp of the
36 * new state-changing event we just read.
97042f0a 37 *
a52fde77 38 * @author alexmont
97042f0a 39 *
a52fde77
AM
40 */
41class TransientState {
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
49 private ArrayList<ITmfStateValue> ongoingStateInfo;
7e0b2b56
AM
50 private final ArrayList<Long> ongoingStateStartTimes;
51 private final ArrayList<Byte> stateValueTypes;
a52fde77
AM
52
53 TransientState(IStateHistoryBackend backend) {
54 this.backend = backend;
55 isActive = true;
56 ongoingStateInfo = new ArrayList<ITmfStateValue>();
57 ongoingStateStartTimes = new ArrayList<Long>();
7e0b2b56 58 stateValueTypes = new ArrayList<Byte>();
a52fde77
AM
59
60 if (backend != null) {
61 latestTime = backend.getStartTime();
62 } else {
63 latestTime = 0;
64 }
65 }
66
67 long getLatestTime() {
68 return latestTime;
69 }
70
602c0697 71 ITmfStateValue getOngoingStateValue(int index) throws AttributeNotFoundException {
a52fde77
AM
72 checkValidAttribute(index);
73 return ongoingStateInfo.get(index);
74 }
75
602c0697
AM
76 long getOngoingStartTime(int index) throws AttributeNotFoundException {
77 checkValidAttribute(index);
78 return ongoingStateStartTimes.get(index);
79 }
80
a52fde77
AM
81 void changeOngoingStateValue(int index, ITmfStateValue newValue)
82 throws AttributeNotFoundException {
a52fde77
AM
83 checkValidAttribute(index);
84 ongoingStateInfo.set(index, newValue);
85 }
86
87 /**
88 * Return the "ongoing" value for a given attribute as a dummy interval
89 * whose end time = -1 (since we don't know its real end time yet).
97042f0a 90 *
a52fde77
AM
91 * @param quark
92 * @throws AttributeNotFoundException
93 */
602c0697 94 ITmfStateInterval getOngoingInterval(int quark) throws AttributeNotFoundException {
a52fde77
AM
95 checkValidAttribute(quark);
96 return new TmfStateInterval(ongoingStateStartTimes.get(quark), -1, quark,
97 ongoingStateInfo.get(quark));
98 }
99
602c0697 100 private void checkValidAttribute(int quark) throws AttributeNotFoundException {
a52fde77
AM
101 if (quark > ongoingStateInfo.size() - 1 || quark < 0) {
102 throw new AttributeNotFoundException();
103 }
104 }
105
106 /**
107 * Batch method of changeOngoingStateValue(), updates the complete
108 * ongoingStateInfo in one go. BE VERY CAREFUL WITH THIS! Especially with
109 * the sizes of both arrays.
97042f0a 110 *
a52fde77
AM
111 * Note that the new ongoingStateInfo will be a shallow copy of
112 * newStateInfo, so that last one must be already instantiated and all.
97042f0a 113 *
a52fde77
AM
114 * @param newStateInfo
115 * The List of StateValues to replace the old ongoingStateInfo
116 * one.
117 */
118 void changeOngoingStateInfo(ArrayList<ITmfStateValue> newStateInfo) {
119 this.ongoingStateInfo = newStateInfo;
120 }
121
122 /**
123 * Add an "empty line" to both "ongoing..." vectors. This is needed so the
124 * Ongoing... tables can stay in sync with the number of attributes in the
125 * attribute tree, namely when we add sub-path attributes.
126 */
127 synchronized void addEmptyEntry() {
128 /*
129 * Since this is a new attribute, we suppose it was in the "null state"
130 * since the beginning (so we can have intervals covering for all
131 * timestamps). A null interval will then get added at the first state
132 * change.
133 */
134 ongoingStateInfo.add(TmfStateValue.nullValue());
7e0b2b56 135 stateValueTypes.add((byte) -1);
a52fde77
AM
136
137 if (backend == null) {
138 ongoingStateStartTimes.add(0L);
139 } else {
140 ongoingStateStartTimes.add(backend.getStartTime());
141 }
142 }
143
144 /**
145 * Ask if the state information about attribute 'quark' at time 'time' is
146 * present in the Builder as it is right now. If it's not, it's either in
147 * the History Tree, or not in the system at all.
97042f0a 148 *
a52fde77
AM
149 * Note that this method does not return the value itself (we don't even
150 * look for it, we can know by just looking at the timestamp)
97042f0a 151 *
a52fde77
AM
152 * @param time
153 * The timestamp to look for
154 * @param quark
155 * The quark of the attribute to look for
156 * @return True if the value is present in the Transient State at this
157 * moment in time, false if it's not
158 */
159 boolean hasInfoAboutStateOf(long time, int quark) {
160 return (this.isActive() && time >= ongoingStateStartTimes.get(quark));
161 }
162
163 /**
164 * This is the lower-level method that will be called by the
165 * StateHistorySystem (with already-built StateValues and timestamps)
97042f0a 166 *
a52fde77
AM
167 * @param index
168 * The index in the vectors (== the quark of the attribute)
169 * @param value
170 * The new StateValue associated to this attribute
171 * @param eventTime
172 * The timestamp associated with this state change
173 * @throws TimeRangeException
174 * @throws AttributeNotFoundException
97042f0a 175 * @throws StateValueTypeException
a52fde77
AM
176 */
177 synchronized void processStateChange(long eventTime,
178 ITmfStateValue value, int index) throws TimeRangeException,
7e0b2b56 179 AttributeNotFoundException, StateValueTypeException {
a52fde77 180 assert (this.isActive);
97042f0a 181
7e0b2b56 182 byte expectedSvType = stateValueTypes.get(index);
a52fde77 183 checkValidAttribute(index);
97042f0a
AM
184
185 /*
7e0b2b56
AM
186 * Make sure the state value type we're inserting is the same as the
187 * one registered for this attribute.
188 */
189 if (expectedSvType == -1) {
97042f0a 190 /*
7e0b2b56
AM
191 * The value hasn't been used yet, set it to the value
192 * we're currently inserting (which might be null/-1 again).
193 */
194 stateValueTypes.set(index, value.getType());
195 } else if ((value.getType() != -1) && (value.getType() != expectedSvType)) {
97042f0a 196 /*
7e0b2b56
AM
197 * We authorize inserting null values in any type of attribute,
198 * but for every other types, it needs to match our expectations!
199 */
200 throw new StateValueTypeException();
201 }
a52fde77 202
7e0b2b56 203 /* Update the Transient State's lastestTime, if needed */
a52fde77
AM
204 if (latestTime < eventTime) {
205 latestTime = eventTime;
206 }
207
208 if (ongoingStateInfo.get(index).equals(value)) {
209 /*
210 * This is the case where the new value and the one already present
211 * in the Builder are the same. We do not need to create an
212 * interval, we'll just keep the current one going.
213 */
214 return;
215 }
216
217 if (backend != null && ongoingStateStartTimes.get(index) < eventTime) {
218 /*
219 * These two conditions are necessary to create an interval and
220 * update ongoingStateInfo.
221 */
7e0b2b56 222 backend.insertPastState(ongoingStateStartTimes.get(index),
a52fde77
AM
223 eventTime - 1, /* End Time */
224 index, /* attribute quark */
225 ongoingStateInfo.get(index)); /* StateValue */
226
227 ongoingStateStartTimes.set(index, eventTime);
228 }
229 ongoingStateInfo.set(index, value);
230 return;
231 }
232
233 /**
234 * Run a "get state at time" query on the Transient State only.
97042f0a 235 *
a52fde77
AM
236 * @param stateInfo
237 * The stateInfo object in which we will put our relevant
238 * information
239 * @param t
240 * The requested timestamp
241 */
242 void doQuery(List<ITmfStateInterval> stateInfo, long t) {
243 ITmfStateInterval interval;
244
245 if (!this.isActive) {
246 return;
247 }
248 assert (stateInfo.size() == ongoingStateInfo.size());
249
250 for (int i = 0; i < ongoingStateInfo.size(); i++) {
251 /*
252 * We build a dummy interval with end time = -1 to put in the answer
253 * to the query.
254 */
255 if (this.hasInfoAboutStateOf(t, i)) {
256 interval = new TmfStateInterval(ongoingStateStartTimes.get(i), -1,
257 i, ongoingStateInfo.get(i));
258 stateInfo.set(i, interval);
259 }
260 }
261 }
262
263 /**
264 * Close off the Transient State, used for example when we are done reading a
265 * static trace file. All the information currently contained in it will be
266 * converted to intervals and "flushed" to the State History.
267 */
268 void closeTransientState(long endTime) {
269 assert (this.isActive);
270
271 for (int i = 0; i < ongoingStateInfo.size(); i++) {
e1c43333 272 if (ongoingStateStartTimes.get(i) > endTime) {
a52fde77 273 /*
faa38350 274 * Handle the cases where trace end > timestamp of last state
97042f0a 275 * change. This can happen when inserting "future" changes.
a52fde77
AM
276 */
277 continue;
278 }
279 try {
7e0b2b56 280 backend.insertPastState(ongoingStateStartTimes.get(i),
a52fde77
AM
281 endTime, /* End Time */
282 i, /* attribute quark */
283 ongoingStateInfo.get(i)); /* StateValue */
284
285 } catch (TimeRangeException e) {
286 /*
287 * This shouldn't happen, since we control where the interval's
288 * start time comes from
289 */
290 e.printStackTrace();
291 }
292 }
293
294 ongoingStateInfo.clear();
295 ongoingStateStartTimes.clear();
296 this.isActive = false;
297 return;
298 }
299
300 /**
301 * Simply returns if this Transient State is currently being used or not
97042f0a 302 *
a52fde77
AM
303 * @return
304 */
305 boolean isActive() {
306 return this.isActive;
307 }
308
309 void setInactive() {
310 isActive = false;
311 }
312
313 /**
314 * Debugging method that prints the contents of both 'ongoing...' vectors
97042f0a 315 *
a52fde77
AM
316 * @param writer
317 */
318 void debugPrint(PrintWriter writer) {
319 /* Only used for debugging, shouldn't be externalized */
320 writer.println("------------------------------"); //$NON-NLS-1$
321 writer.println("Info stored in the Builder:"); //$NON-NLS-1$
322 if (!this.isActive) {
323 writer.println("Builder is currently inactive"); //$NON-NLS-1$
324 writer.println('\n');
325 return;
326 }
327 writer.println("\nAttribute\tStateValue\tValid since time"); //$NON-NLS-1$
328 for (int i = 0; i < ongoingStateInfo.size(); i++) {
329 writer.format("%d\t\t", i); //$NON-NLS-1$
330 writer.print(ongoingStateInfo.get(i).toString() + "\t\t"); //$NON-NLS-1$
331 writer.println(ongoingStateStartTimes.get(i).toString());
332 }
333 writer.println('\n');
334 return;
335 }
336
faa38350 337}
This page took 0.048339 seconds and 5 git commands to generate.