1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 Ericsson
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
10 * Alexandre Montplaisir - Initial API and implementation
11 ******************************************************************************/
13 package org
.eclipse
.tracecompass
.tmf
.core
.statistics
;
15 import java
.util
.Collection
;
16 import java
.util
.HashMap
;
17 import java
.util
.LinkedList
;
18 import java
.util
.List
;
20 import java
.util
.TreeMap
;
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
;
32 * Implementation of ITmfStatistics which uses event requests to the trace to
33 * retrieve its information.
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.
39 * @author Alexandre Montplaisir
41 public class TmfEventsStatistics
implements ITmfStatistics
{
43 /* All timestamps should be stored in nanoseconds in the statistics backend */
44 private static final int SCALE
= ITmfTimestamp
.NANOSECOND_SCALE
;
46 private final ITmfTrace trace
;
48 /* Event request objects for the time-range request. */
49 private StatsTotalRequest totalRequest
= null;
50 private StatsPerTypeRequest perTypeRequest
= null;
56 * The trace for which we are building the statistics
58 public TmfEventsStatistics(ITmfTrace trace
) {
63 public void dispose() {
64 cancelOngoingRequests();
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
;
73 for (int i
= 0; i
< nb
; i
++) {
78 HistogramQueryRequest req
= new HistogramQueryRequest(borders
, end
);
81 List
<Long
> results
= new LinkedList
<>(req
.getResults());
86 private synchronized void cancelOngoingRequests() {
87 if (totalRequest
!= null && totalRequest
.isRunning()) {
88 totalRequest
.cancel();
90 if (perTypeRequest
!= null && perTypeRequest
.isRunning()) {
91 perTypeRequest
.cancel();
96 public long getEventsTotal() {
97 StatsTotalRequest request
= new StatsTotalRequest(trace
, TmfTimeRange
.ETERNITY
);
100 long total
= request
.getResult();
105 public Map
<String
, Long
> getEventTypesTotal() {
106 StatsPerTypeRequest request
= new StatsPerTypeRequest(trace
, TmfTimeRange
.ETERNITY
);
107 sendAndWait(request
);
109 Map
<String
, Long
> stats
= request
.getResults();
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
);
119 StatsTotalRequest request
= new StatsTotalRequest(trace
, range
);
120 sendAndWait(request
);
122 long total
= request
.getResult();
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
);
132 StatsPerTypeRequest request
= new StatsPerTypeRequest(trace
, range
);
133 sendAndWait(request
);
135 Map
<String
, Long
> stats
= request
.getResults();
139 private void sendAndWait(TmfEventRequest request
) {
140 trace
.sendRequest(request
);
142 request
.waitForCompletion();
143 } catch (InterruptedException e
) {
150 * Event request to get the total number of events
152 private class StatsTotalRequest
extends TmfEventRequest
{
154 /* Total number of events the request has found */
157 public StatsTotalRequest(ITmfTrace trace
, TmfTimeRange range
) {
158 super(trace
.getEventType(), range
, 0, ITmfEventRequest
.ALL_DATA
,
159 ITmfEventRequest
.ExecutionType
.BACKGROUND
);
163 public long getResult() {
168 public void handleData(final ITmfEvent event
) {
169 super.handleData(event
);
170 if (!(event
instanceof ITmfLostEvent
) && event
.getTrace() == trace
) {
178 * Event request to get the counts per event type
180 private class StatsPerTypeRequest
extends TmfEventRequest
{
182 /* Map in which the results are saved */
183 private final Map
<String
, Long
> stats
;
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
<>();
191 public Map
<String
, Long
> getResults() {
196 public void handleData(final ITmfEvent event
) {
197 super.handleData(event
);
198 if (event
.getTrace() == trace
) {
199 String eventType
= event
.getName();
201 * Special handling for lost events: instead of counting just
202 * one, we will count how many actual events it represents.
204 if (event
instanceof ITmfLostEvent
) {
205 ITmfLostEvent le
= (ITmfLostEvent
) event
;
206 incrementStats(eventType
, le
.getNbLostEvents());
210 /* For standard event types, just increment by one */
211 incrementStats(eventType
, 1L);
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
);
220 stats
.put(key
, count
);
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
230 private class HistogramQueryRequest
extends TmfEventRequest
{
232 /** Map of <borders, number of events> */
233 private final TreeMap
<Long
, Long
> results
;
236 * New histogram request
239 * The array of borders (not including the end time). The
240 * first element should be the start time of the queries.
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.
245 public HistogramQueryRequest(long[] borders
, long endTime
) {
246 super(trace
.getEventType(),
248 new TmfTimestamp(borders
[0], SCALE
),
249 new TmfTimestamp(endTime
, SCALE
)),
251 ITmfEventRequest
.ALL_DATA
,
252 ITmfEventRequest
.ExecutionType
.BACKGROUND
);
254 /* Prepare the results map, with all counts at 0 */
255 results
= new TreeMap
<>();
256 for (long border
: borders
) {
257 results
.put(border
, 0L);
261 public Collection
<Long
> getResults() {
262 return results
.values();
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
);
277 private void incrementValue(Long key
) {
278 long value
= results
.get(key
);
280 results
.put(key
, value
);