ss: Add a StateSystemUtils for advanced queries
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / internal / tmf / core / statesystem / mipmap / TmfStateSystemOperations.java
CommitLineData
8e364f8e 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2013, 2014 Ericsson
8e364f8e
PT
3 *
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
8 *
9 * Contributors:
10 * Jean-Christian Kouamé - Initial API and implementation
11 * Patrick Tasse - Updates to mipmap feature
12 ******************************************************************************/
13
2bdf0193 14package org.eclipse.tracecompass.internal.tmf.core.statesystem.mipmap;
8e364f8e
PT
15
16import java.util.ArrayList;
17import java.util.List;
18
e894a508 19import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
1dd75589 20import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
e894a508
AM
21import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
22import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
23import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
24import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
25import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
26import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
e894a508 27import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type;
1dd75589
AM
28import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
29
8e364f8e
PT
30
31/**
32 * This class implements additional statistical operations that can be
33 * performed on attributes of the state system.
64d15677
AM
34 *
35 * @author Patrick Tassé
c4767854 36 * @since 3.0
8e364f8e 37 */
64d15677 38public final class TmfStateSystemOperations {
8e364f8e 39
64d15677 40 private TmfStateSystemOperations() {}
8e364f8e
PT
41
42 /**
43 * Return the maximum value of an attribute over a time range
44 *
64d15677
AM
45 * @param ss
46 * The state system to query
8e364f8e
PT
47 * @param t1
48 * The start time of the range
49 * @param t2
50 * The end time of the range
51 * @param quark
52 * The quark of the attribute
53 * @return The maximum value of the attribute in this range
64d15677
AM
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
60 * "Max" operation
8e364f8e 61 */
64d15677
AM
62 public static ITmfStateValue queryRangeMax(ITmfStateSystem ss, long t1, long t2, int quark)
63 throws AttributeNotFoundException, TimeRangeException, StateValueTypeException {
8e364f8e 64 ITmfStateValue max = TmfStateValue.nullValue();
64d15677
AM
65
66 List<ITmfStateInterval> intervals = queryAttributeRange(ss, t1, t2, quark, AbstractTmfMipmapStateProvider.MAX_STRING);
67 if (intervals.size() == 0) {
68 return TmfStateValue.nullValue();
69 }
70 for (ITmfStateInterval si : intervals) {
71 ITmfStateValue value = si.getStateValue();
72
73 switch (value.getType()) {
74 case DOUBLE:
75 if (max.isNull() || si.getStateValue().unboxDouble() > max.unboxDouble()) {
76 max = si.getStateValue();
77 }
78 break;
79
80 case INTEGER:
81 case LONG:
82 if (max.isNull() || si.getStateValue().unboxLong() > max.unboxLong()) {
83 max = si.getStateValue();
8e364f8e 84 }
64d15677
AM
85 break;
86
87 case NULL:
88 case STRING:
89 default:
90 throw new StateValueTypeException();
8e364f8e 91 }
8e364f8e
PT
92 }
93 return max;
94 }
95
96 /**
97 * Return the minimum value of an attribute over a time range
98 *
64d15677
AM
99 * @param ss
100 * The state system to query
8e364f8e
PT
101 * @param t1
102 * The start time of the range
103 * @param t2
104 * The end time of the range
105 * @param quark
106 * The quark of the attribute
107 * @return The minimum value of the attribute in this range
64d15677
AM
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
114 * "Min" operation
8e364f8e 115 */
64d15677
AM
116 public static ITmfStateValue queryRangeMin(ITmfStateSystem ss,
117 long t1, long t2, int quark)
118 throws AttributeNotFoundException, TimeRangeException, StateValueTypeException {
8e364f8e 119 ITmfStateValue min = TmfStateValue.nullValue();
64d15677
AM
120
121 List<ITmfStateInterval> intervals = queryAttributeRange(ss, t1, t2, quark, AbstractTmfMipmapStateProvider.MIN_STRING);
122 if (intervals.size() == 0) {
123 return TmfStateValue.nullValue();
124 }
125 for (ITmfStateInterval si : intervals) {
126 ITmfStateValue value = si.getStateValue();
127
128 switch (value.getType()) {
129 case DOUBLE:
130 if (min.isNull() || si.getStateValue().unboxDouble() < min.unboxDouble()) {
131 min = si.getStateValue();
132 }
133 break;
134
135 case INTEGER:
136 case LONG:
137 if (min.isNull() || si.getStateValue().unboxLong() < min.unboxLong()) {
138 min = si.getStateValue();
8e364f8e 139 }
64d15677
AM
140 break;
141
142 case NULL:
143 case STRING:
144 default:
145 throw new StateValueTypeException();
8e364f8e 146 }
8e364f8e
PT
147 }
148 return min;
149 }
150
151 /**
152 * Return the weighted average value of an attribute over a time range
153 *
64d15677
AM
154 * @param ss
155 * The state system to query
8e364f8e
PT
156 * @param t1
157 * The start time of the range
158 * @param t2
159 * The end time of the range
160 * @param quark
161 * The quark of the attribute
162 * @return The weighted average value of the attribute in this range
64d15677
AM
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
8e364f8e 170 */
64d15677
AM
171 public static double queryRangeAverage(ITmfStateSystem ss, long t1, long t2, int quark)
172 throws AttributeNotFoundException, TimeRangeException, StateValueTypeException {
8e364f8e 173 double avg = 0.0;
64d15677
AM
174 List<ITmfStateInterval> intervals = queryAttributeRange(ss, t1, t2, quark, AbstractTmfMipmapStateProvider.AVG_STRING);
175 if (intervals.size() == 0) {
176 return 0;
177 } else if (t1 == t2) {
178 ITmfStateValue value = intervals.get(0).getStateValue();
179 if (value.getType() == Type.DOUBLE) {
180 return value.unboxDouble();
8e364f8e 181 }
64d15677
AM
182 return value.unboxLong();
183 }
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;
188 if (delta > 0) {
189 ITmfStateValue value = si.getStateValue();
190 if (value.getType() == Type.DOUBLE) {
191 avg += si.getStateValue().unboxDouble() * ((double) delta / (double) (t2 - t1));
192 } else {
193 avg += si.getStateValue().unboxLong() * ((double) delta / (double) (t2 - t1));
8e364f8e
PT
194 }
195 }
8e364f8e
PT
196 }
197 return avg;
198 }
199
64d15677
AM
200 private static List<ITmfStateInterval> queryAttributeRange(ITmfStateSystem ss,
201 long t1, long t2, int baseQuark, String featureString)
202 throws AttributeNotFoundException, TimeRangeException, StateValueTypeException {
0126a8ca 203 TimeRange timeRange = new TimeRange(t1, t2);
8e364f8e 204 int mipmapQuark = -1;
a4524c1b 205 List<ITmfStateInterval> intervals = new ArrayList<>();
8e364f8e
PT
206 try {
207 try {
208 mipmapQuark = ss.getQuarkRelative(baseQuark, featureString);
209 } catch (AttributeNotFoundException e) {
210 /* Not a mipmap attribute, query the base attribute */
211 if (t1 == t2) {
212 ITmfStateInterval interval = ss.querySingleState(t1, baseQuark);
213 if (!interval.getStateValue().isNull()) {
214 intervals.add(interval);
215 }
216 } else {
1dd75589 217 for (ITmfStateInterval interval : StateSystemUtils.queryHistoryRange(ss, baseQuark, t1, t2)) {
8e364f8e
PT
218 if (!interval.getStateValue().isNull()) {
219 intervals.add(interval);
220 }
221 }
222 }
223 return intervals;
224 }
225 ITmfStateInterval maxLevelInterval = ss.querySingleState(timeRange.getSecond(), mipmapQuark);
226 int levelMax = maxLevelInterval.getStateValue().unboxInt();
64d15677 227 queryMipmapAttributeRange(ss, 0, levelMax, baseQuark, mipmapQuark, timeRange, intervals);
8e364f8e 228 return intervals;
64d15677 229
8e364f8e 230 } catch (StateValueTypeException e) {
64d15677
AM
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$
8e364f8e 234 } catch (StateSystemDisposedException e) {
64d15677 235 /* We are shutting down, ignore the operation */
8e364f8e
PT
236 }
237 return intervals;
238 }
239
64d15677
AM
240 private static void queryMipmapAttributeRange(ITmfStateSystem ss,
241 int currentLevel, int levelMax, int baseQuark, int mipmapQuark,
0126a8ca 242 TimeRange timeRange, List<ITmfStateInterval> intervals)
64d15677 243 throws AttributeNotFoundException, TimeRangeException {
8e364f8e 244 int level = currentLevel;
0126a8ca 245 TimeRange range = timeRange;
8e364f8e
PT
246 ITmfStateInterval currentLevelInterval = null, nextLevelInterval = null;
247 if (range == null || range.getFirst() > range.getSecond()) {
248 return;
249 }
250 if (level > levelMax || level < 0) {
251 return;
252 }
253 try {
0126a8ca 254 if (range.getFirst() == range.getSecond()) {
8e364f8e
PT
255 level = 0;
256 currentLevelInterval = ss.querySingleState(range.getFirst(), baseQuark);
257 if (!currentLevelInterval.getStateValue().isNull()) {
258 intervals.add(currentLevelInterval);
259 }
260 return;
261 }
262 if (level < levelMax) {
263 int levelQuark = ss.getQuarkRelative(mipmapQuark, String.valueOf(level + 1));
264 nextLevelInterval = ss.querySingleState(range.getFirst(), levelQuark);
265 }
266
267 if (nextLevelInterval != null && isFullyOverlapped(range, nextLevelInterval)) {
268 if (nextLevelInterval.getStateValue().isNull()) {
269 range = updateTimeRange(range, nextLevelInterval);
270 } else {
271 level++;
272 }
64d15677 273 queryMipmapAttributeRange(ss, level, levelMax, baseQuark, mipmapQuark, range, intervals);
8e364f8e
PT
274 return;
275 }
276
277 if (level == 0) {
278 currentLevelInterval = ss.querySingleState(range.getFirst(), baseQuark);
279 } else {
280 int levelQuark = ss.getQuarkRelative(mipmapQuark, String.valueOf(level));
281 currentLevelInterval = ss.querySingleState(range.getFirst(), levelQuark);
282 }
283
284 if (currentLevelInterval != null && isFullyOverlapped(range, currentLevelInterval)) {
285 if (!currentLevelInterval.getStateValue().isNull()) {
286 intervals.add(currentLevelInterval);
287 }
288 range = updateTimeRange(range, currentLevelInterval);
289 } else {
290 if (level == 0) {
291 if (currentLevelInterval == null) {
292 return;
293 }
294 if (!currentLevelInterval.getStateValue().isNull()) {
295 intervals.add(currentLevelInterval);
296 }
297 range = updateTimeRange(range, currentLevelInterval);
298 } else {
299 level--;
300 }
301 }
302
64d15677
AM
303 queryMipmapAttributeRange(ss, level, levelMax, baseQuark,
304 mipmapQuark, range, intervals);
8e364f8e 305
8e364f8e 306 } catch (StateSystemDisposedException e) {
64d15677 307 /* We are shutting down, ignore the operation */
8e364f8e
PT
308 }
309 }
310
0126a8ca 311 private static TimeRange updateTimeRange(TimeRange timeRange,
64d15677 312 ITmfStateInterval currentLevelInterval) {
8e364f8e
PT
313 if (currentLevelInterval.getEndTime() >= timeRange.getSecond()) {
314 return null;
315 }
64d15677
AM
316 long startTime = Math.max(timeRange.getFirst(),
317 Math.min(currentLevelInterval.getEndTime() + 1, timeRange.getSecond()));
0126a8ca 318 return new TimeRange(startTime, timeRange.getSecond());
8e364f8e
PT
319 }
320
0126a8ca 321 private static boolean isFullyOverlapped(TimeRange range,
64d15677
AM
322 ITmfStateInterval interval) {
323 if (range.getFirst() >= range.getSecond() ||
324 interval.getStartTime() >= interval.getEndTime()) {
8e364f8e
PT
325 return false;
326 }
64d15677
AM
327 if (range.getFirst() <= interval.getStartTime() &&
328 range.getSecond() >= interval.getEndTime()) {
8e364f8e
PT
329 return true;
330 }
331 return false;
332 }
8e364f8e 333}
0126a8ca
AM
334
335class TimeRange {
336
337 private final long a;
338 private final long b;
339
340 public TimeRange(long first, long second) {
341 a = first;
342 b = second;
343 }
344
345 public long getFirst() {
346 return a;
347 }
348
349 public long getSecond() {
350 return b;
351 }
352}
This page took 0.078558 seconds and 5 git commands to generate.