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