Commit | Line | Data |
---|---|---|
1dd75589 | 1 | /******************************************************************************* |
ed48dc75 | 2 | * Copyright (c) 2014, 2016 École Polytechnique de Montréal |
1dd75589 AM |
3 | * |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * Geneviève Bastien - Initial API and implementation | |
11 | * Alexandre Montplaisir - Initial API and implementation | |
e13bd4cd | 12 | * Patrick Tasse - Add message to exceptions |
1dd75589 AM |
13 | *******************************************************************************/ |
14 | ||
15 | package org.eclipse.tracecompass.statesystem.core; | |
16 | ||
17 | import java.util.ArrayList; | |
18 | import java.util.LinkedList; | |
19 | import java.util.List; | |
20 | ||
21 | import org.eclipse.core.runtime.IProgressMonitor; | |
22 | import org.eclipse.core.runtime.NullProgressMonitor; | |
23 | import org.eclipse.jdt.annotation.NonNullByDefault; | |
24 | import org.eclipse.jdt.annotation.Nullable; | |
25 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; | |
26 | import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; | |
27 | import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; | |
28 | import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; | |
29 | import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; | |
30 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; | |
31 | ||
32 | /** | |
33 | * Provide utility methods for the state system | |
34 | * | |
35 | * @author Geneviève Bastien | |
36 | */ | |
37 | @NonNullByDefault | |
38 | public final class StateSystemUtils { | |
39 | ||
40 | private StateSystemUtils() { | |
41 | } | |
42 | ||
43 | /** | |
44 | * Convenience method to query attribute stacks (created with | |
45 | * pushAttribute()/popAttribute()). This will return the interval that is | |
46 | * currently at the top of the stack, or 'null' if that stack is currently | |
47 | * empty. It works similarly to querySingleState(). | |
48 | * | |
49 | * To retrieve the other values in a stack, you can query the sub-attributes | |
50 | * manually. | |
51 | * | |
52 | * @param ss | |
53 | * The state system to query | |
54 | * @param t | |
55 | * The timestamp of the query | |
56 | * @param stackAttributeQuark | |
57 | * The top-level stack-attribute (that was the target of | |
58 | * pushAttribute() at creation time) | |
59 | * @return The interval that was at the top of the stack, or 'null' if the | |
60 | * stack was empty. | |
61 | * @throws StateValueTypeException | |
62 | * If the target attribute is not a valid stack attribute (if it | |
63 | * has a string value for example) | |
64 | * @throws AttributeNotFoundException | |
65 | * If the attribute was simply not found | |
66 | * @throws TimeRangeException | |
67 | * If the given timestamp is invalid | |
68 | * @throws StateSystemDisposedException | |
69 | * If the query is sent after the state system has been disposed | |
70 | */ | |
71 | public static @Nullable ITmfStateInterval querySingleStackTop(ITmfStateSystem ss, | |
72 | long t, int stackAttributeQuark) | |
73 | throws AttributeNotFoundException, StateSystemDisposedException { | |
74 | ITmfStateValue curStackStateValue = ss.querySingleState(t, stackAttributeQuark).getStateValue(); | |
75 | ||
76 | if (curStackStateValue.isNull()) { | |
77 | /* There is nothing stored in this stack at this moment */ | |
78 | return null; | |
79 | } | |
80 | int curStackDepth = curStackStateValue.unboxInt(); | |
81 | if (curStackDepth <= 0) { | |
82 | /* | |
83 | * This attribute is an integer attribute, but it doesn't seem like | |
84 | * it's used as a stack-attribute... | |
85 | */ | |
e13bd4cd | 86 | throw new StateValueTypeException(ss.getSSID() + " Quark:" + stackAttributeQuark + ", Stack depth:" + curStackDepth); //$NON-NLS-1$//$NON-NLS-2$ |
1dd75589 AM |
87 | } |
88 | ||
89 | int subAttribQuark = ss.getQuarkRelative(stackAttributeQuark, String.valueOf(curStackDepth)); | |
90 | return ss.querySingleState(t, subAttribQuark); | |
91 | } | |
92 | ||
93 | /** | |
94 | * Return a list of state intervals, containing the "history" of a given | |
95 | * attribute between timestamps t1 and t2. The list will be ordered by | |
96 | * ascending time. | |
97 | * | |
98 | * Note that contrary to queryFullState(), the returned list here is in the | |
99 | * "direction" of time (and not in the direction of attributes, as is the | |
100 | * case with queryFullState()). | |
101 | * | |
102 | * @param ss | |
103 | * The state system to query | |
104 | * @param attributeQuark | |
105 | * Which attribute this query is interested in | |
106 | * @param t1 | |
107 | * Start time of the range query | |
108 | * @param t2 | |
109 | * Target end time of the query. If t2 is greater than the end of | |
110 | * the trace, we will return what we have up to the end of the | |
111 | * history. | |
112 | * @return The List of state intervals that happened between t1 and t2 | |
113 | * @throws TimeRangeException | |
114 | * If t1 is invalid, or if t2 <= t1 | |
115 | * @throws AttributeNotFoundException | |
116 | * If the requested quark does not exist in the model. | |
117 | * @throws StateSystemDisposedException | |
118 | * If the query is sent after the state system has been disposed | |
119 | */ | |
120 | public static List<ITmfStateInterval> queryHistoryRange(ITmfStateSystem ss, | |
121 | int attributeQuark, long t1, long t2) | |
122 | throws AttributeNotFoundException, StateSystemDisposedException { | |
123 | ||
124 | List<ITmfStateInterval> intervals; | |
125 | ITmfStateInterval currentInterval; | |
126 | long ts, tEnd; | |
127 | ||
128 | /* Make sure the time range makes sense */ | |
129 | if (t2 < t1) { | |
e13bd4cd | 130 | throw new TimeRangeException(ss.getSSID() + " Start:" + t1 + ", End:" + t2); //$NON-NLS-1$ //$NON-NLS-2$ |
1dd75589 AM |
131 | } |
132 | ||
133 | /* Set the actual, valid end time of the range query */ | |
134 | if (t2 > ss.getCurrentEndTime()) { | |
135 | tEnd = ss.getCurrentEndTime(); | |
136 | } else { | |
137 | tEnd = t2; | |
138 | } | |
139 | ||
140 | /* Get the initial state at time T1 */ | |
141 | intervals = new ArrayList<>(); | |
142 | currentInterval = ss.querySingleState(t1, attributeQuark); | |
143 | intervals.add(currentInterval); | |
144 | ||
145 | /* Get the following state changes */ | |
146 | ts = currentInterval.getEndTime(); | |
147 | while (ts != -1 && ts < tEnd) { | |
148 | ts++; /* To "jump over" to the next state in the history */ | |
149 | currentInterval = ss.querySingleState(ts, attributeQuark); | |
150 | intervals.add(currentInterval); | |
151 | ts = currentInterval.getEndTime(); | |
152 | } | |
153 | return intervals; | |
154 | } | |
155 | ||
156 | /** | |
157 | * Return the state history of a given attribute, but with at most one | |
158 | * update per "resolution". This can be useful for populating views (where | |
159 | * it's useless to have more than one query per pixel, for example). A | |
160 | * progress monitor can be used to cancel the query before completion. | |
161 | * | |
162 | * @param ss | |
163 | * The state system to query | |
164 | * @param attributeQuark | |
165 | * Which attribute this query is interested in | |
166 | * @param t1 | |
167 | * Start time of the range query | |
168 | * @param t2 | |
169 | * Target end time of the query. If t2 is greater than the end of | |
170 | * the trace, we will return what we have up to the end of the | |
171 | * history. | |
172 | * @param resolution | |
173 | * The "step" of this query | |
174 | * @param monitor | |
175 | * A progress monitor. If the monitor is canceled during a query, | |
176 | * we will return what has been found up to that point. You can | |
177 | * use "null" if you do not want to use one. | |
178 | * @return The List of states that happened between t1 and t2 | |
179 | * @throws TimeRangeException | |
180 | * If t1 is invalid, if t2 <= t1, or if the resolution isn't | |
181 | * greater than zero. | |
182 | * @throws AttributeNotFoundException | |
183 | * If the attribute doesn't exist | |
184 | * @throws StateSystemDisposedException | |
185 | * If the query is sent after the state system has been disposed | |
186 | */ | |
187 | public static List<ITmfStateInterval> queryHistoryRange(ITmfStateSystem ss, | |
188 | int attributeQuark, long t1, long t2, long resolution, | |
189 | @Nullable IProgressMonitor monitor) | |
190 | throws AttributeNotFoundException, StateSystemDisposedException { | |
191 | List<ITmfStateInterval> intervals = new LinkedList<>(); | |
192 | ITmfStateInterval currentInterval = null; | |
193 | long ts, tEnd; | |
194 | ||
195 | /* Make sure the time range makes sense */ | |
196 | if (t2 < t1 || resolution <= 0) { | |
e13bd4cd | 197 | throw new TimeRangeException(ss.getSSID() + " Start:" + t1 + ", End:" + t2 + ", Resolution:" + resolution); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
1dd75589 AM |
198 | } |
199 | ||
200 | /* Set the actual, valid end time of the range query */ | |
201 | if (t2 > ss.getCurrentEndTime()) { | |
202 | tEnd = ss.getCurrentEndTime(); | |
203 | } else { | |
204 | tEnd = t2; | |
205 | } | |
206 | ||
207 | IProgressMonitor mon = monitor; | |
208 | if (mon == null) { | |
209 | mon = new NullProgressMonitor(); | |
210 | } | |
211 | ||
212 | /* | |
213 | * Iterate over the "resolution points". We skip unneeded queries in the | |
214 | * case the current interval is longer than the resolution. | |
215 | */ | |
216 | for (ts = t1; ts <= tEnd; ts += ((currentInterval.getEndTime() - ts) / resolution + 1) * resolution) { | |
217 | if (mon.isCanceled()) { | |
218 | return intervals; | |
219 | } | |
220 | currentInterval = ss.querySingleState(ts, attributeQuark); | |
221 | intervals.add(currentInterval); | |
222 | } | |
223 | ||
224 | /* Add the interval at t2, if it wasn't included already. */ | |
225 | if (currentInterval != null && currentInterval.getEndTime() < tEnd) { | |
226 | currentInterval = ss.querySingleState(tEnd, attributeQuark); | |
227 | intervals.add(currentInterval); | |
228 | } | |
229 | return intervals; | |
230 | } | |
231 | ||
232 | /** | |
233 | * Queries intervals in the state system for a given attribute, starting at | |
234 | * time t1, until we obtain a non-null value. | |
235 | * | |
236 | * @param ss | |
237 | * The state system on which to query intervals | |
238 | * @param attributeQuark | |
239 | * The attribute quark to query | |
240 | * @param t1 | |
241 | * Start time of the query | |
242 | * @param t2 | |
243 | * Time limit of the query. Use {@link Long#MAX_VALUE} for no | |
244 | * limit. | |
245 | * @return The first interval from t1 for which the value is not a null | |
246 | * value, or <code>null</code> if no interval was found once we | |
247 | * reach either t2 or the end time of the state system. | |
248 | */ | |
249 | public static @Nullable ITmfStateInterval queryUntilNonNullValue(ITmfStateSystem ss, | |
250 | int attributeQuark, long t1, long t2) { | |
251 | ||
252 | long current = t1; | |
253 | /* Make sure the range is ok */ | |
254 | if (t1 < ss.getStartTime()) { | |
255 | current = ss.getStartTime(); | |
256 | } | |
257 | long end = t2; | |
258 | if (end < ss.getCurrentEndTime()) { | |
259 | end = ss.getCurrentEndTime(); | |
260 | } | |
261 | /* Make sure the time range makes sense */ | |
262 | if (end < current) { | |
263 | return null; | |
264 | } | |
265 | ||
266 | try { | |
267 | while (current < t2) { | |
268 | ITmfStateInterval currentInterval = ss.querySingleState(current, attributeQuark); | |
269 | ITmfStateValue value = currentInterval.getStateValue(); | |
270 | ||
271 | if (!value.isNull()) { | |
272 | return currentInterval; | |
273 | } | |
274 | current = currentInterval.getEndTime() + 1; | |
275 | } | |
ed48dc75 | 276 | } catch (StateSystemDisposedException | TimeRangeException e) { |
1dd75589 AM |
277 | /* Nothing to do */ |
278 | } | |
279 | return null; | |
280 | } | |
281 | ||
282 | } |