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 * Mathieu Denis <mathieu.denis@polymtl.ca> - Initial API and implementation
11 * Alexandre Montplaisir - Port to ITmfStatistics provider
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
;
16 import java
.util
.List
;
19 import org
.eclipse
.jface
.viewers
.TreeViewer
;
20 import org
.eclipse
.jface
.viewers
.TreeViewerColumn
;
21 import org
.eclipse
.jface
.viewers
.Viewer
;
22 import org
.eclipse
.jface
.viewers
.ViewerComparator
;
23 import org
.eclipse
.linuxtools
.tmf
.core
.component
.TmfComponent
;
24 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfTimestamp
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfDataRequest
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfExperimentRangeUpdatedSignal
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfRangeSynchSignal
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
31 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfStateSystemBuildCompleted
;
32 import org
.eclipse
.linuxtools
.tmf
.core
.statistics
.ITmfStatistics
;
33 import org
.eclipse
.linuxtools
.tmf
.core
.statistics
.TmfStatistics
;
34 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
35 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfExperiment
;
36 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.TmfViewer
;
37 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.AbsTmfStatisticsTree
;
38 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.ITmfColumnDataProvider
;
39 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfBaseColumnData
;
40 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfBaseColumnDataProvider
;
41 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfBaseStatisticsTree
;
42 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfStatisticsTreeNode
;
43 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfStatisticsTreeRootFactory
;
44 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfTreeContentProvider
;
45 import org
.eclipse
.swt
.SWT
;
46 import org
.eclipse
.swt
.events
.SelectionAdapter
;
47 import org
.eclipse
.swt
.events
.SelectionEvent
;
48 import org
.eclipse
.swt
.graphics
.Color
;
49 import org
.eclipse
.swt
.graphics
.Cursor
;
50 import org
.eclipse
.swt
.widgets
.Composite
;
51 import org
.eclipse
.swt
.widgets
.Control
;
52 import org
.eclipse
.swt
.widgets
.Display
;
53 import org
.eclipse
.swt
.widgets
.Event
;
54 import org
.eclipse
.swt
.widgets
.Listener
;
57 * A basic viewer to display statistics in the statistics view.
59 * It is linked to a single ITmfTrace until its disposal.
61 * @author Mathieu Denis
65 public class TmfStatisticsViewer
extends TmfViewer
{
68 * The initial window span (in nanoseconds)
70 public static final long INITIAL_WINDOW_SPAN
= (1L * 100 * 1000 * 1000); // .1sec
73 * Timestamp scale (nanosecond)
75 public static final byte TIME_SCALE
= -9;
78 * Default PAGE_SIZE for background requests.
80 protected static final int PAGE_SIZE
= 50000;
85 protected final Long STATS_INPUT_CHANGED_REFRESH
= 5000L;
88 * The actual tree viewer to display
90 protected TreeViewer fTreeViewer
;
93 * The statistics tree linked to this viewer
95 protected AbsTmfStatisticsTree fStatisticsData
;
98 * Update synchronization parameter (used for streaming): Update busy
101 protected boolean fStatisticsUpdateBusy
= false;
104 * Update synchronization parameter (used for streaming): Update pending
107 protected boolean fStatisticsUpdatePending
= false;
110 * Update synchronization parameter (used for streaming): Pending Update
113 protected TmfTimeRange fStatisticsUpdateRange
= null;
116 * Update synchronization object.
118 protected final Object fStatisticsUpdateSyncObj
= new Object();
121 * Update range synchronization object.
123 protected final Object fStatisticsRangeUpdateSyncObj
= new Object();
126 * The trace that is displayed by this viewer
128 protected ITmfTrace fTrace
;
131 * Stores the requested time range.
133 protected TmfTimeRange fRequestedTimerange
;
136 * Indicates to process all events
138 private boolean fProcessAll
;
141 * View instance counter (for multiple statistics views)
143 private static int fCountInstance
= 0;
146 * Number of this instance. Used as an instance ID.
148 private int fInstanceNb
;
151 * Object to store the cursor while waiting for the experiment to load
153 private Cursor fWaitCursor
= null;
156 * Counts the number of times waitCursor() has been called. It avoids
157 * removing the waiting cursor, since there may be multiple requests running
160 private int fWaitCursorCount
= 0;
163 * Tells to send a time range request when the experiment gets updated.
165 private boolean fSendRangeRequest
= true;
168 * Empty constructor. To be used in conjunction with
169 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
171 public TmfStatisticsViewer() {
176 * Create a basic statistics viewer. To be used in conjunction with
177 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
180 * The parent composite that will hold the viewer
182 * The name that will be assigned to this viewer
184 * The trace that is displayed by this viewer
187 public TmfStatisticsViewer(Composite parent
, String viewerName
, ITmfTrace trace
) {
188 init(parent
, viewerName
, trace
);
192 * Initialize the statistics viewer.
195 * The parent component of the viewer.
197 * The name to give to the viewer.
199 * The trace that will be displayed by the viewer.
201 public void init(Composite parent
, String viewerName
, ITmfTrace trace
) {
202 super.init(parent
, viewerName
);
203 // Increment a counter to make sure the tree ID is unique.
205 fInstanceNb
= fCountInstance
;
208 // The viewer will process all events if he is assigned to the experiment
209 fProcessAll
= (trace
instanceof TmfExperiment
);
218 * @see org.eclipse.linuxtools.tmf.core.component.TmfComponent#dispose()
221 public void dispose() {
223 if (fWaitCursor
!= null) {
224 fWaitCursor
.dispose();
227 // Clean the model for this viewer
228 TmfStatisticsTreeRootFactory
.removeStatTreeRoot(getTreeID());
232 * Handler for the state system build completed signal
235 * The signal that's received
238 public void stateSystemBuildCompleted(final TmfStateSystemBuildCompleted signal
) {
239 if (isListeningTo(signal
.getTrace().getName()) && signal
.getID().equals(TmfStatistics
.STATE_ID
)) {
240 TmfExperiment experiment
= TmfExperiment
.getCurrentExperiment();
241 requestData(experiment
, experiment
.getTimeRange());
242 requestTimeRangeData(experiment
, fRequestedTimerange
);
247 * Handles the signal about new experiment range.
250 * The experiment range updated signal
253 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal
) {
254 TmfExperiment experiment
= signal
.getExperiment();
256 if (!experiment
.equals(TmfExperiment
.getCurrentExperiment())) {
260 synchronized (fStatisticsRangeUpdateSyncObj
) {
261 // Sends the time range request only once from this method.
262 if (fSendRangeRequest
) {
263 fSendRangeRequest
= false;
264 // Calculate the selected time range to request
265 long startTime
= signal
.getRange().getStartTime().normalize(0, TIME_SCALE
).getValue();
266 TmfTimestamp startTS
= new TmfTimestamp(startTime
, TIME_SCALE
);
267 TmfTimestamp endTS
= new TmfTimestamp(startTime
+ INITIAL_WINDOW_SPAN
, TIME_SCALE
);
268 TmfTimeRange timeRange
= new TmfTimeRange(startTS
, endTS
);
270 requestTimeRangeData(experiment
, timeRange
);
273 requestData(experiment
, signal
.getRange());
277 * Handles the time range updated signal. It updates the time range
281 * Contains the information about the new selected time range.
284 public void timeRangeUpdated(TmfRangeSynchSignal signal
) {
285 requestTimeRangeData(TmfExperiment
.getCurrentExperiment(), signal
.getCurrentRange());
289 * Returns the primary control associated with this viewer.
291 * @return the SWT control which displays this viewer's content
294 public Control
getControl() {
295 return fTreeViewer
.getControl();
299 * Get the input of the viewer.
301 * @return an object representing the input of the statistics viewer.
303 public Object
getInput() {
304 return fTreeViewer
.getInput();
308 * Return the size of the request when performing background request.
310 * @return the block size for background request.
312 public int getPageSize() {
317 * Return the number of events to receive before a refresh of the viewer is
320 * @return the input refresh rate
322 public long getRefreshRate() {
323 return STATS_INPUT_CHANGED_REFRESH
;
327 * This method can be overridden to implement another way of representing
328 * the statistics data and to retrieve the information for display.
330 * @return a TmfStatisticsData object.
332 public AbsTmfStatisticsTree
getStatisticData() {
333 if (fStatisticsData
== null) {
334 fStatisticsData
= new TmfBaseStatisticsTree();
336 return fStatisticsData
;
340 * Returns a unique ID based on name to be associated with the statistics
341 * tree for this viewer. For a same name, it will always return the same ID.
343 * @return a unique statistics tree ID.
345 public String
getTreeID() {
346 return getName() + fInstanceNb
;
350 public void refresh() {
351 final Control viewerControl
= getControl();
352 // Ignore update if disposed
353 if (viewerControl
.isDisposed()) {
357 viewerControl
.getDisplay().asyncExec(new Runnable() {
360 if (!viewerControl
.isDisposed()) {
361 fTreeViewer
.refresh();
368 * Will force a request on the partial event count if one is needed.
370 public void sendPartialRequestOnNextUpdate() {
371 synchronized (fStatisticsRangeUpdateSyncObj
) {
372 fSendRangeRequest
= true;
377 * Focus on the statistics tree of the viewer
379 public void setFocus() {
380 fTreeViewer
.getTree().setFocus();
384 * Cancels the request if it is not already completed
387 * The request to be canceled
389 protected void cancelOngoingRequest(ITmfDataRequest request
) {
390 if (request
!= null && !request
.isCompleted()) {
396 * This method can be overridden to change the representation of the data in
399 * @return an object implementing ITmfBaseColumnDataProvider.
401 protected ITmfColumnDataProvider
getColumnDataProvider() {
402 return new TmfBaseColumnDataProvider();
406 * Initialize the content that will be drawn in this viewer
409 * The parent of the control to create
411 protected void initContent(Composite parent
) {
412 final List
<TmfBaseColumnData
> columnDataList
= getColumnDataProvider().getColumnData();
414 fTreeViewer
= new TreeViewer(parent
, SWT
.BORDER
| SWT
.H_SCROLL
| SWT
.V_SCROLL
);
415 fTreeViewer
.setContentProvider(new TmfTreeContentProvider());
416 fTreeViewer
.getTree().setHeaderVisible(true);
417 fTreeViewer
.setUseHashlookup(true);
419 // Creates the columns defined by the column data provider
420 for (final TmfBaseColumnData columnData
: columnDataList
) {
421 final TreeViewerColumn treeColumn
= new TreeViewerColumn(fTreeViewer
, columnData
.getAlignment());
422 treeColumn
.getColumn().setText(columnData
.getHeader());
423 treeColumn
.getColumn().setWidth(columnData
.getWidth());
424 treeColumn
.getColumn().setToolTipText(columnData
.getTooltip());
426 if (columnData
.getComparator() != null) { // A comparator is defined.
427 // Adds a listener on the columns header for sorting purpose.
428 treeColumn
.getColumn().addSelectionListener(new SelectionAdapter() {
430 private ViewerComparator reverseComparator
;
433 public void widgetSelected(SelectionEvent e
) {
434 // Initializes the reverse comparator once.
435 if (reverseComparator
== null) {
436 reverseComparator
= new ViewerComparator() {
438 public int compare(Viewer viewer
, Object e1
, Object e2
) {
439 return -1 * columnData
.getComparator().compare(viewer
, e1
, e2
);
444 if (fTreeViewer
.getTree().getSortDirection() == SWT
.UP
445 || fTreeViewer
.getTree().getSortColumn() != treeColumn
.getColumn()) {
447 * Puts the descendant order if the old order was
448 * up or if the selected column has changed.
450 fTreeViewer
.setComparator(columnData
.getComparator());
451 fTreeViewer
.getTree().setSortDirection(SWT
.DOWN
);
454 * Puts the ascendant ordering if the selected
455 * column hasn't changed.
457 fTreeViewer
.setComparator(reverseComparator
);
458 fTreeViewer
.getTree().setSortDirection(SWT
.UP
);
460 fTreeViewer
.getTree().setSortColumn(treeColumn
.getColumn());
464 treeColumn
.setLabelProvider(columnData
.getLabelProvider());
467 // Handler that will draw the bar charts.
468 fTreeViewer
.getTree().addListener(SWT
.EraseItem
, new Listener() {
470 public void handleEvent(Event event
) {
471 if (columnDataList
.get(event
.index
).getPercentageProvider() != null) {
472 TmfStatisticsTreeNode node
= (TmfStatisticsTreeNode
) event
.item
.getData();
474 double percentage
= columnDataList
.get(event
.index
).getPercentageProvider().getPercentage(node
);
475 if (percentage
== 0) { // No bar to draw
479 if ((event
.detail
& SWT
.SELECTED
) > 0) { // The item is selected.
480 // Draws our own background to avoid overwritten the bar.
481 event
.gc
.fillRectangle(event
.x
, event
.y
, event
.width
, event
.height
);
482 event
.detail
&= ~SWT
.SELECTED
;
485 int barWidth
= (int) ((fTreeViewer
.getTree().getColumn(event
.index
).getWidth() - 8) * percentage
);
486 int oldAlpha
= event
.gc
.getAlpha();
487 Color oldForeground
= event
.gc
.getForeground();
488 Color oldBackground
= event
.gc
.getBackground();
490 * Draws a transparent gradient rectangle from the color of
491 * foreground and background.
493 event
.gc
.setAlpha(64);
494 event
.gc
.setForeground(event
.item
.getDisplay().getSystemColor(SWT
.COLOR_BLUE
));
495 event
.gc
.setBackground(event
.item
.getDisplay().getSystemColor(SWT
.COLOR_LIST_BACKGROUND
));
496 event
.gc
.fillGradientRectangle(event
.x
, event
.y
, barWidth
, event
.height
, true);
497 event
.gc
.drawRectangle(event
.x
, event
.y
, barWidth
, event
.height
);
498 // Restores old values
499 event
.gc
.setForeground(oldForeground
);
500 event
.gc
.setBackground(oldBackground
);
501 event
.gc
.setAlpha(oldAlpha
);
502 event
.detail
&= ~SWT
.BACKGROUND
;
507 // Initializes the comparator parameters
508 fTreeViewer
.setComparator(columnDataList
.get(0).getComparator());
509 fTreeViewer
.getTree().setSortColumn(fTreeViewer
.getTree().getColumn(0));
510 fTreeViewer
.getTree().setSortDirection(SWT
.DOWN
);
514 * Initializes the input for the tree viewer.
517 * The input of this viewer, or <code>null</code> if none
519 protected void initInput() {
520 String treeID
= getTreeID();
521 TmfStatisticsTreeNode experimentTreeNode
;
522 if (TmfStatisticsTreeRootFactory
.containsTreeRoot(treeID
)) {
523 // The experiment root is already present
524 experimentTreeNode
= TmfStatisticsTreeRootFactory
.getStatTreeRoot(treeID
);
526 // Checks if the trace is already in the statistics tree.
527 int numNodeTraces
= experimentTreeNode
.getNbChildren();
530 ITmfTrace
[] trace
= { fTrace
};
531 // For experiment, gets all the traces within it
532 if (fTrace
instanceof TmfExperiment
) {
533 TmfExperiment experiment
= (TmfExperiment
) fTrace
;
534 numTraces
= experiment
.getTraces().length
;
535 trace
= experiment
.getTraces();
538 if (numTraces
== numNodeTraces
) {
541 * Checks if the experiment contains the same traces as when
542 * previously selected.
544 for (int i
= 0; i
< numTraces
; i
++) {
545 String traceName
= trace
[i
].getName();
546 if (!experimentTreeNode
.containsChild(traceName
)) {
553 // No need to reload data, all traces are already loaded
554 fTreeViewer
.setInput(experimentTreeNode
);
557 // Clears the old content to start over
558 experimentTreeNode
.reset();
561 // Creates a new tree
562 experimentTreeNode
= TmfStatisticsTreeRootFactory
.addStatsTreeRoot(treeID
, getStatisticData());
565 // Sets the input to a clean data model
566 fTreeViewer
.setInput(experimentTreeNode
);
567 resetUpdateSynchronization();
571 * Tells if the viewer is listening to a trace from the selected experiment.
574 * The trace that the viewer may be listening
575 * @return true if the viewer is listening to the trace, false otherwise
577 protected boolean isListeningTo(String traceName
) {
578 if (fProcessAll
|| traceName
.equals(fTrace
.getName())) {
585 * Called when an experiment request has been completed successfully.
588 * Tells if the request is a global or time range (partial)
591 protected void modelComplete(boolean global
) {
600 * Called when an experiment request has failed or has been cancelled.
602 * @param isGlobalRequest
603 * Tells if the request is a global or time range (partial)
606 protected void modelIncomplete(boolean isGlobalRequest
) {
607 if (isGlobalRequest
) { // Clean the global statistics
609 * No need to reset the global number of events, since the index of
610 * the last requested event is known.
612 resetUpdateSynchronization();
614 } else { // Clean the partial statistics
615 resetTimeRangeValue();
622 * Sends the request to the experiment for the whole trace
625 * The experiment used to send the request
627 * The range to request to the experiment
629 protected void requestData(final TmfExperiment experiment
, final TmfTimeRange timeRange
) {
630 final Thread thread
= new Thread("Statistics view build") { //$NON-NLS-1$
633 buildStatisticsTree(experiment
, timeRange
, true);
640 * Sends the time range request from the experiment
643 * The experiment used to send the request
645 * The range to request to the experiment
647 protected void requestTimeRangeData(final TmfExperiment experiment
, final TmfTimeRange timeRange
) {
648 fRequestedTimerange
= timeRange
;
650 final Thread thread
= new Thread("Statistics view build") { //$NON-NLS-1$
653 buildStatisticsTree(experiment
, timeRange
, false);
660 * Requests all the data of the experiment to the state system which
661 * contains information about the statistics.
663 * Since the viewer may be listening to multiple traces, it have to receive
664 * the experiment rather than a single trace. The filtering is done with the
665 * method {@link #isListeningTo(String trace)}.
668 * The experiment for which a request must be done
670 * The time range that will be requested to the state system
672 * Tells if the request is for the global event count or the
675 private void buildStatisticsTree(final TmfExperiment experiment
, TmfTimeRange timeRange
, boolean isGlobal
) {
676 final TmfStatisticsTreeNode statTree
= TmfStatisticsTreeRootFactory
.getStatTreeRoot(getTreeID());
677 final AbsTmfStatisticsTree statsData
= TmfStatisticsTreeRootFactory
.getStatTree(getTreeID());
678 if (statsData
== null) {
682 synchronized (statsData
) {
684 statTree
.resetGlobalValue();
686 statTree
.resetTimeRangeValue();
690 * Checks each trace in the experiment, since the viewer may be
691 * listening to multiple traces.
693 for (final ITmfTrace trace
: experiment
.getTraces()) {
694 if (!isListeningTo(trace
.getName())) {
698 /* Retrieves the statistics object */
699 final ITmfStatistics stats
= trace
.getStatistics();
702 * The state system is not accessible yet for this trace.
708 updateValues(statsData
, trace
, timeRange
, isGlobal
);
710 modelComplete(isGlobal
);
716 * Update the statistics values. It can be extended by subclasses if they
717 * want to show something other than the base information in their viewer.
718 * They can decide to show the base information too, by calling
719 * super.updateValues() or not.
722 * The statistics tree we are updating
724 * The trace related to these statistics
726 * The time range for which we are updating. For updates to the
727 * global data this should be the whole (available) time range of
730 * Are we updating the Global data (for the complete time range
731 * of the trace), or the selected time range data?
733 protected void updateValues(AbsTmfStatisticsTree statsData
, ITmfTrace trace
,
734 TmfTimeRange timeRange
, boolean isGlobal
) {
735 ITmfStatistics stats
= trace
.getStatistics();
738 * "Global", "partial", "total", etc., it's all very confusing...
740 * The base view shows the total count for the trace and for
741 * each even types, organized in columns like this:
743 * | Global | Time range |
744 * trace name | A | B |
746 * <event 1> | C | D |
747 * <event 2> | ... | ... |
750 * Here, we called the cells like this:
753 * C : GlobalTypeCount(s)
754 * D : TimeRangeTypeCount(s)
757 /* The generic statistics are stored in nanoseconds, so we must make
758 * sure the time range is scaled correctly. */
759 ITmfTimestamp start
= timeRange
.getStartTime().normalize(0, TIME_SCALE
);
760 ITmfTimestamp end
= timeRange
.getEndTime().normalize(0, TIME_SCALE
);
761 String name
= trace
.getName();
764 * Fill in the Total row (cell A or B, depending if isGlobal)
765 * (we can still use .getEventsInRange(), even if it's global,
766 * start and end will cover the whole trace)
768 long globalTotal
= stats
.getEventsInRange(start
, end
);
769 statsData
.setTotal(name
, isGlobal
, globalTotal
);
771 /* Fill in an the event counts (either cells C or D) */
772 Map
<String
, Long
> map
= stats
.getEventTypesInRange(start
, end
);
773 for (Map
.Entry
<String
, Long
> entry
: map
.entrySet()) {
774 statsData
.setTypeCount(name
, entry
.getKey(), isGlobal
, entry
.getValue());
779 * Resets the number of events within the time range
781 protected void resetTimeRangeValue() {
782 TmfStatisticsTreeNode treeModelRoot
= TmfStatisticsTreeRootFactory
.getStatTreeRoot(getTreeID());
783 if (treeModelRoot
!= null && treeModelRoot
.hasChildren()) {
784 treeModelRoot
.resetTimeRangeValue();
789 * When the experiment is loading the cursor will be different so the user
790 * knows that the processing is not finished yet.
792 * Calls to this method are stacked.
794 * @param waitRequested
795 * Indicates if we need to show the waiting cursor, or the
798 protected void waitCursor(final boolean waitRequested
) {
799 if ((fTreeViewer
== null) || (fTreeViewer
.getTree().isDisposed())) {
803 boolean needsUpdate
= false;
804 Display display
= fTreeViewer
.getControl().getDisplay();
807 if (fWaitCursor
== null) { // The cursor hasn't been initialized yet
808 fWaitCursor
= new Cursor(display
, SWT
.CURSOR_WAIT
);
810 if (fWaitCursorCount
== 1) { // The cursor is not in waiting mode
814 if (fWaitCursorCount
> 0) { // The cursor is in waiting mode
816 if (fWaitCursorCount
== 0) { // No more reason to wait
817 // Put back the default cursor
824 // Performs the updates on the UI thread
825 display
.asyncExec(new Runnable() {
828 if ((fTreeViewer
!= null)
829 && (!fTreeViewer
.getTree().isDisposed())) {
830 Cursor cursor
= null; // indicates default
832 cursor
= fWaitCursor
;
834 fTreeViewer
.getControl().setCursor(cursor
);
841 // ------------------------------------------------------------------------
842 // Methods reserved for the streaming functionality
843 // ------------------------------------------------------------------------
846 * Resets update synchronization information
848 protected void resetUpdateSynchronization() {
849 synchronized (fStatisticsUpdateSyncObj
) {
850 fStatisticsUpdateBusy
= false;
851 fStatisticsUpdatePending
= false;
852 fStatisticsUpdateRange
= null;
857 * Checks if statistics update is ongoing. If it is ongoing, the new time
858 * range is stored as pending
862 * @return true if statistic update is ongoing else false
864 protected boolean checkUpdateBusy(TmfTimeRange timeRange
) {
865 synchronized (fStatisticsUpdateSyncObj
) {
866 if (fStatisticsUpdateBusy
) {
867 fStatisticsUpdatePending
= true;
868 if (fStatisticsUpdateRange
== null
869 || timeRange
.getEndTime().compareTo(fStatisticsUpdateRange
.getEndTime()) > 0) {
870 fStatisticsUpdateRange
= timeRange
;
874 fStatisticsUpdateBusy
= true;
880 * Sends pending request (if any)
882 protected void sendPendingUpdate() {
883 synchronized (fStatisticsUpdateSyncObj
) {
884 fStatisticsUpdateBusy
= false;
885 if (fStatisticsUpdatePending
) {
886 fStatisticsUpdatePending
= false;
887 requestData(TmfExperiment
.getCurrentExperiment(), fStatisticsUpdateRange
);
888 fStatisticsUpdateRange
= null;