tmf: Make StateValueType and TimeRange exceptions into runtime ones
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / statesystem / TmfStateSystemOperations.java
CommitLineData
8e364f8e
PT
1/*******************************************************************************
2 * Copyright (c) 2013 Ericsson
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
14package org.eclipse.linuxtools.tmf.core.statesystem;
15
16import java.util.ArrayList;
17import java.util.List;
18
19import org.eclipse.linuxtools.internal.tmf.core.statesystem.mipmap.AbstractTmfMipmapStateProvider;
20import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
21import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
22import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
23import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
24import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
25import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
26import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue.Type;
27import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
28import org.eclipse.linuxtools.tmf.core.util.Pair;
29
30/**
31 * This class implements additional statistical operations that can be
32 * performed on attributes of the state system.
64d15677
AM
33 *
34 * @author Patrick Tassé
c4767854 35 * @since 3.0
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:
89 throw new StateValueTypeException();
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:
144 throw new StateValueTypeException();
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 {
a4524c1b 202 Pair<Long, Long> timeRange = new Pair<>(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 {
216 for (ITmfStateInterval interval : ss.queryHistoryRange(baseQuark, t1, t2)) {
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,
241 Pair<Long, Long> timeRange, List<ITmfStateInterval> intervals)
242 throws AttributeNotFoundException, TimeRangeException {
8e364f8e
PT
243 int level = currentLevel;
244 Pair<Long, Long> range = timeRange;
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 {
253 if (range.getFirst().longValue() == range.getSecond().longValue()) {
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
283 if (currentLevelInterval != null && isFullyOverlapped(range, currentLevelInterval)) {
284 if (!currentLevelInterval.getStateValue().isNull()) {
285 intervals.add(currentLevelInterval);
286 }
287 range = updateTimeRange(range, currentLevelInterval);
288 } else {
289 if (level == 0) {
290 if (currentLevelInterval == null) {
291 return;
292 }
293 if (!currentLevelInterval.getStateValue().isNull()) {
294 intervals.add(currentLevelInterval);
295 }
296 range = updateTimeRange(range, currentLevelInterval);
297 } else {
298 level--;
299 }
300 }
301
64d15677
AM
302 queryMipmapAttributeRange(ss, level, levelMax, baseQuark,
303 mipmapQuark, range, intervals);
8e364f8e 304
8e364f8e 305 } catch (StateSystemDisposedException e) {
64d15677 306 /* We are shutting down, ignore the operation */
8e364f8e
PT
307 }
308 }
309
64d15677
AM
310 private static Pair<Long, Long> updateTimeRange(Pair<Long, Long> timeRange,
311 ITmfStateInterval currentLevelInterval) {
8e364f8e
PT
312 if (currentLevelInterval.getEndTime() >= timeRange.getSecond()) {
313 return null;
314 }
64d15677
AM
315 long startTime = Math.max(timeRange.getFirst(),
316 Math.min(currentLevelInterval.getEndTime() + 1, timeRange.getSecond()));
a4524c1b 317 return new Pair<>(startTime, timeRange.getSecond());
8e364f8e
PT
318 }
319
64d15677
AM
320 private static boolean isFullyOverlapped(Pair<Long, Long> range,
321 ITmfStateInterval interval) {
322 if (range.getFirst() >= range.getSecond() ||
323 interval.getStartTime() >= interval.getEndTime()) {
8e364f8e
PT
324 return false;
325 }
64d15677
AM
326 if (range.getFirst() <= interval.getStartTime() &&
327 range.getSecond() >= interval.getEndTime()) {
8e364f8e
PT
328 return true;
329 }
330 return false;
331 }
8e364f8e 332}
This page took 0.049783 seconds and 5 git commands to generate.