tmf: Add a waitForInitialization() to TmfStatisticsModule
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / statistics / TmfStateStatistics.java
CommitLineData
200789b3 1/*******************************************************************************
61759503 2 * Copyright (c) 2012, 2013 Ericsson
200789b3
AM
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
13package org.eclipse.linuxtools.tmf.core.statistics;
14
15import java.io.File;
16import java.util.HashMap;
f3f93fa6 17import java.util.LinkedList;
200789b3
AM
18import java.util.List;
19import java.util.Map;
20
8192f2c6 21import org.eclipse.jdt.annotation.NonNull;
200789b3 22import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
96345c5a 23import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
200789b3
AM
24import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
25import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
26import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
27import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
0fe46f2a 28import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateProvider;
200789b3 29import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
3f436e7c 30import org.eclipse.linuxtools.tmf.core.statesystem.TmfStateSystemFactory;
200789b3
AM
31import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
32
33/**
1c0de632 34 * Implementation of ITmfStatistics which uses a state history for storing its
802017fe
AM
35 * information. In reality, it uses two state histories, one for "event totals"
36 * information (which should ideally use a fast backend), and another one for
37 * the rest (per event type, per CPU, etc.).
1c0de632 38 *
802017fe
AM
39 * Compared to the event-request-based statistics calculations, it adds the
40 * building the history first, but gives much faster response times once built :
41 * Queries are O(log n) wrt the size of the trace, and O(1) wrt to the size of
42 * the time interval selected.
200789b3
AM
43 *
44 * @author Alexandre Montplaisir
45 * @since 2.0
46 */
1c0de632 47public class TmfStateStatistics implements ITmfStatistics {
200789b3 48
802017fe
AM
49 // ------------------------------------------------------------------------
50 // Fields
51 // ------------------------------------------------------------------------
200789b3 52
802017fe
AM
53 /** The event totals state system */
54 private final ITmfStateSystem totalsStats;
55
56 /** The state system for event types */
57 private final ITmfStateSystem typesStats;
58
59 // ------------------------------------------------------------------------
60 // Constructors
61 // ------------------------------------------------------------------------
200789b3
AM
62
63 /**
64 * Constructor
65 *
8192f2c6
AM
66 * @param totals
67 * The state system containing the "totals" information
68 * @param eventTypes
69 * The state system containing the "event types" information
70 * @since 3.0
200789b3 71 */
d6b46913 72 public TmfStateStatistics(@NonNull ITmfStateSystem totals, @NonNull ITmfStateSystem eventTypes) {
8192f2c6
AM
73 this.totalsStats = totals;
74 this.typesStats = eventTypes;
802017fe
AM
75 }
76
e1c43333
AM
77 /**
78 * Manual constructor. This should be used if the trace's Resource is null
79 * (ie, for unit tests). It requires specifying the location of the history
802017fe 80 * files manually.
e1c43333
AM
81 *
82 * @param trace
83 * The trace for which we build these statistics
802017fe
AM
84 * @param totalsHistoryFile
85 * The location of the totals state history file
86 * @param typesHistoryFile
87 * The location of the types state history file
e1c43333
AM
88 * @throws TmfTraceException
89 * If the file could not be written to
802017fe 90 * @since 2.2
e1c43333 91 */
8192f2c6 92 @Deprecated
802017fe
AM
93 public TmfStateStatistics(ITmfTrace trace, File totalsHistoryFile,
94 File typesHistoryFile) throws TmfTraceException {
8192f2c6
AM
95 final ITmfStateProvider totalsInput = new TmfStatisticsTotalsModule().new StatsProviderTotals(trace);
96 final ITmfStateProvider typesInput = new TmfStatisticsEventTypesModule().new StatsProviderEventTypes(trace);
802017fe
AM
97 this.totalsStats = TmfStateSystemFactory.newFullHistory(totalsHistoryFile, totalsInput, true);
98 this.typesStats = TmfStateSystemFactory.newFullHistory(typesHistoryFile, typesInput, true);
6c5e0863
AM
99 }
100
101 /**
8192f2c6
AM
102 * Return the state system containing the "totals" values
103 *
104 * @return The "totals" state system
105 * @since 3.0
106 */
107 public ITmfStateSystem getTotalsSS() {
108 return totalsStats;
109 }
110
111 /**
112 * Return the state system containing the "event types" values
113 *
114 * @return The "event types" state system
115 * @since 3.0
6c5e0863 116 */
8192f2c6
AM
117 public ITmfStateSystem getEventTypesSS() {
118 return typesStats;
e1c43333
AM
119 }
120
200789b3 121 // ------------------------------------------------------------------------
1c0de632 122 // ITmfStatistics
200789b3
AM
123 // ------------------------------------------------------------------------
124
1a4205d9
AM
125 @Override
126 public void dispose() {
802017fe
AM
127 totalsStats.dispose();
128 typesStats.dispose();
1a4205d9
AM
129 }
130
f3f93fa6
AM
131 @Override
132 public List<Long> histogramQuery(final long start, final long end, final int nb) {
a4524c1b 133 final List<Long> list = new LinkedList<>();
f3f93fa6
AM
134 final long increment = (end - start) / nb;
135
2002c638
AM
136 totalsStats.waitUntilBuilt();
137 if (totalsStats.isCancelled()) {
802017fe 138 return list;
f3f93fa6
AM
139 }
140
141 /*
142 * We will do one state system query per "border", and save the
143 * differences between each border.
144 */
802017fe 145 long prevTotal = (start == totalsStats.getStartTime()) ? 0 : getEventCountAt(start);
f3f93fa6
AM
146 long curTime = start + increment;
147
148 long curTotal, count;
149 for (int i = 0; i < nb - 1; i++) {
150 curTotal = getEventCountAt(curTime);
151 count = curTotal - prevTotal;
152 list.add(count);
153
154 curTime += increment;
155 prevTotal = curTotal;
156 }
157
158 /*
159 * For the last bucket, we'll stretch its end time to the end time of
160 * the requested range, in case it got truncated down.
161 */
162 curTotal = getEventCountAt(end);
163 count = curTotal - prevTotal;
164 list.add(count);
1c0de632 165
f3f93fa6 166 return list;
1c0de632
AM
167 }
168
200789b3
AM
169 @Override
170 public long getEventsTotal() {
e1c43333 171 /* We need the complete state history to be built to answer this. */
802017fe 172 totalsStats.waitUntilBuilt();
e1c43333 173
802017fe 174 long endTime = totalsStats.getCurrentEndTime();
e1c43333 175 int count = 0;
df310609
AM
176
177 try {
802017fe
AM
178 final int quark = totalsStats.getQuarkAbsolute(Attributes.TOTAL);
179 count= totalsStats.querySingleState(endTime, quark).getStateValue().unboxInt();
1c0de632
AM
180
181 } catch (TimeRangeException e) {
182 /* Assume there is no events for that range */
183 return 0;
df310609
AM
184 } catch (AttributeNotFoundException e) {
185 e.printStackTrace();
186 } catch (StateValueTypeException e) {
187 e.printStackTrace();
96345c5a
AM
188 } catch (StateSystemDisposedException e) {
189 e.printStackTrace();
200789b3 190 }
df310609 191
e1c43333 192 return count;
200789b3
AM
193 }
194
195 @Override
196 public Map<String, Long> getEventTypesTotal() {
e1c43333 197 /* We need the complete state history to be built to answer this. */
802017fe 198 typesStats.waitUntilBuilt();
e1c43333 199
a4524c1b 200 Map<String, Long> map = new HashMap<>();
802017fe 201 long endTime = typesStats.getCurrentEndTime();
200789b3
AM
202
203 try {
204 /* Get the list of quarks, one for each even type in the database */
802017fe
AM
205 int quark = typesStats.getQuarkAbsolute(Attributes.EVENT_TYPES);
206 List<Integer> quarks = typesStats.getSubAttributes(quark, false);
200789b3
AM
207
208 /* Since we want the total we can look only at the end */
802017fe 209 List<ITmfStateInterval> endState = typesStats.queryFullState(endTime);
200789b3
AM
210
211 String curEventName;
212 long eventCount;
213 for (int typeQuark : quarks) {
802017fe 214 curEventName = typesStats.getAttributeName(typeQuark);
200789b3
AM
215 eventCount = endState.get(typeQuark).getStateValue().unboxInt();
216 map.put(curEventName, eventCount);
217 }
218
219 } catch (TimeRangeException e) {
1c0de632 220 /* Assume there is no events, nothing will be put in the map. */
8192f2c6 221 } catch (AttributeNotFoundException | StateValueTypeException | StateSystemDisposedException e) {
96345c5a 222 e.printStackTrace();
200789b3
AM
223 }
224 return map;
225 }
226
227 @Override
8b260d9f 228 public long getEventsInRange(long start, long end) {
e1c43333
AM
229 // FIXME Instead of waiting until the end, we could check the current
230 // end time, and answer as soon as possible...
802017fe 231 totalsStats.waitUntilBuilt();
e1c43333 232
f3f93fa6 233 long startCount;
802017fe 234 if (start == totalsStats.getStartTime()) {
f3f93fa6
AM
235 startCount = 0;
236 } else {
237 /*
238 * We want the events happening at "start" to be included, so we'll
239 * need to query one unit before that point.
240 */
241 startCount = getEventCountAt(start - 1);
200789b3 242 }
f3f93fa6 243 long endCount = getEventCountAt(end);
df310609 244
f3f93fa6 245 return endCount - startCount;
200789b3
AM
246 }
247
248 @Override
8b260d9f 249 public Map<String, Long> getEventTypesInRange(long start, long end) {
e1c43333
AM
250 // FIXME Instead of waiting until the end, we could check the current
251 // end time, and answer as soon as possible...
802017fe 252 typesStats.waitUntilBuilt();
e1c43333 253
a4524c1b 254 Map<String, Long> map = new HashMap<>();
200789b3
AM
255
256 /* Make sure the start/end times are within the state history, so we
257 * don't get TimeRange exceptions.
258 */
1c0de632
AM
259 long startTime = checkStartTime(start);
260 long endTime = checkEndTime(end);
200789b3
AM
261
262 try {
263 /* Get the list of quarks, one for each even type in the database */
802017fe
AM
264 int quark = typesStats.getQuarkAbsolute(Attributes.EVENT_TYPES);
265 List<Integer> quarks = typesStats.getSubAttributes(quark, false);
200789b3 266
802017fe 267 List<ITmfStateInterval> endState = typesStats.queryFullState(endTime);
200789b3 268
200789b3
AM
269 String curEventName;
270 long countAtStart, countAtEnd, eventCount;
200789b3 271
802017fe 272 if (startTime == typesStats.getStartTime()) {
e1c43333
AM
273 /* Only use the values picked up at the end time */
274 for (int typeQuark : quarks) {
802017fe 275 curEventName = typesStats.getAttributeName(typeQuark);
e1c43333
AM
276 eventCount = endState.get(typeQuark).getStateValue().unboxInt();
277 if (eventCount == -1) {
278 eventCount = 0;
279 }
280 map.put(curEventName, eventCount);
200789b3 281 }
e1c43333 282 } else {
200789b3 283 /*
e1c43333
AM
284 * Query the start time at -1, so the beginning of the interval
285 * is inclusive.
200789b3 286 */
802017fe 287 List<ITmfStateInterval> startState = typesStats.queryFullState(startTime - 1);
e1c43333 288 for (int typeQuark : quarks) {
802017fe 289 curEventName = typesStats.getAttributeName(typeQuark);
e1c43333
AM
290 countAtStart = startState.get(typeQuark).getStateValue().unboxInt();
291 countAtEnd = endState.get(typeQuark).getStateValue().unboxInt();
292
293 if (countAtStart == -1) {
294 countAtStart = 0;
295 }
296 if (countAtEnd == -1) {
297 countAtEnd = 0;
298 }
299 eventCount = countAtEnd - countAtStart;
300 map.put(curEventName, eventCount);
200789b3 301 }
200789b3 302 }
e1c43333 303
200789b3 304 } catch (TimeRangeException e) {
1c0de632 305 /* Assume there is no events, nothing will be put in the map. */
8192f2c6 306 } catch (AttributeNotFoundException | StateValueTypeException | StateSystemDisposedException e) {
200789b3 307 /*
1c0de632
AM
308 * These other exception types would show a logic problem however,
309 * so they should not happen.
200789b3
AM
310 */
311 e.printStackTrace();
200789b3
AM
312 }
313 return map;
314 }
315
802017fe
AM
316 // ------------------------------------------------------------------------
317 // Helper methods
318 // ------------------------------------------------------------------------
319
f3f93fa6
AM
320 private long getEventCountAt(long timestamp) {
321 /* Make sure the target time is within the range of the history */
322 long ts = checkStartTime(timestamp);
323 ts = checkEndTime(ts);
324
325 try {
802017fe
AM
326 final int quark = totalsStats.getQuarkAbsolute(Attributes.TOTAL);
327 long count = totalsStats.querySingleState(ts, quark).getStateValue().unboxInt();
f3f93fa6
AM
328 return count;
329
330 } catch (TimeRangeException e) {
331 /* Assume there is no events for that range */
8192f2c6 332 } catch (AttributeNotFoundException | StateValueTypeException | StateSystemDisposedException e) {
f3f93fa6
AM
333 e.printStackTrace();
334 }
335
336 return 0;
337 }
338
8b260d9f
AM
339 private long checkStartTime(long initialStart) {
340 long start = initialStart;
802017fe
AM
341 if (start < totalsStats.getStartTime()) {
342 return totalsStats.getStartTime();
200789b3
AM
343 }
344 return start;
345 }
346
8b260d9f
AM
347 private long checkEndTime(long initialEnd) {
348 long end = initialEnd;
802017fe
AM
349 if (end > totalsStats.getCurrentEndTime()) {
350 return totalsStats.getCurrentEndTime();
200789b3
AM
351 }
352 return end;
353 }
354
200789b3
AM
355 /**
356 * The attribute names that are used in the state provider
357 */
358 public static class Attributes {
359
df310609
AM
360 /** Total nb of events */
361 public static final String TOTAL = "total"; //$NON-NLS-1$
362
200789b3
AM
363 /** event_types */
364 public static final String EVENT_TYPES = "event_types"; //$NON-NLS-1$<
365 }
366}
This page took 0.053817 seconds and 5 git commands to generate.