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