tmf: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / statistics / TmfStateStatistics.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 * Patrick Tasse - Fix TimeRangeException
12 ******************************************************************************/
13
14 package org.eclipse.tracecompass.tmf.core.statistics;
15
16 import java.util.HashMap;
17 import java.util.LinkedList;
18 import java.util.List;
19 import java.util.Map;
20
21 import org.eclipse.jdt.annotation.NonNull;
22 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
23 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
24 import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
25 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
26
27 /**
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.).
32 *
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.
37 *
38 * @author Alexandre Montplaisir
39 */
40 public class TmfStateStatistics implements ITmfStatistics {
41
42 // ------------------------------------------------------------------------
43 // Fields
44 // ------------------------------------------------------------------------
45
46 /** The event totals state system */
47 private final ITmfStateSystem totalsStats;
48
49 /** The state system for event types */
50 private final ITmfStateSystem typesStats;
51
52 // ------------------------------------------------------------------------
53 // Constructors
54 // ------------------------------------------------------------------------
55
56 /**
57 * Constructor
58 *
59 * @param totals
60 * The state system containing the "totals" information
61 * @param eventTypes
62 * The state system containing the "event types" information
63 */
64 public TmfStateStatistics(@NonNull ITmfStateSystem totals, @NonNull ITmfStateSystem eventTypes) {
65 this.totalsStats = totals;
66 this.typesStats = eventTypes;
67 }
68
69 /**
70 * Return the state system containing the "totals" values
71 *
72 * @return The "totals" state system
73 */
74 public ITmfStateSystem getTotalsSS() {
75 return totalsStats;
76 }
77
78 /**
79 * Return the state system containing the "event types" values
80 *
81 * @return The "event types" state system
82 */
83 public ITmfStateSystem getEventTypesSS() {
84 return typesStats;
85 }
86
87 // ------------------------------------------------------------------------
88 // ITmfStatistics
89 // ------------------------------------------------------------------------
90
91 @Override
92 public void dispose() {
93 totalsStats.dispose();
94 typesStats.dispose();
95 }
96
97 @Override
98 public List<Long> histogramQuery(final long start, final long end, final int nb) {
99 final List<Long> list = new LinkedList<>();
100 final long increment = (end - start) / nb;
101
102 if (totalsStats.isCancelled()) {
103 return list;
104 }
105
106 /*
107 * We will do one state system query per "border", and save the
108 * differences between each border.
109 */
110 long prevTotal = (start == totalsStats.getStartTime()) ? 0 : getEventCountAt(start);
111 long curTime = start + increment;
112
113 long curTotal, count;
114 for (int i = 0; i < nb - 1; i++) {
115 curTotal = getEventCountAt(curTime);
116 count = curTotal - prevTotal;
117 list.add(count);
118
119 curTime += increment;
120 prevTotal = curTotal;
121 }
122
123 /*
124 * For the last bucket, we'll stretch its end time to the end time of
125 * the requested range, in case it got truncated down.
126 */
127 curTotal = getEventCountAt(end);
128 count = curTotal - prevTotal;
129 list.add(count);
130
131 return list;
132 }
133
134 @Override
135 public long getEventsTotal() {
136 long endTime = totalsStats.getCurrentEndTime();
137 int count = 0;
138
139 try {
140 final int quark = totalsStats.getQuarkAbsolute(Attributes.TOTAL);
141 count= totalsStats.querySingleState(endTime, quark).getStateValue().unboxInt();
142
143 } catch (StateSystemDisposedException e) {
144 /* Assume there is no events for that range */
145 return 0;
146 } catch (AttributeNotFoundException e) {
147 e.printStackTrace();
148 }
149
150 return count;
151 }
152
153 @Override
154 public Map<String, Long> getEventTypesTotal() {
155 final Map<String, Long> map = new HashMap<>();
156 long endTime = typesStats.getCurrentEndTime();
157
158 try {
159 /* Get the list of quarks, one for each even type in the database */
160 int quark = typesStats.getQuarkAbsolute(Attributes.EVENT_TYPES);
161 List<Integer> quarks = typesStats.getSubAttributes(quark, false);
162
163 /* Since we want the total we can look only at the end */
164 List<ITmfStateInterval> endState = typesStats.queryFullState(endTime);
165
166 String curEventName;
167 long eventCount;
168 for (int typeQuark : quarks) {
169 curEventName = typesStats.getAttributeName(typeQuark);
170 eventCount = endState.get(typeQuark).getStateValue().unboxInt();
171 map.put(curEventName, eventCount);
172 }
173
174 } catch (StateSystemDisposedException e) {
175 /* Assume there is no events, nothing will be put in the map. */
176 } catch (AttributeNotFoundException e) {
177 e.printStackTrace();
178 }
179 return map;
180 }
181
182 @Override
183 public long getEventsInRange(long start, long end) {
184 long startCount;
185 if (start == totalsStats.getStartTime()) {
186 startCount = 0;
187 } else {
188 /*
189 * We want the events happening at "start" to be included, so we'll
190 * need to query one unit before that point.
191 */
192 startCount = getEventCountAt(start - 1);
193 }
194 long endCount = getEventCountAt(end);
195
196 return endCount - startCount;
197 }
198
199 @Override
200 public Map<String, Long> getEventTypesInRange(long start, long end) {
201 final Map<String, Long> map = new HashMap<>();
202 List<Integer> quarks;
203
204 /* Make sure the start/end times are within the state history, so we
205 * don't get TimeRange exceptions.
206 */
207 long startTime = checkStartTime(start, typesStats);
208 long endTime = checkEndTime(end, typesStats);
209 if (endTime < startTime) {
210 /* The start/end times do not intersect this state system range.
211 * Return the empty map. */
212 return map;
213 }
214
215 try {
216 /* Get the list of quarks, one for each even type in the database */
217 int quark = typesStats.getQuarkAbsolute(Attributes.EVENT_TYPES);
218 quarks = typesStats.getSubAttributes(quark, false);
219 } catch (AttributeNotFoundException e) {
220 /*
221 * The state system does not (yet?) have the needed attributes, it
222 * probably means there are no events counted yet. Return the empty
223 * map.
224 */
225 return map;
226 }
227
228 try {
229 List<ITmfStateInterval> endState = typesStats.queryFullState(endTime);
230
231 if (startTime == typesStats.getStartTime()) {
232 /* Only use the values picked up at the end time */
233 for (int typeQuark : quarks) {
234 String curEventName = typesStats.getAttributeName(typeQuark);
235 long eventCount = endState.get(typeQuark).getStateValue().unboxInt();
236 if (eventCount == -1) {
237 eventCount = 0;
238 }
239 map.put(curEventName, eventCount);
240 }
241 } else {
242 /*
243 * Query the start time at -1, so the beginning of the interval
244 * is inclusive.
245 */
246 List<ITmfStateInterval> startState = typesStats.queryFullState(startTime - 1);
247 for (int typeQuark : quarks) {
248 String curEventName = typesStats.getAttributeName(typeQuark);
249 long countAtStart = startState.get(typeQuark).getStateValue().unboxInt();
250 long countAtEnd = endState.get(typeQuark).getStateValue().unboxInt();
251
252 if (countAtStart == -1) {
253 countAtStart = 0;
254 }
255 if (countAtEnd == -1) {
256 countAtEnd = 0;
257 }
258 long eventCount = countAtEnd - countAtStart;
259 map.put(curEventName, eventCount);
260 }
261 }
262
263 } catch (StateSystemDisposedException e) {
264 /* Assume there is no (more) events, nothing will be put in the map. */
265 }
266 return map;
267 }
268
269 // ------------------------------------------------------------------------
270 // Helper methods
271 // ------------------------------------------------------------------------
272
273 private long getEventCountAt(long timestamp) {
274 /* Make sure the target time is within the range of the history */
275 long ts = checkStartTime(timestamp, totalsStats);
276 ts = checkEndTime(ts, totalsStats);
277
278 try {
279 final int quark = totalsStats.getQuarkAbsolute(Attributes.TOTAL);
280 long count = totalsStats.querySingleState(ts, quark).getStateValue().unboxInt();
281 return count;
282
283 } catch (StateSystemDisposedException e) {
284 /* Assume there is no (more) events, nothing will be put in the map. */
285 } catch (AttributeNotFoundException e) {
286 e.printStackTrace();
287 }
288
289 return 0;
290 }
291
292 private static long checkStartTime(long initialStart, ITmfStateSystem ss) {
293 long start = initialStart;
294 if (start < ss.getStartTime()) {
295 return ss.getStartTime();
296 }
297 return start;
298 }
299
300 private static long checkEndTime(long initialEnd, ITmfStateSystem ss) {
301 long end = initialEnd;
302 if (end > ss.getCurrentEndTime()) {
303 return ss.getCurrentEndTime();
304 }
305 return end;
306 }
307
308 /**
309 * The attribute names that are used in the state provider
310 */
311 public static class Attributes {
312
313 /** Total nb of events */
314 public static final String TOTAL = "total"; //$NON-NLS-1$
315
316 /** event_types */
317 public static final String EVENT_TYPES = "event_types"; //$NON-NLS-1$<
318 }
319 }
This page took 0.040598 seconds and 5 git commands to generate.