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 * Patrick Tasse - Fix TimeRangeException
12 ******************************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.core
.statistics
;
16 import java
.util
.HashMap
;
17 import java
.util
.LinkedList
;
18 import java
.util
.List
;
21 import org
.eclipse
.jdt
.annotation
.NonNull
;
22 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.AttributeNotFoundException
;
23 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.StateSystemDisposedException
;
24 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.ITmfStateInterval
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.ITmfStateSystem
;
28 * Implementation of ITmfStatistics which uses a state history for storing its
29 * information. In reality, it uses two state histories, one for "event totals"
30 * information (which should ideally use a fast backend), and another one for
31 * the rest (per event type, per CPU, etc.).
33 * Compared to the event-request-based statistics calculations, it adds the
34 * building the history first, but gives much faster response times once built :
35 * Queries are O(log n) wrt the size of the trace, and O(1) wrt to the size of
36 * the time interval selected.
38 * @author Alexandre Montplaisir
41 public class TmfStateStatistics
implements ITmfStatistics
{
43 // ------------------------------------------------------------------------
45 // ------------------------------------------------------------------------
47 /** The event totals state system */
48 private final ITmfStateSystem totalsStats
;
50 /** The state system for event types */
51 private final ITmfStateSystem typesStats
;
53 // ------------------------------------------------------------------------
55 // ------------------------------------------------------------------------
61 * The state system containing the "totals" information
63 * The state system containing the "event types" information
66 public TmfStateStatistics(@NonNull ITmfStateSystem totals
, @NonNull ITmfStateSystem eventTypes
) {
67 this.totalsStats
= totals
;
68 this.typesStats
= eventTypes
;
72 * Return the state system containing the "totals" values
74 * @return The "totals" state system
77 public ITmfStateSystem
getTotalsSS() {
82 * Return the state system containing the "event types" values
84 * @return The "event types" state system
87 public ITmfStateSystem
getEventTypesSS() {
91 // ------------------------------------------------------------------------
93 // ------------------------------------------------------------------------
96 public void dispose() {
97 totalsStats
.dispose();
102 public List
<Long
> histogramQuery(final long start
, final long end
, final int nb
) {
103 final List
<Long
> list
= new LinkedList
<>();
104 final long increment
= (end
- start
) / nb
;
106 if (totalsStats
.isCancelled()) {
111 * We will do one state system query per "border", and save the
112 * differences between each border.
114 long prevTotal
= (start
== totalsStats
.getStartTime()) ?
0 : getEventCountAt(start
);
115 long curTime
= start
+ increment
;
117 long curTotal
, count
;
118 for (int i
= 0; i
< nb
- 1; i
++) {
119 curTotal
= getEventCountAt(curTime
);
120 count
= curTotal
- prevTotal
;
123 curTime
+= increment
;
124 prevTotal
= curTotal
;
128 * For the last bucket, we'll stretch its end time to the end time of
129 * the requested range, in case it got truncated down.
131 curTotal
= getEventCountAt(end
);
132 count
= curTotal
- prevTotal
;
139 public long getEventsTotal() {
140 long endTime
= totalsStats
.getCurrentEndTime();
144 final int quark
= totalsStats
.getQuarkAbsolute(Attributes
.TOTAL
);
145 count
= totalsStats
.querySingleState(endTime
, quark
).getStateValue().unboxInt();
147 } catch (StateSystemDisposedException e
) {
148 /* Assume there is no events for that range */
150 } catch (AttributeNotFoundException e
) {
158 public Map
<String
, Long
> getEventTypesTotal() {
159 final Map
<String
, Long
> map
= new HashMap
<>();
160 long endTime
= typesStats
.getCurrentEndTime();
163 /* Get the list of quarks, one for each even type in the database */
164 int quark
= typesStats
.getQuarkAbsolute(Attributes
.EVENT_TYPES
);
165 List
<Integer
> quarks
= typesStats
.getSubAttributes(quark
, false);
167 /* Since we want the total we can look only at the end */
168 List
<ITmfStateInterval
> endState
= typesStats
.queryFullState(endTime
);
172 for (int typeQuark
: quarks
) {
173 curEventName
= typesStats
.getAttributeName(typeQuark
);
174 eventCount
= endState
.get(typeQuark
).getStateValue().unboxInt();
175 map
.put(curEventName
, eventCount
);
178 } catch (StateSystemDisposedException e
) {
179 /* Assume there is no events, nothing will be put in the map. */
180 } catch (AttributeNotFoundException e
) {
187 public long getEventsInRange(long start
, long end
) {
189 if (start
== totalsStats
.getStartTime()) {
193 * We want the events happening at "start" to be included, so we'll
194 * need to query one unit before that point.
196 startCount
= getEventCountAt(start
- 1);
198 long endCount
= getEventCountAt(end
);
200 return endCount
- startCount
;
204 public Map
<String
, Long
> getEventTypesInRange(long start
, long end
) {
205 final Map
<String
, Long
> map
= new HashMap
<>();
206 List
<Integer
> quarks
;
208 /* Make sure the start/end times are within the state history, so we
209 * don't get TimeRange exceptions.
211 long startTime
= checkStartTime(start
, typesStats
);
212 long endTime
= checkEndTime(end
, typesStats
);
213 if (endTime
< startTime
) {
214 /* The start/end times do not intersect this state system range.
215 * Return the empty map. */
220 /* Get the list of quarks, one for each even type in the database */
221 int quark
= typesStats
.getQuarkAbsolute(Attributes
.EVENT_TYPES
);
222 quarks
= typesStats
.getSubAttributes(quark
, false);
223 } catch (AttributeNotFoundException e
) {
225 * The state system does not (yet?) have the needed attributes, it
226 * probably means there are no events counted yet. Return the empty
233 List
<ITmfStateInterval
> endState
= typesStats
.queryFullState(endTime
);
235 if (startTime
== typesStats
.getStartTime()) {
236 /* Only use the values picked up at the end time */
237 for (int typeQuark
: quarks
) {
238 String curEventName
= typesStats
.getAttributeName(typeQuark
);
239 long eventCount
= endState
.get(typeQuark
).getStateValue().unboxInt();
240 if (eventCount
== -1) {
243 map
.put(curEventName
, eventCount
);
247 * Query the start time at -1, so the beginning of the interval
250 List
<ITmfStateInterval
> startState
= typesStats
.queryFullState(startTime
- 1);
251 for (int typeQuark
: quarks
) {
252 String curEventName
= typesStats
.getAttributeName(typeQuark
);
253 long countAtStart
= startState
.get(typeQuark
).getStateValue().unboxInt();
254 long countAtEnd
= endState
.get(typeQuark
).getStateValue().unboxInt();
256 if (countAtStart
== -1) {
259 if (countAtEnd
== -1) {
262 long eventCount
= countAtEnd
- countAtStart
;
263 map
.put(curEventName
, eventCount
);
267 } catch (StateSystemDisposedException e
) {
268 /* Assume there is no (more) events, nothing will be put in the map. */
273 // ------------------------------------------------------------------------
275 // ------------------------------------------------------------------------
277 private long getEventCountAt(long timestamp
) {
278 /* Make sure the target time is within the range of the history */
279 long ts
= checkStartTime(timestamp
, totalsStats
);
280 ts
= checkEndTime(ts
, totalsStats
);
283 final int quark
= totalsStats
.getQuarkAbsolute(Attributes
.TOTAL
);
284 long count
= totalsStats
.querySingleState(ts
, quark
).getStateValue().unboxInt();
287 } catch (StateSystemDisposedException e
) {
288 /* Assume there is no (more) events, nothing will be put in the map. */
289 } catch (AttributeNotFoundException e
) {
296 private static long checkStartTime(long initialStart
, ITmfStateSystem ss
) {
297 long start
= initialStart
;
298 if (start
< ss
.getStartTime()) {
299 return ss
.getStartTime();
304 private static long checkEndTime(long initialEnd
, ITmfStateSystem ss
) {
305 long end
= initialEnd
;
306 if (end
> ss
.getCurrentEndTime()) {
307 return ss
.getCurrentEndTime();
313 * The attribute names that are used in the state provider
315 public static class Attributes
{
317 /** Total nb of events */
318 public static final String TOTAL
= "total"; //$NON-NLS-1$
321 public static final String EVENT_TYPES
= "event_types"; //$NON-NLS-1$<