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
.linuxtools
.internal
.tmf
.core
.statesystem
.mipmap
;
16 import java
.util
.ArrayList
;
17 import java
.util
.List
;
19 import org
.eclipse
.linuxtools
.statesystem
.core
.ITmfStateSystem
;
20 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
21 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
22 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.StateValueTypeException
;
23 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.TimeRangeException
;
24 import org
.eclipse
.linuxtools
.statesystem
.core
.interval
.ITmfStateInterval
;
25 import org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
.ITmfStateValue
;
26 import org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
.TmfStateValue
;
27 import org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
.ITmfStateValue
.Type
;
30 * This class implements additional statistical operations that can be
31 * performed on attributes of the state system.
33 * @author Patrick Tassé
36 public final class TmfStateSystemOperations
{
38 private TmfStateSystemOperations() {}
41 * Return the maximum value of an attribute over a time range
44 * The state system to query
46 * The start time of the range
48 * The end time of the range
50 * The quark of the attribute
51 * @return The maximum value of the attribute in this range
52 * @throws TimeRangeException
53 * If an invalid time range is specified
54 * @throws AttributeNotFoundException
55 * If the specified quark doesn't match an attribute
56 * @throws StateValueTypeException
57 * If the state value type of the attribute does not support the
60 public static ITmfStateValue
queryRangeMax(ITmfStateSystem ss
, long t1
, long t2
, int quark
)
61 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
62 ITmfStateValue max
= TmfStateValue
.nullValue();
64 List
<ITmfStateInterval
> intervals
= queryAttributeRange(ss
, t1
, t2
, quark
, AbstractTmfMipmapStateProvider
.MAX_STRING
);
65 if (intervals
.size() == 0) {
66 return TmfStateValue
.nullValue();
68 for (ITmfStateInterval si
: intervals
) {
69 ITmfStateValue value
= si
.getStateValue();
71 switch (value
.getType()) {
73 if (max
.isNull() || si
.getStateValue().unboxDouble() > max
.unboxDouble()) {
74 max
= si
.getStateValue();
80 if (max
.isNull() || si
.getStateValue().unboxLong() > max
.unboxLong()) {
81 max
= si
.getStateValue();
88 throw new StateValueTypeException();
95 * Return the minimum value of an attribute over a time range
98 * The state system to query
100 * The start time of the range
102 * The end time of the range
104 * The quark of the attribute
105 * @return The minimum value of the attribute in this range
106 * @throws TimeRangeException
107 * If an invalid time range is specified
108 * @throws AttributeNotFoundException
109 * If the specified quark doesn't match an attribute
110 * @throws StateValueTypeException
111 * If the state value type of the attribute does not support the
114 public static ITmfStateValue
queryRangeMin(ITmfStateSystem ss
,
115 long t1
, long t2
, int quark
)
116 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
117 ITmfStateValue min
= TmfStateValue
.nullValue();
119 List
<ITmfStateInterval
> intervals
= queryAttributeRange(ss
, t1
, t2
, quark
, AbstractTmfMipmapStateProvider
.MIN_STRING
);
120 if (intervals
.size() == 0) {
121 return TmfStateValue
.nullValue();
123 for (ITmfStateInterval si
: intervals
) {
124 ITmfStateValue value
= si
.getStateValue();
126 switch (value
.getType()) {
128 if (min
.isNull() || si
.getStateValue().unboxDouble() < min
.unboxDouble()) {
129 min
= si
.getStateValue();
135 if (min
.isNull() || si
.getStateValue().unboxLong() < min
.unboxLong()) {
136 min
= si
.getStateValue();
143 throw new StateValueTypeException();
150 * Return the weighted average value of an attribute over a time range
153 * The state system to query
155 * The start time of the range
157 * The end time of the range
159 * The quark of the attribute
160 * @return The weighted average value of the attribute in this range
161 * @throws TimeRangeException
162 * If an invalid time range is specified
163 * @throws AttributeNotFoundException
164 * If the specified quark doesn't match an attribute
165 * @throws StateValueTypeException
166 * If the state value type of the attribute does not support the
167 * "Average" operation
169 public static double queryRangeAverage(ITmfStateSystem ss
, long t1
, long t2
, int quark
)
170 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
172 List
<ITmfStateInterval
> intervals
= queryAttributeRange(ss
, t1
, t2
, quark
, AbstractTmfMipmapStateProvider
.AVG_STRING
);
173 if (intervals
.size() == 0) {
175 } else if (t1
== t2
) {
176 ITmfStateValue value
= intervals
.get(0).getStateValue();
177 if (value
.getType() == Type
.DOUBLE
) {
178 return value
.unboxDouble();
180 return value
.unboxLong();
182 for (ITmfStateInterval si
: intervals
) {
183 long startTime
= Math
.max(t1
, si
.getStartTime());
184 long endTime
= Math
.min(t2
, si
.getEndTime() + 1);
185 long delta
= endTime
- startTime
;
187 ITmfStateValue value
= si
.getStateValue();
188 if (value
.getType() == Type
.DOUBLE
) {
189 avg
+= si
.getStateValue().unboxDouble() * ((double) delta
/ (double) (t2
- t1
));
191 avg
+= si
.getStateValue().unboxLong() * ((double) delta
/ (double) (t2
- t1
));
198 private static List
<ITmfStateInterval
> queryAttributeRange(ITmfStateSystem ss
,
199 long t1
, long t2
, int baseQuark
, String featureString
)
200 throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
201 TimeRange timeRange
= new TimeRange(t1
, t2
);
202 int mipmapQuark
= -1;
203 List
<ITmfStateInterval
> intervals
= new ArrayList
<>();
206 mipmapQuark
= ss
.getQuarkRelative(baseQuark
, featureString
);
207 } catch (AttributeNotFoundException e
) {
208 /* Not a mipmap attribute, query the base attribute */
210 ITmfStateInterval interval
= ss
.querySingleState(t1
, baseQuark
);
211 if (!interval
.getStateValue().isNull()) {
212 intervals
.add(interval
);
215 for (ITmfStateInterval interval
: ss
.queryHistoryRange(baseQuark
, t1
, t2
)) {
216 if (!interval
.getStateValue().isNull()) {
217 intervals
.add(interval
);
223 ITmfStateInterval maxLevelInterval
= ss
.querySingleState(timeRange
.getSecond(), mipmapQuark
);
224 int levelMax
= maxLevelInterval
.getStateValue().unboxInt();
225 queryMipmapAttributeRange(ss
, 0, levelMax
, baseQuark
, mipmapQuark
, timeRange
, intervals
);
228 } catch (StateValueTypeException e
) {
229 /* This is a special case, so we'll add a message to the exception */
230 throw new StateValueTypeException("State system advertises mipmaps," + //$NON-NLS-1$
231 " but doesn't actually have them.", e
); //$NON-NLS-1$
232 } catch (StateSystemDisposedException e
) {
233 /* We are shutting down, ignore the operation */
238 private static void queryMipmapAttributeRange(ITmfStateSystem ss
,
239 int currentLevel
, int levelMax
, int baseQuark
, int mipmapQuark
,
240 TimeRange timeRange
, List
<ITmfStateInterval
> intervals
)
241 throws AttributeNotFoundException
, TimeRangeException
{
242 int level
= currentLevel
;
243 TimeRange range
= timeRange
;
244 ITmfStateInterval currentLevelInterval
= null, nextLevelInterval
= null;
245 if (range
== null || range
.getFirst() > range
.getSecond()) {
248 if (level
> levelMax
|| level
< 0) {
252 if (range
.getFirst() == range
.getSecond()) {
254 currentLevelInterval
= ss
.querySingleState(range
.getFirst(), baseQuark
);
255 if (!currentLevelInterval
.getStateValue().isNull()) {
256 intervals
.add(currentLevelInterval
);
260 if (level
< levelMax
) {
261 int levelQuark
= ss
.getQuarkRelative(mipmapQuark
, String
.valueOf(level
+ 1));
262 nextLevelInterval
= ss
.querySingleState(range
.getFirst(), levelQuark
);
265 if (nextLevelInterval
!= null && isFullyOverlapped(range
, nextLevelInterval
)) {
266 if (nextLevelInterval
.getStateValue().isNull()) {
267 range
= updateTimeRange(range
, nextLevelInterval
);
271 queryMipmapAttributeRange(ss
, level
, levelMax
, baseQuark
, mipmapQuark
, range
, intervals
);
276 currentLevelInterval
= ss
.querySingleState(range
.getFirst(), baseQuark
);
278 int levelQuark
= ss
.getQuarkRelative(mipmapQuark
, String
.valueOf(level
));
279 currentLevelInterval
= ss
.querySingleState(range
.getFirst(), levelQuark
);
282 if (currentLevelInterval
!= null && isFullyOverlapped(range
, currentLevelInterval
)) {
283 if (!currentLevelInterval
.getStateValue().isNull()) {
284 intervals
.add(currentLevelInterval
);
286 range
= updateTimeRange(range
, currentLevelInterval
);
289 if (currentLevelInterval
== null) {
292 if (!currentLevelInterval
.getStateValue().isNull()) {
293 intervals
.add(currentLevelInterval
);
295 range
= updateTimeRange(range
, currentLevelInterval
);
301 queryMipmapAttributeRange(ss
, level
, levelMax
, baseQuark
,
302 mipmapQuark
, range
, intervals
);
304 } catch (StateSystemDisposedException e
) {
305 /* We are shutting down, ignore the operation */
309 private static TimeRange
updateTimeRange(TimeRange timeRange
,
310 ITmfStateInterval currentLevelInterval
) {
311 if (currentLevelInterval
.getEndTime() >= timeRange
.getSecond()) {
314 long startTime
= Math
.max(timeRange
.getFirst(),
315 Math
.min(currentLevelInterval
.getEndTime() + 1, timeRange
.getSecond()));
316 return new TimeRange(startTime
, timeRange
.getSecond());
319 private static boolean isFullyOverlapped(TimeRange range
,
320 ITmfStateInterval interval
) {
321 if (range
.getFirst() >= range
.getSecond() ||
322 interval
.getStartTime() >= interval
.getEndTime()) {
325 if (range
.getFirst() <= interval
.getStartTime() &&
326 range
.getSecond() >= interval
.getEndTime()) {
335 private final long a
;
336 private final long b
;
338 public TimeRange(long first
, long second
) {
343 public long getFirst() {
347 public long getSecond() {