1 /*******************************************************************************
2 * Copyright (c) 2013, 2014 Ericsson
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 * Jean-Christian Kouamé - Initial API and implementation
11 * Patrick Tasse - Updates to mipmap feature
12 ******************************************************************************/
14 package org
.eclipse
.tracecompass
.internal
.tmf
.core
.statesystem
.mipmap
;
16 import java
.util
.ArrayList
;
17 import java
.util
.List
;
19 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
20 import org
.eclipse
.tracecompass
.statesystem
.core
.StateSystemUtils
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
23 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
24 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
25 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
.Type
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
32 * This class implements additional statistical operations that can be
33 * performed on attributes of the state system.
35 * @author Patrick Tassé
38 public final class TmfStateSystemOperations
{
40 private TmfStateSystemOperations() {}
43 * Return the maximum value of an attribute over a time range
46 * The state system to query
48 * The start time of the range
50 * The end time of the range
52 * The quark of the attribute
53 * @return The maximum value of the attribute in this range
54 * @throws TimeRangeException
55 * If an invalid time range is specified
56 * @throws AttributeNotFoundException
57 * If the specified quark doesn't match an attribute
58 * @throws StateValueTypeException
59 * If the state value type of the attribute does not support the
62 public static ITmfStateValue
queryRangeMax(ITmfStateSystem ss
, long t1
, long t2
, int quark
)
63 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
64 ITmfStateValue max
= TmfStateValue
.nullValue();
66 List
<ITmfStateInterval
> intervals
= queryAttributeRange(ss
, t1
, t2
, quark
, AbstractTmfMipmapStateProvider
.MAX_STRING
);
67 if (intervals
.size() == 0) {
68 return TmfStateValue
.nullValue();
70 for (ITmfStateInterval si
: intervals
) {
71 ITmfStateValue value
= si
.getStateValue();
73 switch (value
.getType()) {
75 if (max
.isNull() || si
.getStateValue().unboxDouble() > max
.unboxDouble()) {
76 max
= si
.getStateValue();
82 if (max
.isNull() || si
.getStateValue().unboxLong() > max
.unboxLong()) {
83 max
= si
.getStateValue();
90 throw new StateValueTypeException();
97 * Return the minimum value of an attribute over a time range
100 * The state system to query
102 * The start time of the range
104 * The end time of the range
106 * The quark of the attribute
107 * @return The minimum value of the attribute in this range
108 * @throws TimeRangeException
109 * If an invalid time range is specified
110 * @throws AttributeNotFoundException
111 * If the specified quark doesn't match an attribute
112 * @throws StateValueTypeException
113 * If the state value type of the attribute does not support the
116 public static ITmfStateValue
queryRangeMin(ITmfStateSystem ss
,
117 long t1
, long t2
, int quark
)
118 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
119 ITmfStateValue min
= TmfStateValue
.nullValue();
121 List
<ITmfStateInterval
> intervals
= queryAttributeRange(ss
, t1
, t2
, quark
, AbstractTmfMipmapStateProvider
.MIN_STRING
);
122 if (intervals
.size() == 0) {
123 return TmfStateValue
.nullValue();
125 for (ITmfStateInterval si
: intervals
) {
126 ITmfStateValue value
= si
.getStateValue();
128 switch (value
.getType()) {
130 if (min
.isNull() || si
.getStateValue().unboxDouble() < min
.unboxDouble()) {
131 min
= si
.getStateValue();
137 if (min
.isNull() || si
.getStateValue().unboxLong() < min
.unboxLong()) {
138 min
= si
.getStateValue();
145 throw new StateValueTypeException();
152 * Return the weighted average value of an attribute over a time range
155 * The state system to query
157 * The start time of the range
159 * The end time of the range
161 * The quark of the attribute
162 * @return The weighted average value of the attribute in this range
163 * @throws TimeRangeException
164 * If an invalid time range is specified
165 * @throws AttributeNotFoundException
166 * If the specified quark doesn't match an attribute
167 * @throws StateValueTypeException
168 * If the state value type of the attribute does not support the
169 * "Average" operation
171 public static double queryRangeAverage(ITmfStateSystem ss
, long t1
, long t2
, int quark
)
172 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
174 List
<ITmfStateInterval
> intervals
= queryAttributeRange(ss
, t1
, t2
, quark
, AbstractTmfMipmapStateProvider
.AVG_STRING
);
175 if (intervals
.size() == 0) {
177 } else if (t1
== t2
) {
178 ITmfStateValue value
= intervals
.get(0).getStateValue();
179 if (value
.getType() == Type
.DOUBLE
) {
180 return value
.unboxDouble();
182 return value
.unboxLong();
184 for (ITmfStateInterval si
: intervals
) {
185 long startTime
= Math
.max(t1
, si
.getStartTime());
186 long endTime
= Math
.min(t2
, si
.getEndTime() + 1);
187 long delta
= endTime
- startTime
;
189 ITmfStateValue value
= si
.getStateValue();
190 if (value
.getType() == Type
.DOUBLE
) {
191 avg
+= si
.getStateValue().unboxDouble() * ((double) delta
/ (double) (t2
- t1
));
193 avg
+= si
.getStateValue().unboxLong() * ((double) delta
/ (double) (t2
- t1
));
200 private static List
<ITmfStateInterval
> queryAttributeRange(ITmfStateSystem ss
,
201 long t1
, long t2
, int baseQuark
, String featureString
)
202 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
203 TimeRange timeRange
= new TimeRange(t1
, t2
);
204 int mipmapQuark
= -1;
205 List
<ITmfStateInterval
> intervals
= new ArrayList
<>();
208 mipmapQuark
= ss
.getQuarkRelative(baseQuark
, featureString
);
209 } catch (AttributeNotFoundException e
) {
210 /* Not a mipmap attribute, query the base attribute */
212 ITmfStateInterval interval
= ss
.querySingleState(t1
, baseQuark
);
213 if (!interval
.getStateValue().isNull()) {
214 intervals
.add(interval
);
217 for (ITmfStateInterval interval
: StateSystemUtils
.queryHistoryRange(ss
, baseQuark
, t1
, t2
)) {
218 if (!interval
.getStateValue().isNull()) {
219 intervals
.add(interval
);
225 ITmfStateInterval maxLevelInterval
= ss
.querySingleState(timeRange
.getSecond(), mipmapQuark
);
226 int levelMax
= maxLevelInterval
.getStateValue().unboxInt();
227 queryMipmapAttributeRange(ss
, 0, levelMax
, baseQuark
, mipmapQuark
, timeRange
, intervals
);
230 } catch (StateValueTypeException e
) {
231 /* This is a special case, so we'll add a message to the exception */
232 throw new StateValueTypeException("State system advertises mipmaps," + //$NON-NLS-1$
233 " but doesn't actually have them.", e
); //$NON-NLS-1$
234 } catch (StateSystemDisposedException e
) {
235 /* We are shutting down, ignore the operation */
240 private static void queryMipmapAttributeRange(ITmfStateSystem ss
,
241 int currentLevel
, int levelMax
, int baseQuark
, int mipmapQuark
,
242 TimeRange timeRange
, List
<ITmfStateInterval
> intervals
)
243 throws AttributeNotFoundException
, TimeRangeException
{
244 int level
= currentLevel
;
245 TimeRange range
= timeRange
;
246 ITmfStateInterval currentLevelInterval
= null, nextLevelInterval
= null;
247 if (range
== null || range
.getFirst() > range
.getSecond()) {
250 if (level
> levelMax
|| level
< 0) {
254 if (range
.getFirst() == range
.getSecond()) {
256 currentLevelInterval
= ss
.querySingleState(range
.getFirst(), baseQuark
);
257 if (!currentLevelInterval
.getStateValue().isNull()) {
258 intervals
.add(currentLevelInterval
);
262 if (level
< levelMax
) {
263 int levelQuark
= ss
.getQuarkRelative(mipmapQuark
, String
.valueOf(level
+ 1));
264 nextLevelInterval
= ss
.querySingleState(range
.getFirst(), levelQuark
);
267 if (nextLevelInterval
!= null && isFullyOverlapped(range
, nextLevelInterval
)) {
268 if (nextLevelInterval
.getStateValue().isNull()) {
269 range
= updateTimeRange(range
, nextLevelInterval
);
273 queryMipmapAttributeRange(ss
, level
, levelMax
, baseQuark
, mipmapQuark
, range
, intervals
);
278 currentLevelInterval
= ss
.querySingleState(range
.getFirst(), baseQuark
);
280 int levelQuark
= ss
.getQuarkRelative(mipmapQuark
, String
.valueOf(level
));
281 currentLevelInterval
= ss
.querySingleState(range
.getFirst(), levelQuark
);
284 if (currentLevelInterval
!= null && isFullyOverlapped(range
, currentLevelInterval
)) {
285 if (!currentLevelInterval
.getStateValue().isNull()) {
286 intervals
.add(currentLevelInterval
);
288 range
= updateTimeRange(range
, currentLevelInterval
);
291 if (currentLevelInterval
== null) {
294 if (!currentLevelInterval
.getStateValue().isNull()) {
295 intervals
.add(currentLevelInterval
);
297 range
= updateTimeRange(range
, currentLevelInterval
);
303 queryMipmapAttributeRange(ss
, level
, levelMax
, baseQuark
,
304 mipmapQuark
, range
, intervals
);
306 } catch (StateSystemDisposedException e
) {
307 /* We are shutting down, ignore the operation */
311 private static TimeRange
updateTimeRange(TimeRange timeRange
,
312 ITmfStateInterval currentLevelInterval
) {
313 if (currentLevelInterval
.getEndTime() >= timeRange
.getSecond()) {
316 long startTime
= Math
.max(timeRange
.getFirst(),
317 Math
.min(currentLevelInterval
.getEndTime() + 1, timeRange
.getSecond()));
318 return new TimeRange(startTime
, timeRange
.getSecond());
321 private static boolean isFullyOverlapped(TimeRange range
,
322 ITmfStateInterval interval
) {
323 if (range
.getFirst() >= range
.getSecond() ||
324 interval
.getStartTime() >= interval
.getEndTime()) {
327 if (range
.getFirst() <= interval
.getStartTime() &&
328 range
.getSecond() >= interval
.getEndTime()) {
337 private final long a
;
338 private final long b
;
340 public TimeRange(long first
, long second
) {
345 public long getFirst() {
349 public long getSecond() {