tmf: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / statistics / TmfEventsStatistics.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 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 * Alexandre Montplaisir - Initial API and implementation
11 ******************************************************************************/
12
13 package org.eclipse.tracecompass.tmf.core.statistics;
14
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.LinkedList;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.TreeMap;
21
22 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
23 import org.eclipse.tracecompass.tmf.core.event.ITmfLostEvent;
24 import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
25 import org.eclipse.tracecompass.tmf.core.request.TmfEventRequest;
26 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
27 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
28 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
29 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
30
31 /**
32 * Implementation of ITmfStatistics which uses event requests to the trace to
33 * retrieve its information.
34 *
35 * There is almost no setup time, but queries themselves are longer than with a
36 * TmfStateStatistics. Queries are O(n * m), where n is the size of the trace,
37 * and m is the portion of the trace covered by the selected interval.
38 *
39 * @author Alexandre Montplaisir
40 */
41 public class TmfEventsStatistics implements ITmfStatistics {
42
43 /* All timestamps should be stored in nanoseconds in the statistics backend */
44 private static final int SCALE = ITmfTimestamp.NANOSECOND_SCALE;
45
46 private final ITmfTrace trace;
47
48 /* Event request objects for the time-range request. */
49 private StatsTotalRequest totalRequest = null;
50 private StatsPerTypeRequest perTypeRequest = null;
51
52 /**
53 * Constructor
54 *
55 * @param trace
56 * The trace for which we are building the statistics
57 */
58 public TmfEventsStatistics(ITmfTrace trace) {
59 this.trace = trace;
60 }
61
62 @Override
63 public void dispose() {
64 cancelOngoingRequests();
65 }
66
67 @Override
68 public List<Long> histogramQuery(long start, long end, int nb) {
69 final long[] borders = new long[nb];
70 final long increment = (end - start) / nb;
71
72 long curTime = start;
73 for (int i = 0; i < nb; i++) {
74 borders[i] = curTime;
75 curTime += increment;
76 }
77
78 HistogramQueryRequest req = new HistogramQueryRequest(borders, end);
79 sendAndWait(req);
80
81 List<Long> results = new LinkedList<>(req.getResults());
82 return results;
83
84 }
85
86 private synchronized void cancelOngoingRequests() {
87 if (totalRequest != null && totalRequest.isRunning()) {
88 totalRequest.cancel();
89 }
90 if (perTypeRequest != null && perTypeRequest.isRunning()) {
91 perTypeRequest.cancel();
92 }
93 }
94
95 @Override
96 public long getEventsTotal() {
97 StatsTotalRequest request = new StatsTotalRequest(trace, TmfTimeRange.ETERNITY);
98 sendAndWait(request);
99
100 long total = request.getResult();
101 return total;
102 }
103
104 @Override
105 public Map<String, Long> getEventTypesTotal() {
106 StatsPerTypeRequest request = new StatsPerTypeRequest(trace, TmfTimeRange.ETERNITY);
107 sendAndWait(request);
108
109 Map<String, Long> stats = request.getResults();
110 return stats;
111 }
112
113 @Override
114 public long getEventsInRange(long start, long end) {
115 ITmfTimestamp startTS = new TmfTimestamp(start, SCALE);
116 ITmfTimestamp endTS = new TmfTimestamp(end, SCALE);
117 TmfTimeRange range = new TmfTimeRange(startTS, endTS);
118
119 StatsTotalRequest request = new StatsTotalRequest(trace, range);
120 sendAndWait(request);
121
122 long total = request.getResult();
123 return total;
124 }
125
126 @Override
127 public Map<String, Long> getEventTypesInRange(long start, long end) {
128 ITmfTimestamp startTS = new TmfTimestamp(start, SCALE);
129 ITmfTimestamp endTS = new TmfTimestamp(end, SCALE);
130 TmfTimeRange range = new TmfTimeRange(startTS, endTS);
131
132 StatsPerTypeRequest request = new StatsPerTypeRequest(trace, range);
133 sendAndWait(request);
134
135 Map<String, Long> stats = request.getResults();
136 return stats;
137 }
138
139 private void sendAndWait(TmfEventRequest request) {
140 trace.sendRequest(request);
141 try {
142 request.waitForCompletion();
143 } catch (InterruptedException e) {
144 e.printStackTrace();
145 }
146 }
147
148
149 /**
150 * Event request to get the total number of events
151 */
152 private class StatsTotalRequest extends TmfEventRequest {
153
154 /* Total number of events the request has found */
155 private long total;
156
157 public StatsTotalRequest(ITmfTrace trace, TmfTimeRange range) {
158 super(trace.getEventType(), range, 0, ITmfEventRequest.ALL_DATA,
159 ITmfEventRequest.ExecutionType.BACKGROUND);
160 total = 0;
161 }
162
163 public long getResult() {
164 return total;
165 }
166
167 @Override
168 public void handleData(final ITmfEvent event) {
169 super.handleData(event);
170 if (!(event instanceof ITmfLostEvent) && event.getTrace() == trace) {
171 total += 1;
172 }
173 }
174 }
175
176
177 /**
178 * Event request to get the counts per event type
179 */
180 private class StatsPerTypeRequest extends TmfEventRequest {
181
182 /* Map in which the results are saved */
183 private final Map<String, Long> stats;
184
185 public StatsPerTypeRequest(ITmfTrace trace, TmfTimeRange range) {
186 super(trace.getEventType(), range, 0, ITmfEventRequest.ALL_DATA,
187 ITmfEventRequest.ExecutionType.BACKGROUND);
188 this.stats = new HashMap<>();
189 }
190
191 public Map<String, Long> getResults() {
192 return stats;
193 }
194
195 @Override
196 public void handleData(final ITmfEvent event) {
197 super.handleData(event);
198 if (event.getTrace() == trace) {
199 String eventType = event.getName();
200 /*
201 * Special handling for lost events: instead of counting just
202 * one, we will count how many actual events it represents.
203 */
204 if (event instanceof ITmfLostEvent) {
205 ITmfLostEvent le = (ITmfLostEvent) event;
206 incrementStats(eventType, le.getNbLostEvents());
207 return;
208 }
209
210 /* For standard event types, just increment by one */
211 incrementStats(eventType, 1L);
212 }
213 }
214
215 private void incrementStats(String key, long count) {
216 if (stats.containsKey(key)) {
217 long curValue = stats.get(key);
218 stats.put(key, curValue + count);
219 } else {
220 stats.put(key, count);
221 }
222 }
223 }
224
225 /**
226 * Event request for histogram queries. It is much faster to do one event
227 * request then set the results accordingly than doing thousands of them one
228 * by one.
229 */
230 private class HistogramQueryRequest extends TmfEventRequest {
231
232 /** Map of <borders, number of events> */
233 private final TreeMap<Long, Long> results;
234
235 /**
236 * New histogram request
237 *
238 * @param borders
239 * The array of borders (not including the end time). The
240 * first element should be the start time of the queries.
241 * @param endTime
242 * The end time of the query. Not used in the results map,
243 * but we need to know when to stop the event request.
244 */
245 public HistogramQueryRequest(long[] borders, long endTime) {
246 super(trace.getEventType(),
247 new TmfTimeRange(
248 new TmfTimestamp(borders[0], SCALE),
249 new TmfTimestamp(endTime, SCALE)),
250 0,
251 ITmfEventRequest.ALL_DATA,
252 ITmfEventRequest.ExecutionType.BACKGROUND);
253
254 /* Prepare the results map, with all counts at 0 */
255 results = new TreeMap<>();
256 for (long border : borders) {
257 results.put(border, 0L);
258 }
259 }
260
261 public Collection<Long> getResults() {
262 return results.values();
263 }
264
265 @Override
266 public void handleData(ITmfEvent event) {
267 super.handleData(event);
268 if (event.getTrace() == trace) {
269 long ts = event.getTimestamp().normalize(0, SCALE).getValue();
270 Long key = results.floorKey(ts);
271 if (key != null) {
272 incrementValue(key);
273 }
274 }
275 }
276
277 private void incrementValue(Long key) {
278 long value = results.get(key);
279 value++;
280 results.put(key, value);
281 }
282 }
283
284 }
This page took 0.036261 seconds and 5 git commands to generate.