* Contributors:
* Mathieu Denis <mathieu.denis@polymtl.ca> - Initial API and implementation
* Alexandre Montplaisir - Port to ITmfStatistics provider
+ * Patrick Tasse - Support selection range
*******************************************************************************/
package org.eclipse.linuxtools.tmf.ui.viewers.statistics;
import java.util.List;
import java.util.Map;
+import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
-import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
+import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
-import org.eclipse.linuxtools.tmf.core.signal.TmfStatsUpdatedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal;
import org.eclipse.linuxtools.tmf.core.statistics.ITmfStatistics;
import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
+import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewer;
import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.ITmfColumnDataProvider;
import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfTreeContentProvider;
+import org.eclipse.linuxtools.tmf.ui.views.statistics.TmfStatisticsModule;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
*/
private boolean fSendRangeRequest = true;
+ /** Reference to the trace manager */
+ private final TmfTraceManager fTraceManager;
+
/**
* Empty constructor. To be used in conjunction with
* {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
*/
public TmfStatisticsViewer() {
super();
+ fTraceManager = TmfTraceManager.getInstance();
}
/**
*/
public TmfStatisticsViewer(Composite parent, String viewerName, ITmfTrace trace) {
init(parent, viewerName, trace);
+ fTraceManager = TmfTraceManager.getInstance();
}
/**
initInput();
}
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.linuxtools.tmf.core.component.TmfComponent#dispose()
- */
@Override
public void dispose() {
super.dispose();
// Sends the time range request only once from this method.
if (fSendRangeRequest) {
fSendRangeRequest = false;
- requestTimeRangeData(trace, fTrace.getCurrentRange());
+ ITmfTimestamp begin = fTraceManager.getSelectionBeginTime();
+ ITmfTimestamp end = fTraceManager.getSelectionEndTime();
+ TmfTimeRange timeRange = new TmfTimeRange(begin, end);
+ requestTimeRangeData(trace, timeRange);
}
}
requestData(trace, signal.getRange());
*
* @param signal
* Contains the information about the new selected time range.
+ * @deprecated
+ * As of 2.1, use {@link #timeSynchUpdated(TmfTimeSynchSignal)}
*/
+ @Deprecated
@TmfSignalHandler
public void timeRangeUpdated(TmfRangeSynchSignal signal) {
- if (fTrace == null) {
- return;
- }
- requestTimeRangeData(fTrace, signal.getCurrentRange());
}
/**
- * Whenever a trace's statistics back-end finishes computing the statistics
- * for a given interval, it will send the StatsUpdated signal. This method
- * will receive this signal and update the statistics view accordingly.
+ * Handles the time synch updated signal. It updates the time range
+ * statistics.
*
- * @param sig
- * The signal that is received
+ * @param signal
+ * Contains the information about the new selected time range.
+ * @since 2.1
*/
@TmfSignalHandler
- public void statsUpdated(TmfStatsUpdatedSignal sig) {
- /* Only handle this signal if it's about the trace we represent. */
- if (!isListeningTo(sig.getTrace())) {
+ public void timeSynchUpdated(TmfTimeSynchSignal signal) {
+ if (fTrace == null) {
return;
}
-
- final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
- Map<String, Long> map = sig.getEventsPerType();
- String name = sig.getTrace().getName();
- boolean isGlobal = sig.isGlobal();
-
- /*
- * "Global", "partial", "total", etc., it's all very confusing...
- *
- * The base view shows the total count for the trace and for
- * each even types, organized in columns like this:
- *
- * | Global | Time range |
- * trace name | A | B |
- * Event Type | | |
- * <event 1> | C | D |
- * <event 2> | ... | ... |
- * ... | | |
- *
- * Here, we called the cells like this:
- * A : GlobalTotal
- * B : TimeRangeTotal
- * C : GlobalTypeCount(s)
- * D : TimeRangeTypeCount(s)
- */
-
- /* Fill in an the event counts (either cells C or D) */
- for (Map.Entry<String, Long> entry : map.entrySet()) {
- statsData.setTypeCount(name, entry.getKey(), isGlobal, entry.getValue());
- }
-
- /*
- * Calculate the totals (cell A or B, depending if isGlobal). We will
- * use the results of the previous request instead of sending another
- * one.
- */
- long globalTotal = 0;
- for (long val : map.values()) {
- globalTotal += val;
- }
- statsData.setTotal(name, isGlobal, globalTotal);
-
- modelComplete(isGlobal);
+ ITmfTimestamp begin = signal.getBeginTime();
+ ITmfTimestamp end = signal.getEndTime();
+ TmfTimeRange timeRange = new TmfTimeRange(begin, end);
+ requestTimeRangeData(fTrace, timeRange);
}
// ------------------------------------------------------------------------
*
* @param request
* The request to be canceled
+ * @since 3.0
*/
- protected void cancelOngoingRequest(ITmfDataRequest request) {
+ protected void cancelOngoingRequest(ITmfEventRequest request) {
if (request != null && !request.isCompleted()) {
request.cancel();
}
// Checks if the trace is already in the statistics tree.
int numNodeTraces = statisticsTreeNode.getNbChildren();
- int numTraces = 1;
- ITmfTrace[] trace = { fTrace };
- // For experiment, gets all the traces within it
- if (fTrace instanceof TmfExperiment) {
- TmfExperiment experiment = (TmfExperiment) fTrace;
- numTraces = experiment.getTraces().length;
- trace = experiment.getTraces();
- }
+ ITmfTrace[] traces = TmfTraceManager.getTraceSet(fTrace);
+ int numTraces = traces.length;
if (numTraces == numNodeTraces) {
boolean same = true;
* previously selected.
*/
for (int i = 0; i < numTraces; i++) {
- String traceName = trace[i].getName();
+ String traceName = traces[i].getName();
if (!statisticsTreeNode.containsChild(traceName)) {
same = false;
break;
* Tells if the request is for the global event count or the
* partial one.
*/
- private void buildStatisticsTree(final ITmfTrace trace, TmfTimeRange timeRange, boolean isGlobal) {
+ private void buildStatisticsTree(final ITmfTrace trace, final TmfTimeRange timeRange, final boolean isGlobal) {
final TmfStatisticsTreeNode statTree = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
if (statsData == null) {
statTree.resetTimeRangeValue();
}
- ITmfTrace[] traces;
- if (trace instanceof TmfExperiment) {
- TmfExperiment experiment = (TmfExperiment) trace;
- traces = experiment.getTraces();
- } else {
- traces = new ITmfTrace[] { trace };
- }
- for (final ITmfTrace aTrace : traces) {
+ for (final ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) {
if (!isListeningTo(aTrace)) {
continue;
}
- /* Retrieves the statistics object */
- final ITmfStatistics stats = aTrace.getStatistics();
- if (stats == null) {
- /*
- * The statistics provider for this trace is not accessible
- * (yet?). Try the next one.
- */
+ /* Retrieve the statistics object */
+ final TmfStatisticsModule statsMod = aTrace.getAnalysisModuleOfClass(TmfStatisticsModule.class, TmfStatisticsModule.ID);
+ if (statsMod == null) {
+ /* No statistics module available for this trace */
continue;
}
- /* The generic statistics are stored in nanoseconds, so we must make
- * sure the time range is scaled correctly. */
- long start = timeRange.getStartTime().normalize(0, TIME_SCALE).getValue();
- long end = timeRange.getEndTime().normalize(0, TIME_SCALE).getValue();
+ /* Run the potentially long queries in a separate thread */
+ Thread statsThread = new Thread("Statistics update") { //$NON-NLS-1$
+ @Override
+ public void run() {
+ /* Wait until the analysis is ready */
+ if (!statsMod.waitForCompletion(new NullProgressMonitor())) {
+ return;
+ }
- /*
- * Send a request to update the statistics view. The result will
- * be sent through a {@link TmfStatsUpdatedSignal}, and will be
- * processed by the signal handler.
- */
- aTrace.getStatistics().updateStats(isGlobal, start, end);
+ ITmfStatistics stats = statsMod.getStatistics();
+ if (stats == null) {
+ /* It should have worked, but didn't */
+ return;
+ }
+
+ /*
+ * The generic statistics are stored in nanoseconds, so
+ * we must make sure the time range is scaled correctly.
+ */
+ long start = timeRange.getStartTime().normalize(0, TIME_SCALE).getValue();
+ long end = timeRange.getEndTime().normalize(0, TIME_SCALE).getValue();
+
+ Map<String, Long> map = stats.getEventTypesInRange(start, end);
+ updateStats(isGlobal, map);
+ }
+ };
+ statsThread.start();
+ return;
}
}
}
+ /**
+ * Whenever a trace's statistics back-end finishes computing the statistics
+ * for a given interval, it will send the StatsUpdated signal. This method
+ * will receive this signal and update the statistics view accordingly.
+ *
+ * @param sig
+ * The signal that is received
+ */
+ private void updateStats(boolean isGlobal, Map<String, Long> eventsPerType) {
+
+ final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
+ Map<String, Long> map = eventsPerType;
+ String name = fTrace.getName();
+
+ /*
+ * "Global", "partial", "total", etc., it's all very confusing...
+ *
+ * The base view shows the total count for the trace and for
+ * each even types, organized in columns like this:
+ *
+ * | Global | Time range |
+ * trace name | A | B |
+ * Event Type | | |
+ * <event 1> | C | D |
+ * <event 2> | ... | ... |
+ * ... | | |
+ *
+ * Here, we called the cells like this:
+ * A : GlobalTotal
+ * B : TimeRangeTotal
+ * C : GlobalTypeCount(s)
+ * D : TimeRangeTypeCount(s)
+ */
+
+ /* Fill in an the event counts (either cells C or D) */
+ for (Map.Entry<String, Long> entry : map.entrySet()) {
+ statsData.setTypeCount(name, entry.getKey(), isGlobal, entry.getValue());
+ }
+
+ /*
+ * Calculate the totals (cell A or B, depending if isGlobal). We will
+ * use the results of the previous request instead of sending another
+ * one.
+ */
+ long globalTotal = 0;
+ for (long val : map.values()) {
+ globalTotal += val;
+ }
+ statsData.setTotal(name, isGlobal, globalTotal);
+
+ modelComplete(isGlobal);
+ }
+
/**
* Resets the number of events within the time range
*/