1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 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
.linuxtools
.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
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
23 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfLostEvent
;
24 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfEventRequest
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.request
.TmfEventRequest
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.ITmfTimestamp
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimeRange
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.timestamp
.TmfTimestamp
;
29 import org
.eclipse
.linuxtools
.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
42 public class TmfEventsStatistics
implements ITmfStatistics
{
44 /* All timestamps should be stored in nanoseconds in the statistics backend */
45 private static final int SCALE
= ITmfTimestamp
.NANOSECOND_SCALE
;
47 private final ITmfTrace trace
;
49 /* Event request objects for the time-range request. */
50 private StatsTotalRequest totalRequest
= null;
51 private StatsPerTypeRequest perTypeRequest
= null;
57 * The trace for which we are building the statistics
59 public TmfEventsStatistics(ITmfTrace trace
) {
64 public void dispose() {
65 cancelOngoingRequests();
69 public List
<Long
> histogramQuery(long start
, long end
, int nb
) {
70 final long[] borders
= new long[nb
];
71 final long increment
= (end
- start
) / nb
;
74 for (int i
= 0; i
< nb
; i
++) {
79 HistogramQueryRequest req
= new HistogramQueryRequest(borders
, end
);
82 List
<Long
> results
= new LinkedList
<>(req
.getResults());
87 private synchronized void cancelOngoingRequests() {
88 if (totalRequest
!= null && totalRequest
.isRunning()) {
89 totalRequest
.cancel();
91 if (perTypeRequest
!= null && perTypeRequest
.isRunning()) {
92 perTypeRequest
.cancel();
97 public long getEventsTotal() {
98 StatsTotalRequest request
= new StatsTotalRequest(trace
, TmfTimeRange
.ETERNITY
);
101 long total
= request
.getResult();
106 public Map
<String
, Long
> getEventTypesTotal() {
107 StatsPerTypeRequest request
= new StatsPerTypeRequest(trace
, TmfTimeRange
.ETERNITY
);
108 sendAndWait(request
);
110 Map
<String
, Long
> stats
= request
.getResults();
115 public long getEventsInRange(long start
, long end
) {
116 ITmfTimestamp startTS
= new TmfTimestamp(start
, SCALE
);
117 ITmfTimestamp endTS
= new TmfTimestamp(end
, SCALE
);
118 TmfTimeRange range
= new TmfTimeRange(startTS
, endTS
);
120 StatsTotalRequest request
= new StatsTotalRequest(trace
, range
);
121 sendAndWait(request
);
123 long total
= request
.getResult();
128 public Map
<String
, Long
> getEventTypesInRange(long start
, long end
) {
129 ITmfTimestamp startTS
= new TmfTimestamp(start
, SCALE
);
130 ITmfTimestamp endTS
= new TmfTimestamp(end
, SCALE
);
131 TmfTimeRange range
= new TmfTimeRange(startTS
, endTS
);
133 StatsPerTypeRequest request
= new StatsPerTypeRequest(trace
, range
);
134 sendAndWait(request
);
136 Map
<String
, Long
> stats
= request
.getResults();
140 private void sendAndWait(TmfEventRequest request
) {
141 trace
.sendRequest(request
);
143 request
.waitForCompletion();
144 } catch (InterruptedException e
) {
151 * Event request to get the total number of events
153 private class StatsTotalRequest
extends TmfEventRequest
{
155 /* Total number of events the request has found */
158 public StatsTotalRequest(ITmfTrace trace
, TmfTimeRange range
) {
159 super(trace
.getEventType(), range
, 0, ITmfEventRequest
.ALL_DATA
,
160 ITmfEventRequest
.ExecutionType
.BACKGROUND
);
164 public long getResult() {
169 public void handleData(final ITmfEvent event
) {
170 super.handleData(event
);
171 if (!(event
instanceof ITmfLostEvent
) && event
.getTrace() == trace
) {
179 * Event request to get the counts per event type
181 private class StatsPerTypeRequest
extends TmfEventRequest
{
183 /* Map in which the results are saved */
184 private final Map
<String
, Long
> stats
;
186 public StatsPerTypeRequest(ITmfTrace trace
, TmfTimeRange range
) {
187 super(trace
.getEventType(), range
, 0, ITmfEventRequest
.ALL_DATA
,
188 ITmfEventRequest
.ExecutionType
.BACKGROUND
);
189 this.stats
= new HashMap
<>();
192 public Map
<String
, Long
> getResults() {
197 public void handleData(final ITmfEvent event
) {
198 super.handleData(event
);
199 if (event
!= null && event
.getTrace() == trace
) {
200 String eventType
= event
.getType().getName();
202 * Special handling for lost events: instead of counting just
203 * one, we will count how many actual events it represents.
205 if (event
instanceof ITmfLostEvent
) {
206 ITmfLostEvent le
= (ITmfLostEvent
) event
;
207 incrementStats(eventType
, le
.getNbLostEvents());
211 /* For standard event types, just increment by one */
212 incrementStats(eventType
, 1L);
216 private void incrementStats(String key
, long count
) {
217 if (stats
.containsKey(key
)) {
218 long curValue
= stats
.get(key
);
219 stats
.put(key
, curValue
+ count
);
221 stats
.put(key
, count
);
227 * Event request for histogram queries. It is much faster to do one event
228 * request then set the results accordingly than doing thousands of them one
231 private class HistogramQueryRequest
extends TmfEventRequest
{
233 /** Map of <borders, number of events> */
234 private final TreeMap
<Long
, Long
> results
;
237 * New histogram request
240 * The array of borders (not including the end time). The
241 * first element should be the start time of the queries.
243 * The end time of the query. Not used in the results map,
244 * but we need to know when to stop the event request.
246 public HistogramQueryRequest(long[] borders
, long endTime
) {
247 super(trace
.getEventType(),
249 new TmfTimestamp(borders
[0], SCALE
),
250 new TmfTimestamp(endTime
, SCALE
)),
252 ITmfEventRequest
.ALL_DATA
,
253 ITmfEventRequest
.ExecutionType
.BACKGROUND
);
255 /* Prepare the results map, with all counts at 0 */
256 results
= new TreeMap
<>();
257 for (long border
: borders
) {
258 results
.put(border
, 0L);
262 public Collection
<Long
> getResults() {
263 return results
.values();
267 public void handleData(ITmfEvent event
) {
268 super.handleData(event
);
269 if ((event
!= null) && (event
.getTrace() == trace
)) {
270 long ts
= event
.getTimestamp().normalize(0, SCALE
).getValue();
271 Long key
= results
.floorKey(ts
);
278 private void incrementValue(Long key
) {
279 long value
= results
.get(key
);
281 results
.put(key
, value
);