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