/*******************************************************************************
- * Copyright (c) 2012 Ericsson
+ * Copyright (c) 2012, 2013 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:
* 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.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.ui.viewers.statistics.model.AbsTmfStatisticsTree;
+import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
+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.TmfBaseColumnDataProvider;
-import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseStatisticsTree;
+import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
+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.TmfStatisticsTreeRootFactory;
import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfTreeContentProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
-import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
/**
* A basic viewer to display statistics in the statistics view.
*
+ * It is linked to a single ITmfTrace until its disposal.
+ *
* @author Mathieu Denis
* @version 2.0
* @since 2.0
*/
-public class TmfStatisticsViewer extends TmfComponent {
+public class TmfStatisticsViewer extends TmfViewer {
+
+ /**
+ * Timestamp scale (nanosecond)
+ */
+ public static final byte TIME_SCALE = ITmfTimestamp.NANOSECOND_SCALE;
/**
- * Refresh frequency
+ * Default PAGE_SIZE for background requests.
*/
- protected static final Long STATS_INPUT_CHANGED_REFRESH = 5000L;
+ protected static final int PAGE_SIZE = 50000;
+
+ /**
+ * Refresh frequency.
+ */
+ protected final Long STATS_INPUT_CHANGED_REFRESH = 5000L;
/**
* The actual tree viewer to display
protected TreeViewer fTreeViewer;
/**
- * View instance counter (for multiple statistic views)
+ * The statistics tree linked to this viewer
+ */
+ protected TmfStatisticsTree fStatisticsData;
+
+ /**
+ * Update synchronization parameter (used for streaming): Update busy
+ * indicator.
+ */
+ protected boolean fStatisticsUpdateBusy = false;
+
+ /**
+ * Update synchronization parameter (used for streaming): Update pending
+ * indicator.
+ */
+ protected boolean fStatisticsUpdatePending = false;
+
+ /**
+ * Update synchronization parameter (used for streaming): Pending Update
+ * time range.
+ */
+ protected TmfTimeRange fStatisticsUpdateRange = null;
+
+ /**
+ * Update synchronization object.
+ */
+ protected final Object fStatisticsUpdateSyncObj = new Object();
+
+ /**
+ * Update range synchronization object.
+ */
+ protected final Object fStatisticsRangeUpdateSyncObj = new Object();
+
+ /**
+ * The trace that is displayed by this viewer
+ */
+ protected ITmfTrace fTrace;
+
+ /**
+ * Stores the requested time range.
+ */
+ protected TmfTimeRange fRequestedTimerange;
+
+ /**
+ * Indicates to process all events
+ */
+ private boolean fProcessAll;
+
+ /**
+ * View instance counter (for multiple statistics views)
*/
private static int fCountInstance = 0;
private int fInstanceNb;
/**
- * Object to store the cursor while waiting for the experiment to load
+ * Object to store the cursor while waiting for the trace to load
*/
private Cursor fWaitCursor = null;
/**
- * Default constructor
+ * Counts the number of times waitCursor() has been called. It avoids
+ * removing the waiting cursor, since there may be multiple requests running
+ * at the same time.
+ */
+ private int fWaitCursorCount = 0;
+
+ /**
+ * Tells to send a time range request when the trace gets updated.
+ */
+ 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();
+ }
+
+ /**
+ * Create a basic statistics viewer. To be used in conjunction with
+ * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
+ *
+ * @param parent
+ * The parent composite that will hold the viewer
+ * @param viewerName
+ * The name that will be assigned to this viewer
+ * @param trace
+ * The trace that is displayed by this viewer
+ * @see TmfComponent
+ */
+ public TmfStatisticsViewer(Composite parent, String viewerName, ITmfTrace trace) {
+ init(parent, viewerName, trace);
+ fTraceManager = TmfTraceManager.getInstance();
+ }
+
+ /**
+ * Initialize the statistics viewer.
*
* @param parent
- * The parent of this viewer
+ * The parent component of the viewer.
+ * @param viewerName
+ * The name to give to the viewer.
+ * @param trace
+ * The trace that will be displayed by the viewer.
*/
- public TmfStatisticsViewer(Composite parent) {
+ public void init(Composite parent, String viewerName, ITmfTrace trace) {
+ super.init(parent, viewerName);
// Increment a counter to make sure the tree ID is unique.
fCountInstance++;
fInstanceNb = fCountInstance;
+ fTrace = trace;
+
+ // The viewer will process all events if he is assigned to an experiment
+ fProcessAll = (trace instanceof TmfExperiment);
+
+ initContent(parent);
+ initInput();
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (fWaitCursor != null) {
+ fWaitCursor.dispose();
+ }
+
+ // Clean the model for this viewer
+ TmfStatisticsTreeManager.removeStatTreeRoot(getTreeID());
+ }
+
+ // ------------------------------------------------------------------------
+ // Signal handlers
+ // ------------------------------------------------------------------------
+
+ /**
+ * Handles the signal about new trace range.
+ *
+ * @param signal
+ * The trace range updated signal
+ */
+ @TmfSignalHandler
+ public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) {
+ ITmfTrace trace = signal.getTrace();
+ // validate
+ if (!isListeningTo(trace)) {
+ return;
+ }
+
+ synchronized (fStatisticsRangeUpdateSyncObj) {
+ // Sends the time range request only once from this method.
+ if (fSendRangeRequest) {
+ fSendRangeRequest = false;
+ ITmfTimestamp begin = fTraceManager.getSelectionBeginTime();
+ ITmfTimestamp end = fTraceManager.getSelectionEndTime();
+ TmfTimeRange timeRange = new TmfTimeRange(begin, end);
+ requestTimeRangeData(trace, timeRange);
+ }
+ }
+ requestData(trace, signal.getRange());
+ }
+
+ /**
+ * Handles the time range updated signal. It updates the time range
+ * statistics.
+ *
+ * @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) {
+ }
+
+ /**
+ * Handles the time synch updated signal. It updates the time range
+ * statistics.
+ *
+ * @param signal
+ * Contains the information about the new selected time range.
+ * @since 3.0
+ */
+ @TmfSignalHandler
+ public void timeSynchUpdated(TmfTimeSynchSignal signal) {
+ if (fTrace == null) {
+ return;
+ }
+ ITmfTimestamp begin = signal.getBeginTime();
+ ITmfTimestamp end = signal.getEndTime();
+ TmfTimeRange timeRange = new TmfTimeRange(begin, end);
+ requestTimeRangeData(fTrace, timeRange);
+ }
+
+ /**
+ * 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
+ */
+ @TmfSignalHandler
+ public void statsUpdated(TmfStatsUpdatedSignal sig) {
+ /* Only handle this signal if it's about the trace we represent. */
+ if (!isListeningTo(sig.getTrace())) {
+ 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);
+ }
+
+ // ------------------------------------------------------------------------
+ // Class methods
+ // ------------------------------------------------------------------------
+
+ /*
+ * Returns the primary control associated with this viewer.
+ *
+ * @return the SWT control which displays this viewer's content
+ */
+ @Override
+ public Control getControl() {
+ return fTreeViewer.getControl();
+ }
+
+ /**
+ * Get the input of the viewer.
+ *
+ * @return an object representing the input of the statistics viewer.
+ */
+ public Object getInput() {
+ return fTreeViewer.getInput();
+ }
+
+ /**
+ * Return the size of the request when performing background request.
+ *
+ * @return the block size for background request.
+ */
+ public int getPageSize() {
+ return PAGE_SIZE;
+ }
+
+ /**
+ * Return the number of events to receive before a refresh of the viewer is
+ * performed.
+ *
+ * @return the input refresh rate
+ */
+ public long getRefreshRate() {
+ return STATS_INPUT_CHANGED_REFRESH;
+ }
+
+ /**
+ * This method can be overridden to implement another way of representing
+ * the statistics data and to retrieve the information for display.
+ *
+ * @return a TmfStatisticsData object.
+ */
+ public TmfStatisticsTree getStatisticData() {
+ if (fStatisticsData == null) {
+ fStatisticsData = new TmfStatisticsTree();
+ }
+ return fStatisticsData;
+ }
+
+ /**
+ * Returns a unique ID based on name to be associated with the statistics
+ * tree for this viewer. For a same name, it will always return the same ID.
+ *
+ * @return a unique statistics tree ID.
+ */
+ public String getTreeID() {
+ return getName() + fInstanceNb;
+ }
+
+ @Override
+ public void refresh() {
+ final Control viewerControl = getControl();
+ // Ignore update if disposed
+ if (viewerControl.isDisposed()) {
+ return;
+ }
+
+ viewerControl.getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (!viewerControl.isDisposed()) {
+ fTreeViewer.refresh();
+ }
+ }
+ });
+ }
+
+ /**
+ * Will force a request on the partial event count if one is needed.
+ */
+ public void sendPartialRequestOnNextUpdate() {
+ synchronized (fStatisticsRangeUpdateSyncObj) {
+ fSendRangeRequest = true;
+ }
+ }
+
+ /**
+ * Focus on the statistics tree of the viewer
+ */
+ public void setFocus() {
+ fTreeViewer.getTree().setFocus();
+ }
+
+ /**
+ * Cancels the request if it is not already completed
+ *
+ * @param request
+ * The request to be canceled
+ */
+ protected void cancelOngoingRequest(ITmfDataRequest request) {
+ if (request != null && !request.isCompleted()) {
+ request.cancel();
+ }
+ }
+
+ /**
+ * This method can be overridden to change the representation of the data in
+ * the columns.
+ *
+ * @return an object implementing ITmfBaseColumnDataProvider.
+ */
+ protected ITmfColumnDataProvider getColumnDataProvider() {
+ return new TmfBaseColumnDataProvider();
+ }
+ /**
+ * Initialize the content that will be drawn in this viewer
+ *
+ * @param parent
+ * The parent of the control to create
+ */
+ protected void initContent(Composite parent) {
final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
- parent.setLayout(new FillLayout());
fTreeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
fTreeViewer.setContentProvider(new TmfTreeContentProvider());
}
/**
- * Refreshes this viewer completely with information freshly obtained from
- * this viewer's model.
+ * Initializes the input for the tree viewer.
*/
- public void refresh() {
- fTreeViewer.refresh();
+ protected void initInput() {
+ String treeID = getTreeID();
+ TmfStatisticsTreeNode statisticsTreeNode;
+ if (TmfStatisticsTreeManager.containsTreeRoot(treeID)) {
+ // The statistics root is already present
+ statisticsTreeNode = TmfStatisticsTreeManager.getStatTreeRoot(treeID);
+
+ // Checks if the trace is already in the statistics tree.
+ int numNodeTraces = statisticsTreeNode.getNbChildren();
+
+ ITmfTrace[] traces = TmfTraceManager.getTraceSet(fTrace);
+ int numTraces = traces.length;
+
+ if (numTraces == numNodeTraces) {
+ boolean same = true;
+ /*
+ * Checks if the experiment contains the same traces as when
+ * previously selected.
+ */
+ for (int i = 0; i < numTraces; i++) {
+ String traceName = traces[i].getName();
+ if (!statisticsTreeNode.containsChild(traceName)) {
+ same = false;
+ break;
+ }
+ }
+
+ if (same) {
+ // No need to reload data, all traces are already loaded
+ fTreeViewer.setInput(statisticsTreeNode);
+ return;
+ }
+ // Clears the old content to start over
+ statisticsTreeNode.reset();
+ }
+ } else {
+ // Creates a new tree
+ statisticsTreeNode = TmfStatisticsTreeManager.addStatsTreeRoot(treeID, getStatisticData());
+ }
+
+ // Sets the input to a clean data model
+ fTreeViewer.setInput(statisticsTreeNode);
+ resetUpdateSynchronization();
}
- /*
- * (non-Javadoc)
+ /**
+ * Tells if the viewer is listening to a trace.
*
- * @see org.eclipse.linuxtools.tmf.core.component.TmfComponent#dispose()
+ * @param trace
+ * The trace that the viewer may be listening
+ * @return true if the viewer is listening to the trace, false otherwise
*/
- @Override
- public void dispose() {
- if (fWaitCursor != null) {
- fWaitCursor.dispose();
+ protected boolean isListeningTo(ITmfTrace trace) {
+ if (fProcessAll || trace == fTrace) {
+ return true;
}
- fTreeViewer.getControl().dispose();
- super.dispose();
- // clean the model
- TmfStatisticsTreeRootFactory.removeAll();
+ return false;
}
/**
- * Focus on the statistics tree of the viewer
+ * Called when an trace request has been completed successfully.
+ *
+ * @param global
+ * Tells if the request is a global or time range (partial)
+ * request.
*/
- public void setFocus() {
- fTreeViewer.getTree().setFocus();
+ protected void modelComplete(boolean global) {
+ refresh();
+ waitCursor(false);
+ if (global) {
+ sendPendingUpdate();
+ }
}
/**
- * Sets or clears the input for this viewer.
+ * Called when an trace request has failed or has been cancelled.
*
- * @param input
- * The input of this viewer, or <code>null</code> if none
+ * @param isGlobalRequest
+ * Tells if the request is a global or time range (partial)
+ * request.
*/
- public void setInput(TmfStatisticsTreeNode input) {
- fTreeViewer.setInput(input);
+ protected void modelIncomplete(boolean isGlobalRequest) {
+ if (isGlobalRequest) { // Clean the global statistics
+ /*
+ * No need to reset the global number of events, since the index of
+ * the last requested event is known.
+ */
+ resetUpdateSynchronization();
+ sendPendingUpdate();
+ } else { // Clean the partial statistics
+ resetTimeRangeValue();
+ }
+ refresh();
+ waitCursor(false);
}
/**
- * Returns the quantity of data to retrieve before a refresh of the view is
- * performed
+ * Sends the request to the trace for the whole trace
*
- * @return the quantity of data to retrieve before a refresh of the view is
- * performed.
+ * @param trace
+ * The trace used to send the request
+ * @param timeRange
+ * The range to request to the trace
*/
- public long getInputChangedRefresh() {
- return STATS_INPUT_CHANGED_REFRESH;
+ protected void requestData(final ITmfTrace trace, final TmfTimeRange timeRange) {
+ buildStatisticsTree(trace, timeRange, true);
}
/**
- * This method can be overridden to implement another way to represent the
- * statistics data and to retrieve the information for display.
+ * Sends the time range request from the trace
*
- * @return a TmfStatisticsData object.
+ * @param trace
+ * The trace used to send the request
+ * @param timeRange
+ * The range to request to the trace
*/
- public AbsTmfStatisticsTree getStatisticData() {
- return new TmfBaseStatisticsTree();
+ protected void requestTimeRangeData(final ITmfTrace trace, final TmfTimeRange timeRange) {
+ fRequestedTimerange = timeRange;
+ buildStatisticsTree(trace, timeRange, false);
}
/**
- * Get the input of the viewer
+ * Requests all the data of the trace to the state system which
+ * contains information about the statistics.
*
- * @return an object representing the input of the statistics viewer
+ * Since the viewer may be listening to multiple traces, it may receive
+ * an experiment rather than a single trace. The filtering is done with the
+ * method {@link #isListeningTo(String trace)}.
+ *
+ * @param trace
+ * The trace for which a request must be done
+ * @param timeRange
+ * The time range that will be requested to the state system
+ * @param isGlobal
+ * Tells if the request is for the global event count or the
+ * partial one.
*/
- public Object getInput() {
- return fTreeViewer.getInput();
+ private void buildStatisticsTree(final ITmfTrace trace, TmfTimeRange timeRange, boolean isGlobal) {
+ final TmfStatisticsTreeNode statTree = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
+ final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
+ if (statsData == null) {
+ return;
+ }
+
+ synchronized (statsData) {
+ if (isGlobal) {
+ statTree.resetGlobalValue();
+ } else {
+ statTree.resetTimeRangeValue();
+ }
+
+ 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.
+ */
+ 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();
+
+ /*
+ * 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);
+ }
+ }
}
/**
- * Returns the primary control associated with this viewer.
- *
- * @return the SWT control which displays this viewer's content
+ * Resets the number of events within the time range
*/
- public Control getControl() {
- return fTreeViewer.getControl();
+ protected void resetTimeRangeValue() {
+ TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
+ if (treeModelRoot != null && treeModelRoot.hasChildren()) {
+ treeModelRoot.resetTimeRangeValue();
+ }
}
/**
- * When the experiment is loading the cursor will be different so the user
- * know the processing is not finished yet.
+ * When the trace is loading the cursor will be different so the user
+ * knows that the processing is not finished yet.
*
- * @param waitInd
+ * Calls to this method are stacked.
+ *
+ * @param waitRequested
* Indicates if we need to show the waiting cursor, or the
- * default one
+ * default one.
*/
- public void waitCursor(final boolean waitInd) {
+ protected void waitCursor(final boolean waitRequested) {
if ((fTreeViewer == null) || (fTreeViewer.getTree().isDisposed())) {
return;
}
+ boolean needsUpdate = false;
Display display = fTreeViewer.getControl().getDisplay();
- if (fWaitCursor == null) {
- fWaitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+ if (waitRequested) {
+ fWaitCursorCount++;
+ if (fWaitCursor == null) { // The cursor hasn't been initialized yet
+ fWaitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+ }
+ if (fWaitCursorCount == 1) { // The cursor is not in waiting mode
+ needsUpdate = true;
+ }
+ } else {
+ if (fWaitCursorCount > 0) { // The cursor is in waiting mode
+ fWaitCursorCount--;
+ if (fWaitCursorCount == 0) { // No more reason to wait
+ // Put back the default cursor
+ needsUpdate = true;
+ }
+ }
}
- // Perform the updates on the UI thread
- display.asyncExec(new Runnable() {
- @Override
- public void run() {
- if ((fTreeViewer != null)
- && (!fTreeViewer.getTree().isDisposed())) {
- Cursor cursor = null; /* indicates default */
- if (waitInd) {
- cursor = fWaitCursor;
+ if (needsUpdate) {
+ // Performs the updates on the UI thread
+ display.asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if ((fTreeViewer != null)
+ && (!fTreeViewer.getTree().isDisposed())) {
+ Cursor cursor = null; // indicates default
+ if (waitRequested) {
+ cursor = fWaitCursor;
+ }
+ fTreeViewer.getControl().setCursor(cursor);
}
- fTreeViewer.getControl().setCursor(cursor);
}
- }
- });
+ });
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods reserved for the streaming functionality
+ // ------------------------------------------------------------------------
+
+ /**
+ * Resets update synchronization information
+ */
+ protected void resetUpdateSynchronization() {
+ synchronized (fStatisticsUpdateSyncObj) {
+ fStatisticsUpdateBusy = false;
+ fStatisticsUpdatePending = false;
+ fStatisticsUpdateRange = null;
+ }
}
/**
- * Constructs the ID based on the experiment name and the instance number
+ * Checks if statistics update is ongoing. If it is ongoing, the new time
+ * range is stored as pending
*
- * @param name
- * The name of the trace to show in the view
- * @return a view ID
+ * @param timeRange
+ * - new time range
+ * @return true if statistic update is ongoing else false
*/
- public String getTreeID(String name) {
- return name + fInstanceNb;
+ protected boolean checkUpdateBusy(TmfTimeRange timeRange) {
+ synchronized (fStatisticsUpdateSyncObj) {
+ if (fStatisticsUpdateBusy) {
+ fStatisticsUpdatePending = true;
+ if (fStatisticsUpdateRange == null
+ || timeRange.getEndTime().compareTo(fStatisticsUpdateRange.getEndTime()) > 0) {
+ fStatisticsUpdateRange = timeRange;
+ }
+ return true;
+ }
+ fStatisticsUpdateBusy = true;
+ return false;
+ }
}
/**
- * This method can be overridden to change the representation of the data in
- * the columns.
- *
- * @return an object implementing ITmfBaseColumnDataProvider.
+ * Sends pending request (if any)
*/
- protected ITmfColumnDataProvider getColumnDataProvider() {
- return new TmfBaseColumnDataProvider();
+ protected void sendPendingUpdate() {
+ synchronized (fStatisticsUpdateSyncObj) {
+ fStatisticsUpdateBusy = false;
+ if (fStatisticsUpdatePending) {
+ fStatisticsUpdatePending = false;
+ requestData(fTrace, fStatisticsUpdateRange);
+ fStatisticsUpdateRange = null;
+ }
+ }
}
}