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