tmf: Introduce the ITmfStatistics interface
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / statistics / TmfStatistics.java
CommitLineData
200789b3
AM
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
13package org.eclipse.linuxtools.tmf.core.statistics;
14
15import java.io.File;
16import java.util.HashMap;
17import java.util.List;
18import java.util.Map;
19
20import org.eclipse.core.resources.IResource;
21import org.eclipse.core.runtime.CoreException;
22import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
23import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
24import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
25import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
26import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
27import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
28import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
29import org.eclipse.linuxtools.tmf.core.statesystem.IStateChangeInput;
30import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
31import org.eclipse.linuxtools.tmf.core.statesystem.StateSystemManager;
32import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
33
34/**
35 * Default implementation of an ITmfStatisticsProvider. It uses a state system
36 * underneath to store its information.
37 *
38 * @author Alexandre Montplaisir
39 * @since 2.0
40 */
41
42public class TmfStatistics implements ITmfStatistics {
43
44 /* Filename the "statistics state history" file will have */
45 private static final String STATS_STATE_FILENAME = "statistics.ht"; //$NON-NLS-1$
46
47 /*
48 * The state system that's used to stored the statistics. It's hidden from
49 * the trace, so that it doesn't conflict with ITmfTrace.getStateSystem()
50 * (which is something else!)
51 */
52 private final ITmfStateSystem stats;
53
54 /**
55 * Constructor
56 *
57 * @param trace
58 * The trace for which we build these statistics
59 * @throws TmfTraceException
60 * If something went wrong trying to initialize the statistics
61 */
62 public TmfStatistics(ITmfTrace trace) throws TmfTraceException {
63 /* Set up the path to the history tree file we'll use */
64 IResource resource = trace.getResource();
65 String supplDirectory = null;
66
67 try {
68 // get the directory where the history file will be stored.
69 supplDirectory = resource.getPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER);
70 } catch (CoreException e) {
71 throw new TmfTraceException(e.toString(), e);
72 }
73
74 final File htFile = new File(supplDirectory + File.separator + STATS_STATE_FILENAME);
75 final IStateChangeInput htInput = new StatsStateProvider(trace);
76
77 this.stats = StateSystemManager.loadStateHistory(htFile, htInput, false);
78 }
79
80 // ------------------------------------------------------------------------
81 // ITmfStatisticsProvider
82 // ------------------------------------------------------------------------
83
84 @Override
85 public long getEventsTotal() {
86 /*
87 * The total itself is not stored in the state, so we will do a
88 * "event types" query then add the contents manually.
89 */
90 Map<String, Long> map = getEventTypesTotal();
91 long total = 0;
92 for (long count : map.values()) {
93 total += count;
94 }
95 return total;
96 }
97
98 @Override
99 public Map<String, Long> getEventTypesTotal() {
100 Map<String, Long> map = new HashMap<String, Long>();
101 long endTime = stats.getCurrentEndTime(); //shouldn't need to check it...
102
103 try {
104 /* Get the list of quarks, one for each even type in the database */
105 int quark = stats.getQuarkAbsolute(Attributes.EVENT_TYPES);
106 List<Integer> quarks = stats.getSubAttributes(quark, false);
107
108 /* Since we want the total we can look only at the end */
109 List<ITmfStateInterval> endState = stats.queryFullState(endTime);
110
111 String curEventName;
112 long eventCount;
113 for (int typeQuark : quarks) {
114 curEventName = stats.getAttributeName(typeQuark);
115 eventCount = endState.get(typeQuark).getStateValue().unboxInt();
116 map.put(curEventName, eventCount);
117 }
118
119 } catch (TimeRangeException e) {
120 /* Ignore silently */
121 } catch (AttributeNotFoundException e) {
122 e.printStackTrace();
123 } catch (StateValueTypeException e) {
124 e.printStackTrace();
125 }
126 return map;
127 }
128
129 @Override
130 public long getEventsInRange(ITmfTimestamp start, ITmfTimestamp end) {
131 /*
132 * The total itself is not stored in the state, so we will do a
133 * "event types" query then add the contents manually.
134 */
135 Map<String, Long> map = getEventTypesInRange(start, end);
136 long total = 0;
137 for (long count : map.values()) {
138 total += count;
139 }
140 return total;
141 }
142
143 @Override
144 public Map<String, Long> getEventTypesInRange(ITmfTimestamp start, ITmfTimestamp end) {
145 Map<String, Long> map = new HashMap<String, Long>();
146
147 /* Make sure the start/end times are within the state history, so we
148 * don't get TimeRange exceptions.
149 */
150 long startTimestamp = checkStartTime(start.getValue());
151 long endTimestamp = checkEndTime(end.getValue());
152
153 try {
154 /* Get the list of quarks, one for each even type in the database */
155 int quark = stats.getQuarkAbsolute(Attributes.EVENT_TYPES);
156 List<Integer> quarks = stats.getSubAttributes(quark, false);
157
158 /*
159 * Get the complete states (in our case, event counts) at the start
160 * time and end time of the requested time range.
161 */
162 List<ITmfStateInterval> startState = stats.queryFullState(startTimestamp);
163 List<ITmfStateInterval> endState = stats.queryFullState(endTimestamp);
164
165 /* Save the relevant information in the map we will be returning */
166 String curEventName;
167 long countAtStart, countAtEnd, eventCount;
168 for (int typeQuark : quarks) {
169 curEventName = stats.getAttributeName(typeQuark);
170 countAtStart = startState.get(typeQuark).getStateValue().unboxInt();
171 countAtEnd = endState.get(typeQuark).getStateValue().unboxInt();
172
173 /*
174 * The default value for the statistics is 0, rather than the
175 * value -1 used by the state system for non-initialized state.
176 */
177 if (startTimestamp == stats.getStartTime() || countAtStart == -1) {
178 countAtStart = 0;
179 }
180
181 /*
182 * Workaround a bug in the state system where requests for the
183 * very last state change will give -1. Send the request 1ns
184 * before the end of the trace and add the last event to the
185 * count.
186 */
187 if (countAtEnd < 0) {
188 ITmfStateInterval realInterval = stats.querySingleState(endTimestamp - 1, typeQuark);
189 countAtEnd = realInterval.getStateValue().unboxInt() + 1;
190 }
191
192 /*
193 * If after this it is still at -1, it's because no event of
194 * this type happened during the requested time range.
195 */
196 if (countAtEnd < 0) {
197 countAtEnd = 0;
198 }
199
200 eventCount = countAtEnd - countAtStart;
201 map.put(curEventName, eventCount);
202 }
203 } catch (TimeRangeException e) {
204 /*
205 * If a request is made for an invalid time range, we will ignore it
206 * silently and not add any information to the map.
207 */
208 } catch (AttributeNotFoundException e) {
209 /*
210 * These other exceptions would show a logic problem however, so
211 * they should not happen.
212 */
213 e.printStackTrace();
214 } catch (StateValueTypeException e) {
215 e.printStackTrace();
216 }
217 return map;
218 }
219
220 private long checkStartTime(long start) {
221 if (start < stats.getStartTime()) {
222 return stats.getStartTime();
223 }
224 return start;
225 }
226
227 private long checkEndTime(long end) {
228 if (end > stats.getCurrentEndTime()) {
229 return stats.getCurrentEndTime();
230 }
231 return end;
232 }
233
234
235 /**
236 * The attribute names that are used in the state provider
237 */
238 public static class Attributes {
239
240 /** event_types */
241 public static final String EVENT_TYPES = "event_types"; //$NON-NLS-1$<
242 }
243}
This page took 0.034782 seconds and 5 git commands to generate.