1 /*******************************************************************************
2 * Copyright (c) 2012 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 ******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.core
.statistics
;
16 import java
.util
.HashMap
;
17 import java
.util
.List
;
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
.StateValueTypeException
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TmfTraceException
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.ITmfStateInterval
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.IStateChangeInput
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.ITmfStateSystem
;
31 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.StateSystemManager
;
32 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
35 * Default implementation of an ITmfStatisticsProvider. It uses a state system
36 * underneath to store its information.
38 * @author Alexandre Montplaisir
42 public class TmfStatistics
implements ITmfStatistics
{
44 /** ID for the statistics state system */
45 public static final String STATE_ID
= "org.eclipse.linuxtools.tmf.statistics"; //$NON-NLS-1$
47 /* Filename the "statistics state history" file will have */
48 private static final String STATS_STATE_FILENAME
= "statistics.ht"; //$NON-NLS-1$
51 * The state system that's used to stored the statistics. It's hidden from
52 * the trace, so that it doesn't conflict with ITmfTrace.getStateSystem()
53 * (which is something else!)
55 private final ITmfStateSystem stats
;
61 * The trace for which we build these statistics
62 * @throws TmfTraceException
63 * If something went wrong trying to initialize the statistics
65 public TmfStatistics(ITmfTrace trace
) throws TmfTraceException
{
66 /* Set up the path to the history tree file we'll use */
67 IResource resource
= trace
.getResource();
68 String supplDirectory
= null;
71 // get the directory where the history file will be stored.
72 supplDirectory
= resource
.getPersistentProperty(TmfCommonConstants
.TRACE_SUPPLEMENTARY_FOLDER
);
73 } catch (CoreException e
) {
74 throw new TmfTraceException(e
.toString(), e
);
77 final File htFile
= new File(supplDirectory
+ File
.separator
+ STATS_STATE_FILENAME
);
78 final IStateChangeInput htInput
= new StatsStateProvider(trace
);
80 this.stats
= StateSystemManager
.loadStateHistory(htFile
, htInput
, STATE_ID
, false);
83 // ------------------------------------------------------------------------
84 // ITmfStatisticsProvider
85 // ------------------------------------------------------------------------
88 public long getEventsTotal() {
90 * The total itself is not stored in the state, so we will do a
91 * "event types" query then add the contents manually.
93 Map
<String
, Long
> map
= getEventTypesTotal();
95 for (long count
: map
.values()) {
102 public Map
<String
, Long
> getEventTypesTotal() {
103 Map
<String
, Long
> map
= new HashMap
<String
, Long
>();
104 long endTime
= stats
.getCurrentEndTime(); //shouldn't need to check it...
107 /* Get the list of quarks, one for each even type in the database */
108 int quark
= stats
.getQuarkAbsolute(Attributes
.EVENT_TYPES
);
109 List
<Integer
> quarks
= stats
.getSubAttributes(quark
, false);
111 /* Since we want the total we can look only at the end */
112 List
<ITmfStateInterval
> endState
= stats
.queryFullState(endTime
);
116 for (int typeQuark
: quarks
) {
117 curEventName
= stats
.getAttributeName(typeQuark
);
118 eventCount
= endState
.get(typeQuark
).getStateValue().unboxInt();
119 map
.put(curEventName
, eventCount
);
122 } catch (TimeRangeException e
) {
123 /* Ignore silently */
124 } catch (AttributeNotFoundException e
) {
126 } catch (StateValueTypeException e
) {
133 public long getEventsInRange(ITmfTimestamp start
, ITmfTimestamp end
) {
135 * The total itself is not stored in the state, so we will do a
136 * "event types" query then add the contents manually.
138 Map
<String
, Long
> map
= getEventTypesInRange(start
, end
);
140 for (long count
: map
.values()) {
147 public Map
<String
, Long
> getEventTypesInRange(ITmfTimestamp start
, ITmfTimestamp end
) {
148 Map
<String
, Long
> map
= new HashMap
<String
, Long
>();
150 /* Make sure the start/end times are within the state history, so we
151 * don't get TimeRange exceptions.
153 long startTimestamp
= checkStartTime(start
.getValue());
154 long endTimestamp
= checkEndTime(end
.getValue());
157 /* Get the list of quarks, one for each even type in the database */
158 int quark
= stats
.getQuarkAbsolute(Attributes
.EVENT_TYPES
);
159 List
<Integer
> quarks
= stats
.getSubAttributes(quark
, false);
162 * Get the complete states (in our case, event counts) at the start
163 * time and end time of the requested time range.
165 List
<ITmfStateInterval
> startState
= stats
.queryFullState(startTimestamp
);
166 List
<ITmfStateInterval
> endState
= stats
.queryFullState(endTimestamp
);
168 /* Save the relevant information in the map we will be returning */
170 long countAtStart
, countAtEnd
, eventCount
;
171 for (int typeQuark
: quarks
) {
172 curEventName
= stats
.getAttributeName(typeQuark
);
173 countAtStart
= startState
.get(typeQuark
).getStateValue().unboxInt();
174 countAtEnd
= endState
.get(typeQuark
).getStateValue().unboxInt();
177 * The default value for the statistics is 0, rather than the
178 * value -1 used by the state system for non-initialized state.
180 if (startTimestamp
== stats
.getStartTime() || countAtStart
== -1) {
185 * Workaround a bug in the state system where requests for the
186 * very last state change will give -1. Send the request 1ns
187 * before the end of the trace and add the last event to the
190 if (countAtEnd
< 0) {
191 ITmfStateInterval realInterval
= stats
.querySingleState(endTimestamp
- 1, typeQuark
);
192 countAtEnd
= realInterval
.getStateValue().unboxInt() + 1;
196 * If after this it is still at -1, it's because no event of
197 * this type happened during the requested time range.
199 if (countAtEnd
< 0) {
203 eventCount
= countAtEnd
- countAtStart
;
204 map
.put(curEventName
, eventCount
);
206 } catch (TimeRangeException e
) {
208 * If a request is made for an invalid time range, we will ignore it
209 * silently and not add any information to the map.
211 } catch (AttributeNotFoundException e
) {
213 * These other exceptions would show a logic problem however, so
214 * they should not happen.
217 } catch (StateValueTypeException e
) {
223 private long checkStartTime(long start
) {
224 if (start
< stats
.getStartTime()) {
225 return stats
.getStartTime();
230 private long checkEndTime(long end
) {
231 if (end
> stats
.getCurrentEndTime()) {
232 return stats
.getCurrentEndTime();
239 * The attribute names that are used in the state provider
241 public static class Attributes
{
244 public static final String EVENT_TYPES
= "event_types"; //$NON-NLS-1$<