tmf : Add Leaf nodes to the History Tree
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / statistics / TmfStateStatistics.java
CommitLineData
200789b3 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2012, 2014 Ericsson
200789b3
AM
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 * Alexandre Montplaisir - Initial API and implementation
63fe91fb 11 * Patrick Tasse - Fix TimeRangeException
200789b3
AM
12 ******************************************************************************/
13
14package org.eclipse.linuxtools.tmf.core.statistics;
15
200789b3 16import java.util.HashMap;
f3f93fa6 17import java.util.LinkedList;
200789b3
AM
18import java.util.List;
19import java.util.Map;
20
8192f2c6 21import org.eclipse.jdt.annotation.NonNull;
200789b3 22import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
96345c5a 23import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
200789b3
AM
24import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
25import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
200789b3 26import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
200789b3 27import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
200789b3
AM
28
29/**
1c0de632 30 * Implementation of ITmfStatistics which uses a state history for storing its
802017fe
AM
31 * information. In reality, it uses two state histories, one for "event totals"
32 * information (which should ideally use a fast backend), and another one for
33 * the rest (per event type, per CPU, etc.).
1c0de632 34 *
802017fe
AM
35 * Compared to the event-request-based statistics calculations, it adds the
36 * building the history first, but gives much faster response times once built :
37 * Queries are O(log n) wrt the size of the trace, and O(1) wrt to the size of
38 * the time interval selected.
200789b3
AM
39 *
40 * @author Alexandre Montplaisir
41 * @since 2.0
42 */
1c0de632 43public class TmfStateStatistics implements ITmfStatistics {
200789b3 44
802017fe
AM
45 // ------------------------------------------------------------------------
46 // Fields
47 // ------------------------------------------------------------------------
200789b3 48
802017fe
AM
49 /** The event totals state system */
50 private final ITmfStateSystem totalsStats;
51
52 /** The state system for event types */
53 private final ITmfStateSystem typesStats;
54
55 // ------------------------------------------------------------------------
56 // Constructors
57 // ------------------------------------------------------------------------
200789b3
AM
58
59 /**
60 * Constructor
61 *
8192f2c6
AM
62 * @param totals
63 * The state system containing the "totals" information
64 * @param eventTypes
65 * The state system containing the "event types" information
66 * @since 3.0
200789b3 67 */
d6b46913 68 public TmfStateStatistics(@NonNull ITmfStateSystem totals, @NonNull ITmfStateSystem eventTypes) {
8192f2c6
AM
69 this.totalsStats = totals;
70 this.typesStats = eventTypes;
802017fe
AM
71 }
72
6c5e0863 73 /**
8192f2c6
AM
74 * Return the state system containing the "totals" values
75 *
76 * @return The "totals" state system
77 * @since 3.0
78 */
79 public ITmfStateSystem getTotalsSS() {
80 return totalsStats;
81 }
82
83 /**
84 * Return the state system containing the "event types" values
85 *
86 * @return The "event types" state system
87 * @since 3.0
6c5e0863 88 */
8192f2c6
AM
89 public ITmfStateSystem getEventTypesSS() {
90 return typesStats;
e1c43333
AM
91 }
92
200789b3 93 // ------------------------------------------------------------------------
1c0de632 94 // ITmfStatistics
200789b3
AM
95 // ------------------------------------------------------------------------
96
1a4205d9
AM
97 @Override
98 public void dispose() {
802017fe
AM
99 totalsStats.dispose();
100 typesStats.dispose();
1a4205d9
AM
101 }
102
f3f93fa6
AM
103 @Override
104 public List<Long> histogramQuery(final long start, final long end, final int nb) {
a4524c1b 105 final List<Long> list = new LinkedList<>();
f3f93fa6
AM
106 final long increment = (end - start) / nb;
107
2002c638 108 if (totalsStats.isCancelled()) {
802017fe 109 return list;
f3f93fa6
AM
110 }
111
112 /*
113 * We will do one state system query per "border", and save the
114 * differences between each border.
115 */
802017fe 116 long prevTotal = (start == totalsStats.getStartTime()) ? 0 : getEventCountAt(start);
f3f93fa6
AM
117 long curTime = start + increment;
118
119 long curTotal, count;
120 for (int i = 0; i < nb - 1; i++) {
121 curTotal = getEventCountAt(curTime);
122 count = curTotal - prevTotal;
123 list.add(count);
124
125 curTime += increment;
126 prevTotal = curTotal;
127 }
128
129 /*
130 * For the last bucket, we'll stretch its end time to the end time of
131 * the requested range, in case it got truncated down.
132 */
133 curTotal = getEventCountAt(end);
134 count = curTotal - prevTotal;
135 list.add(count);
1c0de632 136
f3f93fa6 137 return list;
1c0de632
AM
138 }
139
200789b3
AM
140 @Override
141 public long getEventsTotal() {
802017fe 142 long endTime = totalsStats.getCurrentEndTime();
e1c43333 143 int count = 0;
df310609
AM
144
145 try {
802017fe
AM
146 final int quark = totalsStats.getQuarkAbsolute(Attributes.TOTAL);
147 count= totalsStats.querySingleState(endTime, quark).getStateValue().unboxInt();
1c0de632
AM
148
149 } catch (TimeRangeException e) {
150 /* Assume there is no events for that range */
151 return 0;
55954069 152 } catch (AttributeNotFoundException | StateValueTypeException | StateSystemDisposedException e) {
96345c5a 153 e.printStackTrace();
200789b3 154 }
df310609 155
e1c43333 156 return count;
200789b3
AM
157 }
158
159 @Override
160 public Map<String, Long> getEventTypesTotal() {
55954069 161 final Map<String, Long> map = new HashMap<>();
802017fe 162 long endTime = typesStats.getCurrentEndTime();
200789b3
AM
163
164 try {
165 /* Get the list of quarks, one for each even type in the database */
802017fe
AM
166 int quark = typesStats.getQuarkAbsolute(Attributes.EVENT_TYPES);
167 List<Integer> quarks = typesStats.getSubAttributes(quark, false);
200789b3
AM
168
169 /* Since we want the total we can look only at the end */
802017fe 170 List<ITmfStateInterval> endState = typesStats.queryFullState(endTime);
200789b3
AM
171
172 String curEventName;
173 long eventCount;
174 for (int typeQuark : quarks) {
802017fe 175 curEventName = typesStats.getAttributeName(typeQuark);
200789b3
AM
176 eventCount = endState.get(typeQuark).getStateValue().unboxInt();
177 map.put(curEventName, eventCount);
178 }
179
180 } catch (TimeRangeException e) {
1c0de632 181 /* Assume there is no events, nothing will be put in the map. */
8192f2c6 182 } catch (AttributeNotFoundException | StateValueTypeException | StateSystemDisposedException e) {
96345c5a 183 e.printStackTrace();
200789b3
AM
184 }
185 return map;
186 }
187
188 @Override
8b260d9f 189 public long getEventsInRange(long start, long end) {
f3f93fa6 190 long startCount;
802017fe 191 if (start == totalsStats.getStartTime()) {
f3f93fa6
AM
192 startCount = 0;
193 } else {
194 /*
195 * We want the events happening at "start" to be included, so we'll
196 * need to query one unit before that point.
197 */
198 startCount = getEventCountAt(start - 1);
200789b3 199 }
f3f93fa6 200 long endCount = getEventCountAt(end);
df310609 201
f3f93fa6 202 return endCount - startCount;
200789b3
AM
203 }
204
205 @Override
8b260d9f 206 public Map<String, Long> getEventTypesInRange(long start, long end) {
55954069
AM
207 final Map<String, Long> map = new HashMap<>();
208 List<Integer> quarks;
200789b3
AM
209
210 /* Make sure the start/end times are within the state history, so we
211 * don't get TimeRange exceptions.
212 */
63fe91fb
PT
213 long startTime = checkStartTime(start, typesStats);
214 long endTime = checkEndTime(end, typesStats);
200789b3
AM
215
216 try {
217 /* Get the list of quarks, one for each even type in the database */
802017fe 218 int quark = typesStats.getQuarkAbsolute(Attributes.EVENT_TYPES);
55954069
AM
219 quarks = typesStats.getSubAttributes(quark, false);
220 } catch (AttributeNotFoundException e) {
221 /*
222 * The state system does not (yet?) have the needed attributes, it
223 * probably means there are no events counted yet. Return the empty
224 * map.
225 */
226 return map;
227 }
200789b3 228
55954069 229 try {
802017fe 230 List<ITmfStateInterval> endState = typesStats.queryFullState(endTime);
200789b3 231
802017fe 232 if (startTime == typesStats.getStartTime()) {
e1c43333
AM
233 /* Only use the values picked up at the end time */
234 for (int typeQuark : quarks) {
55954069
AM
235 String curEventName = typesStats.getAttributeName(typeQuark);
236 long eventCount = endState.get(typeQuark).getStateValue().unboxInt();
e1c43333
AM
237 if (eventCount == -1) {
238 eventCount = 0;
239 }
240 map.put(curEventName, eventCount);
200789b3 241 }
e1c43333 242 } else {
200789b3 243 /*
e1c43333
AM
244 * Query the start time at -1, so the beginning of the interval
245 * is inclusive.
200789b3 246 */
802017fe 247 List<ITmfStateInterval> startState = typesStats.queryFullState(startTime - 1);
e1c43333 248 for (int typeQuark : quarks) {
55954069
AM
249 String curEventName = typesStats.getAttributeName(typeQuark);
250 long countAtStart = startState.get(typeQuark).getStateValue().unboxInt();
251 long countAtEnd = endState.get(typeQuark).getStateValue().unboxInt();
e1c43333
AM
252
253 if (countAtStart == -1) {
254 countAtStart = 0;
255 }
256 if (countAtEnd == -1) {
257 countAtEnd = 0;
258 }
55954069 259 long eventCount = countAtEnd - countAtStart;
e1c43333 260 map.put(curEventName, eventCount);
200789b3 261 }
200789b3 262 }
e1c43333 263
55954069
AM
264 } catch (TimeRangeException | StateSystemDisposedException e) {
265 /* Assume there is no (more) events, nothing will be put in the map. */
266 } catch (StateValueTypeException e) {
200789b3 267 /*
55954069 268 * This exception type would show a logic problem however,
1c0de632 269 * so they should not happen.
200789b3 270 */
55954069 271 throw new IllegalStateException();
200789b3
AM
272 }
273 return map;
274 }
275
802017fe
AM
276 // ------------------------------------------------------------------------
277 // Helper methods
278 // ------------------------------------------------------------------------
279
f3f93fa6
AM
280 private long getEventCountAt(long timestamp) {
281 /* Make sure the target time is within the range of the history */
63fe91fb
PT
282 long ts = checkStartTime(timestamp, totalsStats);
283 ts = checkEndTime(ts, totalsStats);
f3f93fa6
AM
284
285 try {
802017fe
AM
286 final int quark = totalsStats.getQuarkAbsolute(Attributes.TOTAL);
287 long count = totalsStats.querySingleState(ts, quark).getStateValue().unboxInt();
f3f93fa6
AM
288 return count;
289
290 } catch (TimeRangeException e) {
291 /* Assume there is no events for that range */
8192f2c6 292 } catch (AttributeNotFoundException | StateValueTypeException | StateSystemDisposedException e) {
f3f93fa6
AM
293 e.printStackTrace();
294 }
295
296 return 0;
297 }
298
63fe91fb 299 private static long checkStartTime(long initialStart, ITmfStateSystem ss) {
8b260d9f 300 long start = initialStart;
63fe91fb
PT
301 if (start < ss.getStartTime()) {
302 return ss.getStartTime();
200789b3
AM
303 }
304 return start;
305 }
306
63fe91fb 307 private static long checkEndTime(long initialEnd, ITmfStateSystem ss) {
8b260d9f 308 long end = initialEnd;
63fe91fb
PT
309 if (end > ss.getCurrentEndTime()) {
310 return ss.getCurrentEndTime();
200789b3
AM
311 }
312 return end;
313 }
314
200789b3
AM
315 /**
316 * The attribute names that are used in the state provider
317 */
318 public static class Attributes {
319
df310609
AM
320 /** Total nb of events */
321 public static final String TOTAL = "total"; //$NON-NLS-1$
322
200789b3
AM
323 /** event_types */
324 public static final String EVENT_TYPES = "event_types"; //$NON-NLS-1$<
325 }
326}
This page took 0.05558 seconds and 5 git commands to generate.