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