tmf/lttng: Fix newly-introduced Javadoc warnings
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / statistics / TmfStateStatistics.java
1 /*******************************************************************************
2 * Copyright (c) 2012 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 ******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.core.statistics;
14
15 import java.io.File;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19
20 import org.eclipse.core.resources.IResource;
21 import org.eclipse.core.runtime.CoreException;
22 import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
23 import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
24 import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
25 import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
26 import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
27 import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
28 import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
29 import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
30 import org.eclipse.linuxtools.tmf.core.signal.TmfSignal;
31 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
32 import org.eclipse.linuxtools.tmf.core.signal.TmfStatsUpdatedSignal;
33 import org.eclipse.linuxtools.tmf.core.statesystem.IStateChangeInput;
34 import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
35 import org.eclipse.linuxtools.tmf.core.statesystem.StateSystemManager;
36 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
37
38 /**
39 * Implementation of ITmfStatistics which uses a state history for storing its
40 * information.
41 *
42 * It requires building the history first, but gives very fast response times
43 * when built : Queries are O(log n) wrt the size of the trace, and O(1) wrt to
44 * the size of the time interval selected.
45 *
46 * @author Alexandre Montplaisir
47 * @since 2.0
48 */
49
50 public class TmfStateStatistics implements ITmfStatistics {
51
52 /** ID for the statistics state system */
53 public static final String STATE_ID = "org.eclipse.linuxtools.tmf.statistics"; //$NON-NLS-1$
54
55 /** Filename the "statistics state history" file will have */
56 private static final String STATS_STATE_FILENAME = "statistics.ht"; //$NON-NLS-1$
57
58 private final ITmfTrace trace;
59
60 /**
61 * The state system that's used to stored the statistics. It's hidden from
62 * the trace, so that it doesn't conflict with ITmfTrace.getStateSystem()
63 * (which is something else!)
64 */
65 private final ITmfStateSystem stats;
66
67 /**
68 * Empty constructor. The resulting TmfStatistics object will not be usable,
69 * but it might be needed for sub-classes.
70 */
71 public TmfStateStatistics() {
72 stats = null;
73 trace = null;
74 }
75
76 /**
77 * Constructor
78 *
79 * @param trace
80 * The trace for which we build these statistics
81 * @throws TmfTraceException
82 * If something went wrong trying to initialize the statistics
83 */
84 public TmfStateStatistics(ITmfTrace trace) throws TmfTraceException {
85 /* Set up the path to the history tree file we'll use */
86 this.trace = trace;
87 IResource resource = trace.getResource();
88 String supplDirectory = null;
89
90 try {
91 // get the directory where the history file will be stored.
92 supplDirectory = resource.getPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER);
93 } catch (CoreException e) {
94 throw new TmfTraceException(e.toString(), e);
95 }
96
97 final File htFile = new File(supplDirectory + File.separator + STATS_STATE_FILENAME);
98 final IStateChangeInput htInput = new StatsStateProvider(trace);
99
100 this.stats = StateSystemManager.loadStateHistory(htFile, htInput, STATE_ID, false);
101 }
102
103 /**
104 * Manual constructor. This should be used if the trace's Resource is null
105 * (ie, for unit tests). It requires specifying the location of the history
106 * file manually.
107 *
108 * @param trace
109 * The trace for which we build these statistics
110 * @param historyFile
111 * The location of the state history file to build for the stats
112 * @throws TmfTraceException
113 * If the file could not be written to
114 */
115 public TmfStateStatistics(ITmfTrace trace, File historyFile) throws TmfTraceException {
116 this.trace = trace;
117 final IStateChangeInput htInput = new StatsStateProvider(trace);
118 this.stats = StateSystemManager.loadStateHistory(historyFile, htInput, STATE_ID, true);
119 }
120
121 // ------------------------------------------------------------------------
122 // ITmfStatistics
123 // ------------------------------------------------------------------------
124
125 @Override
126 public void dispose() {
127 stats.dispose();
128 }
129
130 @Override
131 public void updateStats(final boolean isGlobal, final ITmfTimestamp start,
132 final ITmfTimestamp end) {
133 /*
134 * Since we are currently in a signal handler (ie, in the UI thread),
135 * and since state system queries can be arbitrarily long (O(log n) wrt
136 * the size of the trace), we will run those queries in a separate
137 * thread and update the statistics view out-of-band.
138 */
139 Thread statsThread = new Thread("Statistics update") { //$NON-NLS-1$
140 @Override
141 public void run() {
142 long total;
143 Map<String, Long> map;
144
145 /* Wait until the history building completed */
146 if (!stats.waitUntilBuilt()) {
147 return;
148 }
149
150 /* Range should be valid for both global and time range queries */
151 total = getEventsInRange(start, end);
152 map = getEventTypesInRange(start, end);
153
154 /* Send the signal to notify the stats viewer to update its display */
155 TmfSignal sig = new TmfStatsUpdatedSignal(this, trace, isGlobal, total, map);
156 TmfSignalManager.dispatchSignal(sig);
157 }
158 };
159 statsThread.start();
160 return;
161
162 }
163
164 @Override
165 public long getEventsTotal() {
166 /* We need the complete state history to be built to answer this. */
167 stats.waitUntilBuilt();
168
169 long endTime = stats.getCurrentEndTime();
170 int count = 0;
171
172 try {
173 final int quark = stats.getQuarkAbsolute(Attributes.TOTAL);
174 count= stats.querySingleState(endTime, quark).getStateValue().unboxInt();
175
176 } catch (TimeRangeException e) {
177 /* Assume there is no events for that range */
178 return 0;
179 } catch (AttributeNotFoundException e) {
180 e.printStackTrace();
181 } catch (StateValueTypeException e) {
182 e.printStackTrace();
183 } catch (StateSystemDisposedException e) {
184 e.printStackTrace();
185 }
186
187 return count;
188 }
189
190 @Override
191 public Map<String, Long> getEventTypesTotal() {
192 /* We need the complete state history to be built to answer this. */
193 stats.waitUntilBuilt();
194
195 Map<String, Long> map = new HashMap<String, Long>();
196 long endTime = stats.getCurrentEndTime();
197
198 try {
199 /* Get the list of quarks, one for each even type in the database */
200 int quark = stats.getQuarkAbsolute(Attributes.EVENT_TYPES);
201 List<Integer> quarks = stats.getSubAttributes(quark, false);
202
203 /* Since we want the total we can look only at the end */
204 List<ITmfStateInterval> endState = stats.queryFullState(endTime);
205
206 String curEventName;
207 long eventCount;
208 for (int typeQuark : quarks) {
209 curEventName = stats.getAttributeName(typeQuark);
210 eventCount = endState.get(typeQuark).getStateValue().unboxInt();
211 map.put(curEventName, eventCount);
212 }
213
214 } catch (TimeRangeException e) {
215 /* Assume there is no events, nothing will be put in the map. */
216 } catch (AttributeNotFoundException e) {
217 e.printStackTrace();
218 } catch (StateValueTypeException e) {
219 e.printStackTrace();
220 } catch (StateSystemDisposedException e) {
221 e.printStackTrace();
222 }
223 return map;
224 }
225
226 @Override
227 public long getEventsInRange(ITmfTimestamp start, ITmfTimestamp end) {
228 // FIXME Instead of waiting until the end, we could check the current
229 // end time, and answer as soon as possible...
230 stats.waitUntilBuilt();
231
232 int countAtStart = 0, countAtEnd = 0;
233 long startTime = checkStartTime(start);
234 long endTime = checkEndTime(end);
235
236 try {
237 final int quark = stats.getQuarkAbsolute(Attributes.TOTAL);
238 if (startTime == stats.getStartTime()) {
239 countAtStart = 0;
240 } else {
241 /* State system works that way... */
242 countAtStart = stats.querySingleState(startTime - 1, quark).getStateValue().unboxInt();
243 }
244 countAtEnd = stats.querySingleState(endTime, quark).getStateValue().unboxInt();
245
246 } catch (TimeRangeException e) {
247 /* Assume there is no events for that range */
248 return 0;
249 } catch (AttributeNotFoundException e) {
250 e.printStackTrace();
251 } catch (StateValueTypeException e) {
252 e.printStackTrace();
253 } catch (StateSystemDisposedException e) {
254 e.printStackTrace();
255 }
256
257 long total = countAtEnd - countAtStart;
258 return total;
259 }
260
261 @Override
262 public Map<String, Long> getEventTypesInRange(ITmfTimestamp start, ITmfTimestamp end) {
263 // FIXME Instead of waiting until the end, we could check the current
264 // end time, and answer as soon as possible...
265 stats.waitUntilBuilt();
266
267 Map<String, Long> map = new HashMap<String, Long>();
268
269 /* Make sure the start/end times are within the state history, so we
270 * don't get TimeRange exceptions.
271 */
272 long startTime = checkStartTime(start);
273 long endTime = checkEndTime(end);
274
275 try {
276 /* Get the list of quarks, one for each even type in the database */
277 int quark = stats.getQuarkAbsolute(Attributes.EVENT_TYPES);
278 List<Integer> quarks = stats.getSubAttributes(quark, false);
279
280 List<ITmfStateInterval> endState = stats.queryFullState(endTime);
281
282 String curEventName;
283 long countAtStart, countAtEnd, eventCount;
284
285 if (startTime == stats.getStartTime()) {
286 /* Only use the values picked up at the end time */
287 for (int typeQuark : quarks) {
288 curEventName = stats.getAttributeName(typeQuark);
289 eventCount = endState.get(typeQuark).getStateValue().unboxInt();
290 if (eventCount == -1) {
291 eventCount = 0;
292 }
293 map.put(curEventName, eventCount);
294 }
295 } else {
296 /*
297 * Query the start time at -1, so the beginning of the interval
298 * is inclusive.
299 */
300 List<ITmfStateInterval> startState = stats.queryFullState(startTime - 1);
301 for (int typeQuark : quarks) {
302 curEventName = stats.getAttributeName(typeQuark);
303 countAtStart = startState.get(typeQuark).getStateValue().unboxInt();
304 countAtEnd = endState.get(typeQuark).getStateValue().unboxInt();
305
306 if (countAtStart == -1) {
307 countAtStart = 0;
308 }
309 if (countAtEnd == -1) {
310 countAtEnd = 0;
311 }
312 eventCount = countAtEnd - countAtStart;
313 map.put(curEventName, eventCount);
314 }
315 }
316
317 } catch (TimeRangeException e) {
318 /* Assume there is no events, nothing will be put in the map. */
319 } catch (AttributeNotFoundException e) {
320 /*
321 * These other exception types would show a logic problem however,
322 * so they should not happen.
323 */
324 e.printStackTrace();
325 } catch (StateValueTypeException e) {
326 e.printStackTrace();
327 } catch (StateSystemDisposedException e) {
328 e.printStackTrace();
329 }
330 return map;
331 }
332
333 private long checkStartTime(ITmfTimestamp startTs) {
334 long start = startTs.normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
335 if (start < stats.getStartTime()) {
336 return stats.getStartTime();
337 }
338 return start;
339 }
340
341 private long checkEndTime(ITmfTimestamp endTs) {
342 long end = endTs.normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
343 if (end > stats.getCurrentEndTime()) {
344 return stats.getCurrentEndTime();
345 }
346 return end;
347 }
348
349
350 /**
351 * The attribute names that are used in the state provider
352 */
353 public static class Attributes {
354
355 /** Total nb of events */
356 public static final String TOTAL = "total"; //$NON-NLS-1$
357
358 /** event_types */
359 public static final String EVENT_TYPES = "event_types"; //$NON-NLS-1$<
360 }
361 }
This page took 0.040662 seconds and 6 git commands to generate.