1 /*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
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
10 * Geneviève Bastien - Initial API and implementation
11 * Alexandre Montplaisir - Initial API and implementation
12 *******************************************************************************/
14 package org
.eclipse
.tracecompass
.statesystem
.core
;
16 import java
.util
.ArrayList
;
17 import java
.util
.LinkedList
;
18 import java
.util
.List
;
20 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
21 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
22 import org
.eclipse
.jdt
.annotation
.NonNullByDefault
;
23 import org
.eclipse
.jdt
.annotation
.Nullable
;
24 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
25 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
29 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
32 * Provide utility methods for the state system
34 * @author Geneviève Bastien
37 public final class StateSystemUtils
{
39 private StateSystemUtils() {
43 * Convenience method to query attribute stacks (created with
44 * pushAttribute()/popAttribute()). This will return the interval that is
45 * currently at the top of the stack, or 'null' if that stack is currently
46 * empty. It works similarly to querySingleState().
48 * To retrieve the other values in a stack, you can query the sub-attributes
52 * The state system to query
54 * The timestamp of the query
55 * @param stackAttributeQuark
56 * The top-level stack-attribute (that was the target of
57 * pushAttribute() at creation time)
58 * @return The interval that was at the top of the stack, or 'null' if the
60 * @throws StateValueTypeException
61 * If the target attribute is not a valid stack attribute (if it
62 * has a string value for example)
63 * @throws AttributeNotFoundException
64 * If the attribute was simply not found
65 * @throws TimeRangeException
66 * If the given timestamp is invalid
67 * @throws StateSystemDisposedException
68 * If the query is sent after the state system has been disposed
70 public static @Nullable ITmfStateInterval
querySingleStackTop(ITmfStateSystem ss
,
71 long t
, int stackAttributeQuark
)
72 throws AttributeNotFoundException
, StateSystemDisposedException
{
73 ITmfStateValue curStackStateValue
= ss
.querySingleState(t
, stackAttributeQuark
).getStateValue();
75 if (curStackStateValue
.isNull()) {
76 /* There is nothing stored in this stack at this moment */
79 int curStackDepth
= curStackStateValue
.unboxInt();
80 if (curStackDepth
<= 0) {
82 * This attribute is an integer attribute, but it doesn't seem like
83 * it's used as a stack-attribute...
85 throw new StateValueTypeException();
88 int subAttribQuark
= ss
.getQuarkRelative(stackAttributeQuark
, String
.valueOf(curStackDepth
));
89 return ss
.querySingleState(t
, subAttribQuark
);
93 * Return a list of state intervals, containing the "history" of a given
94 * attribute between timestamps t1 and t2. The list will be ordered by
97 * Note that contrary to queryFullState(), the returned list here is in the
98 * "direction" of time (and not in the direction of attributes, as is the
99 * case with queryFullState()).
102 * The state system to query
103 * @param attributeQuark
104 * Which attribute this query is interested in
106 * Start time of the range query
108 * Target end time of the query. If t2 is greater than the end of
109 * the trace, we will return what we have up to the end of the
111 * @return The List of state intervals that happened between t1 and t2
112 * @throws TimeRangeException
113 * If t1 is invalid, or if t2 <= t1
114 * @throws AttributeNotFoundException
115 * If the requested quark does not exist in the model.
116 * @throws StateSystemDisposedException
117 * If the query is sent after the state system has been disposed
119 public static List
<ITmfStateInterval
> queryHistoryRange(ITmfStateSystem ss
,
120 int attributeQuark
, long t1
, long t2
)
121 throws AttributeNotFoundException
, StateSystemDisposedException
{
123 List
<ITmfStateInterval
> intervals
;
124 ITmfStateInterval currentInterval
;
127 /* Make sure the time range makes sense */
129 throw new TimeRangeException();
132 /* Set the actual, valid end time of the range query */
133 if (t2
> ss
.getCurrentEndTime()) {
134 tEnd
= ss
.getCurrentEndTime();
139 /* Get the initial state at time T1 */
140 intervals
= new ArrayList
<>();
141 currentInterval
= ss
.querySingleState(t1
, attributeQuark
);
142 intervals
.add(currentInterval
);
144 /* Get the following state changes */
145 ts
= currentInterval
.getEndTime();
146 while (ts
!= -1 && ts
< tEnd
) {
147 ts
++; /* To "jump over" to the next state in the history */
148 currentInterval
= ss
.querySingleState(ts
, attributeQuark
);
149 intervals
.add(currentInterval
);
150 ts
= currentInterval
.getEndTime();
156 * Return the state history of a given attribute, but with at most one
157 * update per "resolution". This can be useful for populating views (where
158 * it's useless to have more than one query per pixel, for example). A
159 * progress monitor can be used to cancel the query before completion.
162 * The state system to query
163 * @param attributeQuark
164 * Which attribute this query is interested in
166 * Start time of the range query
168 * Target end time of the query. If t2 is greater than the end of
169 * the trace, we will return what we have up to the end of the
172 * The "step" of this query
174 * A progress monitor. If the monitor is canceled during a query,
175 * we will return what has been found up to that point. You can
176 * use "null" if you do not want to use one.
177 * @return The List of states that happened between t1 and t2
178 * @throws TimeRangeException
179 * If t1 is invalid, if t2 <= t1, or if the resolution isn't
181 * @throws AttributeNotFoundException
182 * If the attribute doesn't exist
183 * @throws StateSystemDisposedException
184 * If the query is sent after the state system has been disposed
186 public static List
<ITmfStateInterval
> queryHistoryRange(ITmfStateSystem ss
,
187 int attributeQuark
, long t1
, long t2
, long resolution
,
188 @Nullable IProgressMonitor monitor
)
189 throws AttributeNotFoundException
, StateSystemDisposedException
{
190 List
<ITmfStateInterval
> intervals
= new LinkedList
<>();
191 ITmfStateInterval currentInterval
= null;
194 /* Make sure the time range makes sense */
195 if (t2
< t1
|| resolution
<= 0) {
196 throw new TimeRangeException();
199 /* Set the actual, valid end time of the range query */
200 if (t2
> ss
.getCurrentEndTime()) {
201 tEnd
= ss
.getCurrentEndTime();
206 IProgressMonitor mon
= monitor
;
208 mon
= new NullProgressMonitor();
212 * Iterate over the "resolution points". We skip unneeded queries in the
213 * case the current interval is longer than the resolution.
215 for (ts
= t1
; ts
<= tEnd
; ts
+= ((currentInterval
.getEndTime() - ts
) / resolution
+ 1) * resolution
) {
216 if (mon
.isCanceled()) {
219 currentInterval
= ss
.querySingleState(ts
, attributeQuark
);
220 intervals
.add(currentInterval
);
223 /* Add the interval at t2, if it wasn't included already. */
224 if (currentInterval
!= null && currentInterval
.getEndTime() < tEnd
) {
225 currentInterval
= ss
.querySingleState(tEnd
, attributeQuark
);
226 intervals
.add(currentInterval
);
232 * Queries intervals in the state system for a given attribute, starting at
233 * time t1, until we obtain a non-null value.
236 * The state system on which to query intervals
237 * @param attributeQuark
238 * The attribute quark to query
240 * Start time of the query
242 * Time limit of the query. Use {@link Long#MAX_VALUE} for no
244 * @return The first interval from t1 for which the value is not a null
245 * value, or <code>null</code> if no interval was found once we
246 * reach either t2 or the end time of the state system.
248 public static @Nullable ITmfStateInterval
queryUntilNonNullValue(ITmfStateSystem ss
,
249 int attributeQuark
, long t1
, long t2
) {
252 /* Make sure the range is ok */
253 if (t1
< ss
.getStartTime()) {
254 current
= ss
.getStartTime();
257 if (end
< ss
.getCurrentEndTime()) {
258 end
= ss
.getCurrentEndTime();
260 /* Make sure the time range makes sense */
266 while (current
< t2
) {
267 ITmfStateInterval currentInterval
= ss
.querySingleState(current
, attributeQuark
);
268 ITmfStateValue value
= currentInterval
.getStateValue();
270 if (!value
.isNull()) {
271 return currentInterval
;
273 current
= currentInterval
.getEndTime() + 1;
275 } catch (AttributeNotFoundException
| StateSystemDisposedException
| TimeRangeException e
) {