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