/*******************************************************************************
- * Copyright (c) 2012, 2013 Ericsson
+ * Copyright (c) 2012, 2014 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
*
* Contributors:
* Alexandre Montplaisir - Initial API and implementation
+ * Patrick Tasse - Fix TimeRangeException
******************************************************************************/
package org.eclipse.linuxtools.tmf.core.statistics;
-import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
-import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
-import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
-import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
-import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
-import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
-import org.eclipse.linuxtools.tmf.core.signal.TmfSignal;
-import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
-import org.eclipse.linuxtools.tmf.core.signal.TmfStatsUpdatedSignal;
-import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateProvider;
-import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
-import org.eclipse.linuxtools.tmf.core.statesystem.TmfStateSystemFactory;
-import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
-import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.linuxtools.statesystem.core.ITmfStateSystem;
+import org.eclipse.linuxtools.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.linuxtools.statesystem.core.interval.ITmfStateInterval;
/**
* Implementation of ITmfStatistics which uses a state history for storing its
*/
public class TmfStateStatistics implements ITmfStatistics {
- // ------------------------------------------------------------------------
- // Constants
- // ------------------------------------------------------------------------
-
- /**
- * @deprecated Do not use, it's been replaced by {@link #TOTALS_STATE_ID}
- * and {@link #TYPES_STATE_ID}
- */
- @Deprecated
- public static final String STATE_ID = "org.eclipse.linuxtools.tmf.statistics"; //$NON-NLS-1$
-
- /** ID for the "event totals" statistics state system
- * @since 2.2 */
- public static final String TOTALS_STATE_ID = "org.eclipse.linuxtools.tmf.statistics.totals"; //$NON-NLS-1$
-
- /** ID for the "event types" statistics state system
- * @since 2.2 */
- public static final String TYPES_STATE_ID = "org.eclipse.linuxtools.tmf.statistics.types"; //$NON-NLS-1$
-
- /** Filename for the "event totals" state history file */
- private static final String TOTALS_STATE_FILENAME = "statistics-totals.ht"; //$NON-NLS-1$
-
- /** Filename for the "event types" state history file */
- private static final String TYPES_STATE_FILENAME = "statistics-types.ht"; //$NON-NLS-1$
-
// ------------------------------------------------------------------------
// Fields
// ------------------------------------------------------------------------
- private final ITmfTrace trace;
-
/** The event totals state system */
private final ITmfStateSystem totalsStats;
// Constructors
// ------------------------------------------------------------------------
- /**
- * Empty constructor. The resulting TmfStatistics object will not be usable,
- * but it might be needed for sub-classes.
- */
- public TmfStateStatistics() {
- totalsStats = null;
- typesStats = null;
- trace = null;
- }
-
/**
* Constructor
*
- * @param trace
- * The trace for which we build these statistics
- * @throws TmfTraceException
- * If something went wrong trying to initialize the statistics
+ * @param totals
+ * The state system containing the "totals" information
+ * @param eventTypes
+ * The state system containing the "event types" information
+ * @since 3.0
*/
- public TmfStateStatistics(ITmfTrace trace) throws TmfTraceException {
- this.trace = trace;
- String directory = TmfTraceManager.getSupplementaryFileDir(trace);
-
- final File totalsFile = new File(directory + TOTALS_STATE_FILENAME);
- final ITmfStateProvider totalsInput = new StatsProviderTotals(trace);
- this.totalsStats = TmfStateSystemFactory.newFullHistory(totalsFile, totalsInput, false);
-
- final File typesFile = new File(directory + TYPES_STATE_FILENAME);
- final ITmfStateProvider typesInput = new StatsProviderEventTypes(trace);
- this.typesStats = TmfStateSystemFactory.newFullHistory(typesFile, typesInput, false);
-
- registerStateSystems();
+ public TmfStateStatistics(@NonNull ITmfStateSystem totals, @NonNull ITmfStateSystem eventTypes) {
+ this.totalsStats = totals;
+ this.typesStats = eventTypes;
}
/**
- * Old manual constructor.
+ * Return the state system containing the "totals" values
*
- * @param trace Trace
- * @param historyFile Full history file
- * @deprecated Need to use {@link #TmfStateStatistics(ITmfTrace trace,
- * File fullHistoryFile, File partialHistoryFile)} now.
+ * @return The "totals" state system
+ * @since 3.0
*/
- @Deprecated
- public TmfStateStatistics(ITmfTrace trace, File historyFile) {
- this();
+ public ITmfStateSystem getTotalsSS() {
+ return totalsStats;
}
/**
- * Manual constructor. This should be used if the trace's Resource is null
- * (ie, for unit tests). It requires specifying the location of the history
- * files manually.
+ * Return the state system containing the "event types" values
*
- * @param trace
- * The trace for which we build these statistics
- * @param totalsHistoryFile
- * The location of the totals state history file
- * @param typesHistoryFile
- * The location of the types state history file
- * @throws TmfTraceException
- * If the file could not be written to
- * @since 2.2
+ * @return The "event types" state system
+ * @since 3.0
*/
- public TmfStateStatistics(ITmfTrace trace, File totalsHistoryFile,
- File typesHistoryFile) throws TmfTraceException {
- this.trace = trace;
- final ITmfStateProvider totalsInput = new StatsProviderTotals(trace);
- final ITmfStateProvider typesInput = new StatsProviderEventTypes(trace);
- this.totalsStats = TmfStateSystemFactory.newFullHistory(totalsHistoryFile, totalsInput, true);
- this.typesStats = TmfStateSystemFactory.newFullHistory(typesHistoryFile, typesInput, true);
- registerStateSystems();
- }
-
- /**
- * Register the state systems used here into the trace's state system map.
- */
- private void registerStateSystems() {
- trace.registerStateSystem(TOTALS_STATE_ID, totalsStats);
- trace.registerStateSystem(TYPES_STATE_ID, typesStats);
+ public ITmfStateSystem getEventTypesSS() {
+ return typesStats;
}
// ------------------------------------------------------------------------
typesStats.dispose();
}
- @Override
- public void updateStats(final boolean isGlobal, final long start,
- final long end) {
- /*
- * Since we are currently in a signal handler (ie, in the UI thread),
- * and since state system queries can be arbitrarily long (O(log n) wrt
- * the size of the trace), we will run those queries in a separate
- * thread and update the statistics view out-of-band.
- */
- Thread statsThread = new Thread("Statistics update") { //$NON-NLS-1$
- @Override
- public void run() {
- /* Wait until the history building is completed */
- if (!waitUntilBuilt()) {
- return;
- }
-
- /* Range should be valid for both global and time range queries */
- long total = getEventsInRange(start, end);
- Map<String, Long> map = getEventTypesInRange(start, end);
-
- /* Send the signal to notify the stats viewer to update its display */
- TmfSignal sig = new TmfStatsUpdatedSignal(this, trace, isGlobal, total, map);
- TmfSignalManager.dispatchSignal(sig);
- }
- };
- statsThread.start();
- return;
- }
-
@Override
public List<Long> histogramQuery(final long start, final long end, final int nb) {
- final List<Long> list = new LinkedList<Long>();
+ final List<Long> list = new LinkedList<>();
final long increment = (end - start) / nb;
- if (!totalsStats.waitUntilBuilt()) {
+ if (totalsStats.isCancelled()) {
return list;
}
@Override
public long getEventsTotal() {
- /* We need the complete state history to be built to answer this. */
- totalsStats.waitUntilBuilt();
-
long endTime = totalsStats.getCurrentEndTime();
int count = 0;
final int quark = totalsStats.getQuarkAbsolute(Attributes.TOTAL);
count= totalsStats.querySingleState(endTime, quark).getStateValue().unboxInt();
- } catch (TimeRangeException e) {
+ } catch (StateSystemDisposedException e) {
/* Assume there is no events for that range */
return 0;
} catch (AttributeNotFoundException e) {
e.printStackTrace();
- } catch (StateValueTypeException e) {
- e.printStackTrace();
- } catch (StateSystemDisposedException e) {
- e.printStackTrace();
}
return count;
@Override
public Map<String, Long> getEventTypesTotal() {
- /* We need the complete state history to be built to answer this. */
- typesStats.waitUntilBuilt();
-
- Map<String, Long> map = new HashMap<String, Long>();
+ final Map<String, Long> map = new HashMap<>();
long endTime = typesStats.getCurrentEndTime();
try {
map.put(curEventName, eventCount);
}
- } catch (TimeRangeException e) {
+ } catch (StateSystemDisposedException e) {
/* Assume there is no events, nothing will be put in the map. */
} catch (AttributeNotFoundException e) {
e.printStackTrace();
- } catch (StateValueTypeException e) {
- e.printStackTrace();
- } catch (StateSystemDisposedException e) {
- e.printStackTrace();
}
return map;
}
@Override
public long getEventsInRange(long start, long end) {
- // FIXME Instead of waiting until the end, we could check the current
- // end time, and answer as soon as possible...
- totalsStats.waitUntilBuilt();
-
long startCount;
if (start == totalsStats.getStartTime()) {
startCount = 0;
@Override
public Map<String, Long> getEventTypesInRange(long start, long end) {
- // FIXME Instead of waiting until the end, we could check the current
- // end time, and answer as soon as possible...
- typesStats.waitUntilBuilt();
-
- Map<String, Long> map = new HashMap<String, Long>();
+ final Map<String, Long> map = new HashMap<>();
+ List<Integer> quarks;
/* Make sure the start/end times are within the state history, so we
* don't get TimeRange exceptions.
*/
- long startTime = checkStartTime(start);
- long endTime = checkEndTime(end);
+ long startTime = checkStartTime(start, typesStats);
+ long endTime = checkEndTime(end, typesStats);
+ if (endTime < startTime) {
+ /* The start/end times do not intersect this state system range.
+ * Return the empty map. */
+ return map;
+ }
try {
/* Get the list of quarks, one for each even type in the database */
int quark = typesStats.getQuarkAbsolute(Attributes.EVENT_TYPES);
- List<Integer> quarks = typesStats.getSubAttributes(quark, false);
+ quarks = typesStats.getSubAttributes(quark, false);
+ } catch (AttributeNotFoundException e) {
+ /*
+ * The state system does not (yet?) have the needed attributes, it
+ * probably means there are no events counted yet. Return the empty
+ * map.
+ */
+ return map;
+ }
+ try {
List<ITmfStateInterval> endState = typesStats.queryFullState(endTime);
- String curEventName;
- long countAtStart, countAtEnd, eventCount;
-
if (startTime == typesStats.getStartTime()) {
/* Only use the values picked up at the end time */
for (int typeQuark : quarks) {
- curEventName = typesStats.getAttributeName(typeQuark);
- eventCount = endState.get(typeQuark).getStateValue().unboxInt();
+ String curEventName = typesStats.getAttributeName(typeQuark);
+ long eventCount = endState.get(typeQuark).getStateValue().unboxInt();
if (eventCount == -1) {
eventCount = 0;
}
*/
List<ITmfStateInterval> startState = typesStats.queryFullState(startTime - 1);
for (int typeQuark : quarks) {
- curEventName = typesStats.getAttributeName(typeQuark);
- countAtStart = startState.get(typeQuark).getStateValue().unboxInt();
- countAtEnd = endState.get(typeQuark).getStateValue().unboxInt();
+ String curEventName = typesStats.getAttributeName(typeQuark);
+ long countAtStart = startState.get(typeQuark).getStateValue().unboxInt();
+ long countAtEnd = endState.get(typeQuark).getStateValue().unboxInt();
if (countAtStart == -1) {
countAtStart = 0;
if (countAtEnd == -1) {
countAtEnd = 0;
}
- eventCount = countAtEnd - countAtStart;
+ long eventCount = countAtEnd - countAtStart;
map.put(curEventName, eventCount);
}
}
- } catch (TimeRangeException e) {
- /* Assume there is no events, nothing will be put in the map. */
- } catch (AttributeNotFoundException e) {
- /*
- * These other exception types would show a logic problem however,
- * so they should not happen.
- */
- e.printStackTrace();
- } catch (StateValueTypeException e) {
- e.printStackTrace();
} catch (StateSystemDisposedException e) {
- e.printStackTrace();
+ /* Assume there is no (more) events, nothing will be put in the map. */
}
return map;
}
private long getEventCountAt(long timestamp) {
/* Make sure the target time is within the range of the history */
- long ts = checkStartTime(timestamp);
- ts = checkEndTime(ts);
+ long ts = checkStartTime(timestamp, totalsStats);
+ ts = checkEndTime(ts, totalsStats);
try {
final int quark = totalsStats.getQuarkAbsolute(Attributes.TOTAL);
long count = totalsStats.querySingleState(ts, quark).getStateValue().unboxInt();
return count;
- } catch (TimeRangeException e) {
- /* Assume there is no events for that range */
- } catch (AttributeNotFoundException e) {
- e.printStackTrace();
- } catch (StateValueTypeException e) {
- e.printStackTrace();
} catch (StateSystemDisposedException e) {
+ /* Assume there is no (more) events, nothing will be put in the map. */
+ } catch (AttributeNotFoundException e) {
e.printStackTrace();
}
return 0;
}
- private long checkStartTime(long initialStart) {
+ private static long checkStartTime(long initialStart, ITmfStateSystem ss) {
long start = initialStart;
- if (start < totalsStats.getStartTime()) {
- return totalsStats.getStartTime();
+ if (start < ss.getStartTime()) {
+ return ss.getStartTime();
}
return start;
}
- private long checkEndTime(long initialEnd) {
+ private static long checkEndTime(long initialEnd, ITmfStateSystem ss) {
long end = initialEnd;
- if (end > totalsStats.getCurrentEndTime()) {
- return totalsStats.getCurrentEndTime();
+ if (end > ss.getCurrentEndTime()) {
+ return ss.getCurrentEndTime();
}
return end;
}
- /**
- * Wait until both backing state systems are finished building.
- *
- * @return If both state systems were built successfully
- */
- private boolean waitUntilBuilt() {
- boolean check1 = totalsStats.waitUntilBuilt();
- boolean check2 = typesStats.waitUntilBuilt();
- return (check1 && check2);
- }
-
-
/**
* The attribute names that are used in the state provider
*/