1 /*******************************************************************************
2 * Copyright (c) 2013, 2015 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é
37 public final class TmfStateSystemOperations
{
39 private TmfStateSystemOperations() {}
42 * Return the maximum value of an attribute over a time range
45 * The state system to query
47 * The start time of the range
49 * The end time of the range
51 * The quark of the attribute
52 * @return The maximum value of the attribute in this range
53 * @throws TimeRangeException
54 * If an invalid time range is specified
55 * @throws AttributeNotFoundException
56 * If the specified quark doesn't match an attribute
57 * @throws StateValueTypeException
58 * If the state value type of the attribute does not support the
61 public static ITmfStateValue
queryRangeMax(ITmfStateSystem ss
, long t1
, long t2
, int quark
)
62 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
63 ITmfStateValue max
= TmfStateValue
.nullValue();
65 List
<ITmfStateInterval
> intervals
= queryAttributeRange(ss
, t1
, t2
, quark
, AbstractTmfMipmapStateProvider
.MAX_STRING
);
66 if (intervals
.size() == 0) {
67 return TmfStateValue
.nullValue();
69 for (ITmfStateInterval si
: intervals
) {
70 ITmfStateValue value
= si
.getStateValue();
72 switch (value
.getType()) {
74 if (max
.isNull() || si
.getStateValue().unboxDouble() > max
.unboxDouble()) {
75 max
= si
.getStateValue();
81 if (max
.isNull() || si
.getStateValue().unboxLong() > max
.unboxLong()) {
82 max
= si
.getStateValue();
89 throw new StateValueTypeException(ss
.getSSID() + " Quark:" + quark
+ ", Type:" + value
.getType()); //$NON-NLS-1$ //$NON-NLS-2$
96 * Return the minimum value of an attribute over a time range
99 * The state system to query
101 * The start time of the range
103 * The end time of the range
105 * The quark of the attribute
106 * @return The minimum value of the attribute in this range
107 * @throws TimeRangeException
108 * If an invalid time range is specified
109 * @throws AttributeNotFoundException
110 * If the specified quark doesn't match an attribute
111 * @throws StateValueTypeException
112 * If the state value type of the attribute does not support the
115 public static ITmfStateValue
queryRangeMin(ITmfStateSystem ss
,
116 long t1
, long t2
, int quark
)
117 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
118 ITmfStateValue min
= TmfStateValue
.nullValue();
120 List
<ITmfStateInterval
> intervals
= queryAttributeRange(ss
, t1
, t2
, quark
, AbstractTmfMipmapStateProvider
.MIN_STRING
);
121 if (intervals
.size() == 0) {
122 return TmfStateValue
.nullValue();
124 for (ITmfStateInterval si
: intervals
) {
125 ITmfStateValue value
= si
.getStateValue();
127 switch (value
.getType()) {
129 if (min
.isNull() || si
.getStateValue().unboxDouble() < min
.unboxDouble()) {
130 min
= si
.getStateValue();
136 if (min
.isNull() || si
.getStateValue().unboxLong() < min
.unboxLong()) {
137 min
= si
.getStateValue();
144 throw new StateValueTypeException(ss
.getSSID() + " Quark:" + quark
+ ", Type:" + value
.getType()); //$NON-NLS-1$ //$NON-NLS-2$
151 * Return the weighted average value of an attribute over a time range
154 * The state system to query
156 * The start time of the range
158 * The end time of the range
160 * The quark of the attribute
161 * @return The weighted average value of the attribute in this range
162 * @throws TimeRangeException
163 * If an invalid time range is specified
164 * @throws AttributeNotFoundException
165 * If the specified quark doesn't match an attribute
166 * @throws StateValueTypeException
167 * If the state value type of the attribute does not support the
168 * "Average" operation
170 public static double queryRangeAverage(ITmfStateSystem ss
, long t1
, long t2
, int quark
)
171 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
173 List
<ITmfStateInterval
> intervals
= queryAttributeRange(ss
, t1
, t2
, quark
, AbstractTmfMipmapStateProvider
.AVG_STRING
);
174 if (intervals
.size() == 0) {
176 } else if (t1
== t2
) {
177 ITmfStateValue value
= intervals
.get(0).getStateValue();
178 if (value
.getType() == Type
.DOUBLE
) {
179 return value
.unboxDouble();
181 return value
.unboxLong();
183 for (ITmfStateInterval si
: intervals
) {
184 long startTime
= Math
.max(t1
, si
.getStartTime());
185 long endTime
= Math
.min(t2
, si
.getEndTime() + 1);
186 long delta
= endTime
- startTime
;
188 ITmfStateValue value
= si
.getStateValue();
189 if (value
.getType() == Type
.DOUBLE
) {
190 avg
+= si
.getStateValue().unboxDouble() * ((double) delta
/ (double) (t2
- t1
));
192 avg
+= si
.getStateValue().unboxLong() * ((double) delta
/ (double) (t2
- t1
));
199 private static List
<ITmfStateInterval
> queryAttributeRange(ITmfStateSystem ss
,
200 long t1
, long t2
, int baseQuark
, String featureString
)
201 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
202 TimeRange timeRange
= new TimeRange(t1
, t2
);
203 int mipmapQuark
= -1;
204 List
<ITmfStateInterval
> intervals
= new ArrayList
<>();
207 mipmapQuark
= ss
.getQuarkRelative(baseQuark
, featureString
);
208 } catch (AttributeNotFoundException e
) {
209 /* Not a mipmap attribute, query the base attribute */
211 ITmfStateInterval interval
= ss
.querySingleState(t1
, baseQuark
);
212 if (!interval
.getStateValue().isNull()) {
213 intervals
.add(interval
);
216 for (ITmfStateInterval interval
: StateSystemUtils
.queryHistoryRange(ss
, baseQuark
, t1
, t2
)) {
217 if (!interval
.getStateValue().isNull()) {
218 intervals
.add(interval
);
224 ITmfStateInterval maxLevelInterval
= ss
.querySingleState(timeRange
.getSecond(), mipmapQuark
);
225 int levelMax
= maxLevelInterval
.getStateValue().unboxInt();
226 queryMipmapAttributeRange(ss
, 0, levelMax
, baseQuark
, mipmapQuark
, timeRange
, intervals
);
229 } catch (StateValueTypeException e
) {
230 /* This is a special case, so we'll add a message to the exception */
231 throw new StateValueTypeException("State system advertises mipmaps," + //$NON-NLS-1$
232 " but doesn't actually have them.", e
); //$NON-NLS-1$
233 } catch (StateSystemDisposedException e
) {
234 /* We are shutting down, ignore the operation */
239 private static void queryMipmapAttributeRange(ITmfStateSystem ss
,
240 int currentLevel
, int levelMax
, int baseQuark
, int mipmapQuark
,
241 TimeRange timeRange
, List
<ITmfStateInterval
> intervals
)
242 throws AttributeNotFoundException
, TimeRangeException
{
243 int level
= currentLevel
;
244 TimeRange range
= timeRange
;
245 ITmfStateInterval currentLevelInterval
= null, nextLevelInterval
= null;
246 if (range
== null || range
.getFirst() > range
.getSecond()) {
249 if (level
> levelMax
|| level
< 0) {
253 if (range
.getFirst() == range
.getSecond()) {
255 currentLevelInterval
= ss
.querySingleState(range
.getFirst(), baseQuark
);
256 if (!currentLevelInterval
.getStateValue().isNull()) {
257 intervals
.add(currentLevelInterval
);
261 if (level
< levelMax
) {
262 int levelQuark
= ss
.getQuarkRelative(mipmapQuark
, String
.valueOf(level
+ 1));
263 nextLevelInterval
= ss
.querySingleState(range
.getFirst(), levelQuark
);
266 if (nextLevelInterval
!= null && isFullyOverlapped(range
, nextLevelInterval
)) {
267 if (nextLevelInterval
.getStateValue().isNull()) {
268 range
= updateTimeRange(range
, nextLevelInterval
);
272 queryMipmapAttributeRange(ss
, level
, levelMax
, baseQuark
, mipmapQuark
, range
, intervals
);
277 currentLevelInterval
= ss
.querySingleState(range
.getFirst(), baseQuark
);
279 int levelQuark
= ss
.getQuarkRelative(mipmapQuark
, String
.valueOf(level
));
280 currentLevelInterval
= ss
.querySingleState(range
.getFirst(), levelQuark
);
283 if (isFullyOverlapped(range
, currentLevelInterval
)) {
284 if (!currentLevelInterval
.getStateValue().isNull()) {
285 intervals
.add(currentLevelInterval
);
287 range
= updateTimeRange(range
, currentLevelInterval
);
290 if (!currentLevelInterval
.getStateValue().isNull()) {
291 intervals
.add(currentLevelInterval
);
293 range
= updateTimeRange(range
, currentLevelInterval
);
299 queryMipmapAttributeRange(ss
, level
, levelMax
, baseQuark
,
300 mipmapQuark
, range
, intervals
);
302 } catch (StateSystemDisposedException e
) {
303 /* We are shutting down, ignore the operation */
307 private static TimeRange
updateTimeRange(TimeRange timeRange
,
308 ITmfStateInterval currentLevelInterval
) {
309 if (currentLevelInterval
.getEndTime() >= timeRange
.getSecond()) {
312 long startTime
= Math
.max(timeRange
.getFirst(),
313 Math
.min(currentLevelInterval
.getEndTime() + 1, timeRange
.getSecond()));
314 return new TimeRange(startTime
, timeRange
.getSecond());
317 private static boolean isFullyOverlapped(TimeRange range
,
318 ITmfStateInterval interval
) {
319 if (range
.getFirst() >= range
.getSecond() ||
320 interval
.getStartTime() >= interval
.getEndTime()) {
323 if (range
.getFirst() <= interval
.getStartTime() &&
324 range
.getSecond() >= interval
.getEndTime()) {
333 private final long a
;
334 private final long b
;
336 public TimeRange(long first
, long second
) {
341 public long getFirst() {
345 public long getSecond() {