tmf: Dipose traces in CtfTmfTestTrace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / statistics / TmfEventsStatistics.java
CommitLineData
1c0de632 1/*******************************************************************************
61759503 2 * Copyright (c) 2012, 2013 Ericsson
1c0de632
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
11 ******************************************************************************/
12
13package org.eclipse.linuxtools.tmf.core.statistics;
14
f3f93fa6 15import java.util.Collection;
1c0de632 16import java.util.HashMap;
f3f93fa6
AM
17import java.util.LinkedList;
18import java.util.List;
1c0de632 19import java.util.Map;
f3f93fa6 20import java.util.TreeMap;
1c0de632
AM
21
22import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
6debe8aa 23import org.eclipse.linuxtools.tmf.core.event.ITmfLostEvent;
1c0de632
AM
24import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
25import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest;
26import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
27import org.eclipse.linuxtools.tmf.core.signal.TmfSignal;
28import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
29import org.eclipse.linuxtools.tmf.core.signal.TmfStatsUpdatedSignal;
3bd46eef
AM
30import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
31import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
32import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
1c0de632
AM
33import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
34
35/**
36 * Implementation of ITmfStatistics which uses event requests to the trace to
37 * retrieve its information.
38 *
39 * There is almost no setup time, but queries themselves are longer than with a
40 * TmfStateStatistics. Queries are O(n * m), where n is the size of the trace,
41 * and m is the portion of the trace covered by the selected interval.
42 *
43 * @author Alexandre Montplaisir
44 * @since 2.0
45 */
46public class TmfEventsStatistics implements ITmfStatistics {
47
8b260d9f
AM
48 /* All timestamps should be stored in nanoseconds in the statistics backend */
49 private static final int SCALE = ITmfTimestamp.NANOSECOND_SCALE;
50
1c0de632
AM
51 private final ITmfTrace trace;
52
53 /* Event request objects for the time-range request. */
54 private StatsTotalRequest totalRequest = null;
55 private StatsPerTypeRequest perTypeRequest = null;
56
57 /**
58 * Constructor
59 *
60 * @param trace
61 * The trace for which we are building the statistics
62 */
63 public TmfEventsStatistics(ITmfTrace trace) {
64 this.trace = trace;
65 }
66
1a4205d9
AM
67 @Override
68 public void dispose() {
69 cancelOngoingRequests();
70 }
71
1c0de632 72 @Override
8b260d9f 73 public void updateStats(final boolean isGlobal, long start, long end) {
1c0de632
AM
74 cancelOngoingRequests();
75
76 /*
77 * Prepare and send the event requests. This needs to be done in the
78 * same thread, since it will be run by TmfStatisticsViewer's signal
79 * handlers, to ensure they get correctly coalesced.
80 */
8b260d9f
AM
81 ITmfTimestamp startTS = new TmfTimestamp(start, SCALE);
82 ITmfTimestamp endTS = new TmfTimestamp(end, SCALE);
83 TmfTimeRange range = isGlobal ? TmfTimeRange.ETERNITY : new TmfTimeRange(startTS, endTS);
1c0de632
AM
84 final StatsTotalRequest totalReq = new StatsTotalRequest(trace, range);
85 final StatsPerTypeRequest perTypeReq = new StatsPerTypeRequest(trace, range);
86
87 /*
88 * Only allow one time-range request at a time (there should be only one
89 * global request at the beginning anyway, no need to track those).
90 */
91 if (!isGlobal) {
92 this.totalRequest = totalReq;
93 this.perTypeRequest = perTypeReq;
94 }
95
96 trace.sendRequest(totalReq);
97 trace.sendRequest(perTypeReq);
98
99 /*
100 * This thread can now return. Start a new thread that will wait until
101 * the request are done and will then send the results.
102 */
103 Thread statsThread = new Thread("Statistics update") { //$NON-NLS-1$
104 @Override
105 public void run() {
106 /* Wait for both requests to complete */
107 try {
108 totalReq.waitForCompletion();
109 perTypeReq.waitForCompletion();
110 } catch (InterruptedException e) {
111 e.printStackTrace();
112 }
113
114 /*
115 * If the request was cancelled, this means a newer one was
116 * sent, discard the current one and return without sending
117 * the signal.
118 */
119 if (totalReq.isCancelled() || perTypeReq.isCancelled()) {
120 return;
121 }
122
123 /* If it completed successfully, retrieve the results. */
124 long total = totalReq.getResult();
125 Map<String, Long> map = perTypeReq.getResults();
126
127 /* Send the signal to notify the stats viewer to update its display. */
128 TmfSignal sig = new TmfStatsUpdatedSignal(this, trace, isGlobal, total, map);
129 TmfSignalManager.dispatchSignal(sig);
130 }
131 };
132 statsThread.start();
133 return;
134 }
135
f3f93fa6
AM
136 @Override
137 public List<Long> histogramQuery(long start, long end, int nb) {
138 final long[] borders = new long[nb];
139 final long increment = (end - start) / nb;
140
141 long curTime = start;
142 for (int i = 0; i < nb; i++) {
143 borders[i] = curTime;
144 curTime += increment;
145 }
146
147 HistogramQueryRequest req = new HistogramQueryRequest(borders, end);
148 sendAndWait(req);
149
150 List<Long> results = new LinkedList<Long>(req.getResults());
151 return results;
152
153 }
154
1c0de632
AM
155 private synchronized void cancelOngoingRequests() {
156 if (totalRequest != null && totalRequest.isRunning()) {
157 totalRequest.cancel();
158 }
159 if (perTypeRequest != null && perTypeRequest.isRunning()) {
160 perTypeRequest.cancel();
161 }
162 }
163
164 @Override
165 public long getEventsTotal() {
166 StatsTotalRequest request = new StatsTotalRequest(trace, TmfTimeRange.ETERNITY);
167 sendAndWait(request);
168
169 long total = request.getResult();
170 return total;
171 }
172
173 @Override
174 public Map<String, Long> getEventTypesTotal() {
175 StatsPerTypeRequest request = new StatsPerTypeRequest(trace, TmfTimeRange.ETERNITY);
176 sendAndWait(request);
177
178 Map<String, Long> stats = request.getResults();
179 return stats;
180 }
181
182 @Override
8b260d9f
AM
183 public long getEventsInRange(long start, long end) {
184 ITmfTimestamp startTS = new TmfTimestamp(start, SCALE);
185 ITmfTimestamp endTS = new TmfTimestamp(end, SCALE);
186 TmfTimeRange range = new TmfTimeRange(startTS, endTS);
187
1c0de632
AM
188 StatsTotalRequest request = new StatsTotalRequest(trace, range);
189 sendAndWait(request);
190
191 long total = request.getResult();
192 return total;
193 }
194
195 @Override
8b260d9f
AM
196 public Map<String, Long> getEventTypesInRange(long start, long end) {
197 ITmfTimestamp startTS = new TmfTimestamp(start, SCALE);
198 ITmfTimestamp endTS = new TmfTimestamp(end, SCALE);
199 TmfTimeRange range = new TmfTimeRange(startTS, endTS);
200
1c0de632
AM
201 StatsPerTypeRequest request = new StatsPerTypeRequest(trace, range);
202 sendAndWait(request);
203
204 Map<String, Long> stats = request.getResults();
205 return stats;
206 }
207
208 private void sendAndWait(TmfEventRequest request) {
209 trace.sendRequest(request);
210 try {
211 request.waitForCompletion();
212 } catch (InterruptedException e) {
213 e.printStackTrace();
214 }
215 }
216
217
218 /**
219 * Event request to get the total number of events
220 */
221 private class StatsTotalRequest extends TmfEventRequest {
222
223 /* Total number of events the request has found */
224 private long total;
225
226 public StatsTotalRequest(ITmfTrace trace, TmfTimeRange range) {
227 super(trace.getEventType(), range, TmfDataRequest.ALL_DATA,
228 trace.getCacheSize(), ITmfDataRequest.ExecutionType.BACKGROUND);
229 total = 0;
230 }
231
232 public long getResult() {
233 return total;
234 }
235
236 @Override
237 public void handleData(final ITmfEvent event) {
238 super.handleData(event);
6debe8aa
AM
239 if (!(event instanceof ITmfLostEvent) && event.getTrace() == trace) {
240 total += 1;
1c0de632
AM
241 }
242 }
243 }
244
245
246 /**
247 * Event request to get the counts per event type
248 */
249 private class StatsPerTypeRequest extends TmfEventRequest {
250
251 /* Map in which the results are saved */
252 private final Map<String, Long> stats;
253
254 public StatsPerTypeRequest(ITmfTrace trace, TmfTimeRange range) {
255 super(trace.getEventType(), range, TmfDataRequest.ALL_DATA,
256 trace.getCacheSize(), ITmfDataRequest.ExecutionType.BACKGROUND);
257 this.stats = new HashMap<String, Long>();
258 }
259
260 public Map<String, Long> getResults() {
261 return stats;
262 }
263
264 @Override
5419a136
AM
265 public void handleData(final ITmfEvent event) {
266 super.handleData(event);
6debe8aa
AM
267 if (event != null && event.getTrace() == trace) {
268 /*
269 * Special handling for lost events: instead of counting just
270 * one, we will count how many actual events it represents.
271 */
272 if (event instanceof ITmfLostEvent) {
273 ITmfLostEvent le = (ITmfLostEvent) event;
274 incrementStats(Messages.LostEventsName, le.getNbLostEvents());
275 return;
1c0de632 276 }
6debe8aa
AM
277
278 /* For standard event types, just increment by one */
279 String eventType = event.getType().getName();
280 incrementStats(eventType, 1L);
1c0de632
AM
281 }
282 }
283
6debe8aa
AM
284 private void incrementStats(String key, long count) {
285 if (stats.containsKey(key)) {
286 long curValue = stats.get(key);
287 stats.put(key, curValue + count);
1c0de632 288 } else {
6debe8aa 289 stats.put(key, count);
1c0de632
AM
290 }
291 }
292 }
293
f3f93fa6
AM
294 /**
295 * Event request for histogram queries. It is much faster to do one event
296 * request then set the results accordingly than doing thousands of them one
297 * by one.
298 */
299 private class HistogramQueryRequest extends TmfEventRequest {
300
301 /** Map of <borders, number of events> */
302 private final TreeMap<Long, Long> results;
303
304 /**
305 * New histogram request
306 *
307 * @param borders
308 * The array of borders (not including the end time). The
309 * first element should be the start time of the queries.
310 * @param endTime
311 * The end time of the query. Not used in the results map,
312 * but we need to know when to stop the event request.
313 */
314 public HistogramQueryRequest(long[] borders, long endTime) {
315 super(trace.getEventType(),
316 new TmfTimeRange(
317 new TmfTimestamp(borders[0], SCALE),
318 new TmfTimestamp(endTime, SCALE)),
319 TmfDataRequest.ALL_DATA,
320 trace.getCacheSize(),
321 ITmfDataRequest.ExecutionType.BACKGROUND);
322
323 /* Prepare the results map, with all counts at 0 */
324 results = new TreeMap<Long, Long>();
325 for (long border : borders) {
326 results.put(border, 0L);
327 }
328 }
329
330 public Collection<Long> getResults() {
331 return results.values();
332 }
333
334 @Override
5419a136
AM
335 public void handleData(ITmfEvent event) {
336 super.handleData(event);
f3f93fa6
AM
337 if ((event != null) && (event.getTrace() == trace)) {
338 long ts = event.getTimestamp().normalize(0, SCALE).getValue();
339 Long key = results.floorKey(ts);
340 if (key != null) {
341 incrementValue(key);
342 }
343 }
344 }
345
346 private void incrementValue(Long key) {
347 long value = results.get(key);
348 value++;
349 results.put(key, value);
350 }
351 }
352
1c0de632 353}
This page took 0.048358 seconds and 5 git commands to generate.