1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 É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 * Patrick Tasse - Add message to exceptions
13 *******************************************************************************/
15 package org
.eclipse
.tracecompass
.statesystem
.core
;
17 import java
.util
.ArrayList
;
18 import java
.util
.LinkedList
;
19 import java
.util
.List
;
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
;
33 * Provide utility methods for the state system
35 * @author Geneviève Bastien
38 public final class StateSystemUtils
{
40 private StateSystemUtils() {
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().
49 * To retrieve the other values in a stack, you can query the sub-attributes
53 * The state system to query
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
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
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();
76 if (curStackStateValue
.isNull()) {
77 /* There is nothing stored in this stack at this moment */
80 int curStackDepth
= curStackStateValue
.unboxInt();
81 if (curStackDepth
<= 0) {
83 * This attribute is an integer attribute, but it doesn't seem like
84 * it's used as a stack-attribute...
86 throw new StateValueTypeException(ss
.getSSID() + " Quark:" + stackAttributeQuark
+ ", Stack depth:" + curStackDepth
); //$NON-NLS-1$//$NON-NLS-2$
89 int subAttribQuark
= ss
.getQuarkRelative(stackAttributeQuark
, String
.valueOf(curStackDepth
));
90 return ss
.querySingleState(t
, subAttribQuark
);
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
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()).
103 * The state system to query
104 * @param attributeQuark
105 * Which attribute this query is interested in
107 * Start time of the range query
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
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
120 public static List
<ITmfStateInterval
> queryHistoryRange(ITmfStateSystem ss
,
121 int attributeQuark
, long t1
, long t2
)
122 throws AttributeNotFoundException
, StateSystemDisposedException
{
124 List
<ITmfStateInterval
> intervals
;
125 ITmfStateInterval currentInterval
;
128 /* Make sure the time range makes sense */
130 throw new TimeRangeException(ss
.getSSID() + " Start:" + t1
+ ", End:" + t2
); //$NON-NLS-1$ //$NON-NLS-2$
133 /* Set the actual, valid end time of the range query */
134 if (t2
> ss
.getCurrentEndTime()) {
135 tEnd
= ss
.getCurrentEndTime();
140 /* Get the initial state at time T1 */
141 intervals
= new ArrayList
<>();
142 currentInterval
= ss
.querySingleState(t1
, attributeQuark
);
143 intervals
.add(currentInterval
);
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();
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.
163 * The state system to query
164 * @param attributeQuark
165 * Which attribute this query is interested in
167 * Start time of the range query
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
173 * The "step" of this query
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
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
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;
195 /* Make sure the time range makes sense */
196 if (t2
< t1
|| resolution
<= 0) {
197 throw new TimeRangeException(ss
.getSSID() + " Start:" + t1
+ ", End:" + t2
+ ", Resolution:" + resolution
); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
200 /* Set the actual, valid end time of the range query */
201 if (t2
> ss
.getCurrentEndTime()) {
202 tEnd
= ss
.getCurrentEndTime();
207 IProgressMonitor mon
= monitor
;
209 mon
= new NullProgressMonitor();
213 * Iterate over the "resolution points". We skip unneeded queries in the
214 * case the current interval is longer than the resolution.
216 for (ts
= t1
; ts
<= tEnd
; ts
+= ((currentInterval
.getEndTime() - ts
) / resolution
+ 1) * resolution
) {
217 if (mon
.isCanceled()) {
220 currentInterval
= ss
.querySingleState(ts
, attributeQuark
);
221 intervals
.add(currentInterval
);
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
);
233 * Queries intervals in the state system for a given attribute, starting at
234 * time t1, until we obtain a non-null value.
237 * The state system on which to query intervals
238 * @param attributeQuark
239 * The attribute quark to query
241 * Start time of the query
243 * Time limit of the query. Use {@link Long#MAX_VALUE} for no
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.
249 public static @Nullable ITmfStateInterval
queryUntilNonNullValue(ITmfStateSystem ss
,
250 int attributeQuark
, long t1
, long t2
) {
253 /* Make sure the range is ok */
254 if (t1
< ss
.getStartTime()) {
255 current
= ss
.getStartTime();
258 if (end
< ss
.getCurrentEndTime()) {
259 end
= ss
.getCurrentEndTime();
261 /* Make sure the time range makes sense */
267 while (current
< t2
) {
268 ITmfStateInterval currentInterval
= ss
.querySingleState(current
, attributeQuark
);
269 ITmfStateValue value
= currentInterval
.getStateValue();
271 if (!value
.isNull()) {
272 return currentInterval
;
274 current
= currentInterval
.getEndTime() + 1;
276 } catch (AttributeNotFoundException
| StateSystemDisposedException
| TimeRangeException e
) {