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
.ITmfColumnDataProvider
;
38 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfBaseColumnData
;
39 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfBaseColumnDataProvider
;
40 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfStatisticsTree
;
41 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfStatisticsTreeManager
;
42 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfStatisticsTreeNode
;
43 import org
.eclipse
.linuxtools
.tmf
.ui
.viewers
.statistics
.model
.TmfTreeContentProvider
;
44 import org
.eclipse
.swt
.SWT
;
45 import org
.eclipse
.swt
.events
.SelectionAdapter
;
46 import org
.eclipse
.swt
.events
.SelectionEvent
;
47 import org
.eclipse
.swt
.graphics
.Color
;
48 import org
.eclipse
.swt
.graphics
.Cursor
;
49 import org
.eclipse
.swt
.widgets
.Composite
;
50 import org
.eclipse
.swt
.widgets
.Control
;
51 import org
.eclipse
.swt
.widgets
.Display
;
52 import org
.eclipse
.swt
.widgets
.Event
;
53 import org
.eclipse
.swt
.widgets
.Listener
;
56 * A basic viewer to display statistics in the statistics view.
58 * It is linked to a single ITmfTrace until its disposal.
60 * @author Mathieu Denis
64 public class TmfStatisticsViewer
extends TmfViewer
{
67 * The initial window span (in nanoseconds)
69 public static final long INITIAL_WINDOW_SPAN
= (1L * 100 * 1000 * 1000); // .1sec
72 * Timestamp scale (nanosecond)
74 public static final byte TIME_SCALE
= -9;
77 * Default PAGE_SIZE for background requests.
79 protected static final int PAGE_SIZE
= 50000;
84 protected final Long STATS_INPUT_CHANGED_REFRESH
= 5000L;
87 * The actual tree viewer to display
89 protected TreeViewer fTreeViewer
;
92 * The statistics tree linked to this viewer
94 protected TmfStatisticsTree fStatisticsData
;
97 * Update synchronization parameter (used for streaming): Update busy
100 protected boolean fStatisticsUpdateBusy
= false;
103 * Update synchronization parameter (used for streaming): Update pending
106 protected boolean fStatisticsUpdatePending
= false;
109 * Update synchronization parameter (used for streaming): Pending Update
112 protected TmfTimeRange fStatisticsUpdateRange
= null;
115 * Update synchronization object.
117 protected final Object fStatisticsUpdateSyncObj
= new Object();
120 * Update range synchronization object.
122 protected final Object fStatisticsRangeUpdateSyncObj
= new Object();
125 * The trace that is displayed by this viewer
127 protected ITmfTrace fTrace
;
130 * Stores the requested time range.
132 protected TmfTimeRange fRequestedTimerange
;
135 * Indicates to process all events
137 private boolean fProcessAll
;
140 * View instance counter (for multiple statistics views)
142 private static int fCountInstance
= 0;
145 * Number of this instance. Used as an instance ID.
147 private int fInstanceNb
;
150 * Object to store the cursor while waiting for the experiment to load
152 private Cursor fWaitCursor
= null;
155 * Counts the number of times waitCursor() has been called. It avoids
156 * removing the waiting cursor, since there may be multiple requests running
159 private int fWaitCursorCount
= 0;
162 * Tells to send a time range request when the experiment gets updated.
164 private boolean fSendRangeRequest
= true;
167 * Empty constructor. To be used in conjunction with
168 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
170 public TmfStatisticsViewer() {
175 * Create a basic statistics viewer. To be used in conjunction with
176 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
179 * The parent composite that will hold the viewer
181 * The name that will be assigned to this viewer
183 * The trace that is displayed by this viewer
186 public TmfStatisticsViewer(Composite parent
, String viewerName
, ITmfTrace trace
) {
187 init(parent
, viewerName
, trace
);
191 * Initialize the statistics viewer.
194 * The parent component of the viewer.
196 * The name to give to the viewer.
198 * The trace that will be displayed by the viewer.
200 public void init(Composite parent
, String viewerName
, ITmfTrace trace
) {
201 super.init(parent
, viewerName
);
202 // Increment a counter to make sure the tree ID is unique.
204 fInstanceNb
= fCountInstance
;
207 // The viewer will process all events if he is assigned to the experiment
208 fProcessAll
= (trace
instanceof TmfExperiment
);
217 * @see org.eclipse.linuxtools.tmf.core.component.TmfComponent#dispose()
220 public void dispose() {
222 if (fWaitCursor
!= null) {
223 fWaitCursor
.dispose();
226 // Clean the model for this viewer
227 TmfStatisticsTreeManager
.removeStatTreeRoot(getTreeID());
231 * Handler for the state system build completed signal
234 * The signal that's received
237 public void stateSystemBuildCompleted(final TmfStateSystemBuildCompleted signal
) {
238 if (isListeningTo(signal
.getTrace().getName()) && signal
.getID().equals(TmfStatistics
.STATE_ID
)) {
239 TmfExperiment experiment
= TmfExperiment
.getCurrentExperiment();
240 requestData(experiment
, experiment
.getTimeRange());
241 requestTimeRangeData(experiment
, fRequestedTimerange
);
246 * Handles the signal about new experiment range.
249 * The experiment range updated signal
252 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal
) {
253 TmfExperiment experiment
= signal
.getExperiment();
255 if (!experiment
.equals(TmfExperiment
.getCurrentExperiment())) {
259 synchronized (fStatisticsRangeUpdateSyncObj
) {
260 // Sends the time range request only once from this method.
261 if (fSendRangeRequest
) {
262 fSendRangeRequest
= false;
263 // Calculate the selected time range to request
264 long startTime
= signal
.getRange().getStartTime().normalize(0, TIME_SCALE
).getValue();
265 TmfTimestamp startTS
= new TmfTimestamp(startTime
, TIME_SCALE
);
266 TmfTimestamp endTS
= new TmfTimestamp(startTime
+ INITIAL_WINDOW_SPAN
, TIME_SCALE
);
267 TmfTimeRange timeRange
= new TmfTimeRange(startTS
, endTS
);
269 requestTimeRangeData(experiment
, timeRange
);
272 requestData(experiment
, signal
.getRange());
276 * Handles the time range updated signal. It updates the time range
280 * Contains the information about the new selected time range.
283 public void timeRangeUpdated(TmfRangeSynchSignal signal
) {
284 requestTimeRangeData(TmfExperiment
.getCurrentExperiment(), signal
.getCurrentRange());
288 * Returns the primary control associated with this viewer.
290 * @return the SWT control which displays this viewer's content
293 public Control
getControl() {
294 return fTreeViewer
.getControl();
298 * Get the input of the viewer.
300 * @return an object representing the input of the statistics viewer.
302 public Object
getInput() {
303 return fTreeViewer
.getInput();
307 * Return the size of the request when performing background request.
309 * @return the block size for background request.
311 public int getPageSize() {
316 * Return the number of events to receive before a refresh of the viewer is
319 * @return the input refresh rate
321 public long getRefreshRate() {
322 return STATS_INPUT_CHANGED_REFRESH
;
326 * This method can be overridden to implement another way of representing
327 * the statistics data and to retrieve the information for display.
329 * @return a TmfStatisticsData object.
331 public TmfStatisticsTree
getStatisticData() {
332 if (fStatisticsData
== null) {
333 fStatisticsData
= new TmfStatisticsTree();
335 return fStatisticsData
;
339 * Returns a unique ID based on name to be associated with the statistics
340 * tree for this viewer. For a same name, it will always return the same ID.
342 * @return a unique statistics tree ID.
344 public String
getTreeID() {
345 return getName() + fInstanceNb
;
349 public void refresh() {
350 final Control viewerControl
= getControl();
351 // Ignore update if disposed
352 if (viewerControl
.isDisposed()) {
356 viewerControl
.getDisplay().asyncExec(new Runnable() {
359 if (!viewerControl
.isDisposed()) {
360 fTreeViewer
.refresh();
367 * Will force a request on the partial event count if one is needed.
369 public void sendPartialRequestOnNextUpdate() {
370 synchronized (fStatisticsRangeUpdateSyncObj
) {
371 fSendRangeRequest
= true;
376 * Focus on the statistics tree of the viewer
378 public void setFocus() {
379 fTreeViewer
.getTree().setFocus();
383 * Cancels the request if it is not already completed
386 * The request to be canceled
388 protected void cancelOngoingRequest(ITmfDataRequest request
) {
389 if (request
!= null && !request
.isCompleted()) {
395 * This method can be overridden to change the representation of the data in
398 * @return an object implementing ITmfBaseColumnDataProvider.
400 protected ITmfColumnDataProvider
getColumnDataProvider() {
401 return new TmfBaseColumnDataProvider();
405 * Initialize the content that will be drawn in this viewer
408 * The parent of the control to create
410 protected void initContent(Composite parent
) {
411 final List
<TmfBaseColumnData
> columnDataList
= getColumnDataProvider().getColumnData();
413 fTreeViewer
= new TreeViewer(parent
, SWT
.BORDER
| SWT
.H_SCROLL
| SWT
.V_SCROLL
);
414 fTreeViewer
.setContentProvider(new TmfTreeContentProvider());
415 fTreeViewer
.getTree().setHeaderVisible(true);
416 fTreeViewer
.setUseHashlookup(true);
418 // Creates the columns defined by the column data provider
419 for (final TmfBaseColumnData columnData
: columnDataList
) {
420 final TreeViewerColumn treeColumn
= new TreeViewerColumn(fTreeViewer
, columnData
.getAlignment());
421 treeColumn
.getColumn().setText(columnData
.getHeader());
422 treeColumn
.getColumn().setWidth(columnData
.getWidth());
423 treeColumn
.getColumn().setToolTipText(columnData
.getTooltip());
425 if (columnData
.getComparator() != null) { // A comparator is defined.
426 // Adds a listener on the columns header for sorting purpose.
427 treeColumn
.getColumn().addSelectionListener(new SelectionAdapter() {
429 private ViewerComparator reverseComparator
;
432 public void widgetSelected(SelectionEvent e
) {
433 // Initializes the reverse comparator once.
434 if (reverseComparator
== null) {
435 reverseComparator
= new ViewerComparator() {
437 public int compare(Viewer viewer
, Object e1
, Object e2
) {
438 return -1 * columnData
.getComparator().compare(viewer
, e1
, e2
);
443 if (fTreeViewer
.getTree().getSortDirection() == SWT
.UP
444 || fTreeViewer
.getTree().getSortColumn() != treeColumn
.getColumn()) {
446 * Puts the descendant order if the old order was
447 * up or if the selected column has changed.
449 fTreeViewer
.setComparator(columnData
.getComparator());
450 fTreeViewer
.getTree().setSortDirection(SWT
.DOWN
);
453 * Puts the ascendant ordering if the selected
454 * column hasn't changed.
456 fTreeViewer
.setComparator(reverseComparator
);
457 fTreeViewer
.getTree().setSortDirection(SWT
.UP
);
459 fTreeViewer
.getTree().setSortColumn(treeColumn
.getColumn());
463 treeColumn
.setLabelProvider(columnData
.getLabelProvider());
466 // Handler that will draw the bar charts.
467 fTreeViewer
.getTree().addListener(SWT
.EraseItem
, new Listener() {
469 public void handleEvent(Event event
) {
470 if (columnDataList
.get(event
.index
).getPercentageProvider() != null) {
471 TmfStatisticsTreeNode node
= (TmfStatisticsTreeNode
) event
.item
.getData();
473 double percentage
= columnDataList
.get(event
.index
).getPercentageProvider().getPercentage(node
);
474 if (percentage
== 0) { // No bar to draw
478 if ((event
.detail
& SWT
.SELECTED
) > 0) { // The item is selected.
479 // Draws our own background to avoid overwritten the bar.
480 event
.gc
.fillRectangle(event
.x
, event
.y
, event
.width
, event
.height
);
481 event
.detail
&= ~SWT
.SELECTED
;
484 int barWidth
= (int) ((fTreeViewer
.getTree().getColumn(event
.index
).getWidth() - 8) * percentage
);
485 int oldAlpha
= event
.gc
.getAlpha();
486 Color oldForeground
= event
.gc
.getForeground();
487 Color oldBackground
= event
.gc
.getBackground();
489 * Draws a transparent gradient rectangle from the color of
490 * foreground and background.
492 event
.gc
.setAlpha(64);
493 event
.gc
.setForeground(event
.item
.getDisplay().getSystemColor(SWT
.COLOR_BLUE
));
494 event
.gc
.setBackground(event
.item
.getDisplay().getSystemColor(SWT
.COLOR_LIST_BACKGROUND
));
495 event
.gc
.fillGradientRectangle(event
.x
, event
.y
, barWidth
, event
.height
, true);
496 event
.gc
.drawRectangle(event
.x
, event
.y
, barWidth
, event
.height
);
497 // Restores old values
498 event
.gc
.setForeground(oldForeground
);
499 event
.gc
.setBackground(oldBackground
);
500 event
.gc
.setAlpha(oldAlpha
);
501 event
.detail
&= ~SWT
.BACKGROUND
;
506 // Initializes the comparator parameters
507 fTreeViewer
.setComparator(columnDataList
.get(0).getComparator());
508 fTreeViewer
.getTree().setSortColumn(fTreeViewer
.getTree().getColumn(0));
509 fTreeViewer
.getTree().setSortDirection(SWT
.DOWN
);
513 * Initializes the input for the tree viewer.
516 * The input of this viewer, or <code>null</code> if none
518 protected void initInput() {
519 String treeID
= getTreeID();
520 TmfStatisticsTreeNode experimentTreeNode
;
521 if (TmfStatisticsTreeManager
.containsTreeRoot(treeID
)) {
522 // The experiment root is already present
523 experimentTreeNode
= TmfStatisticsTreeManager
.getStatTreeRoot(treeID
);
525 // Checks if the trace is already in the statistics tree.
526 int numNodeTraces
= experimentTreeNode
.getNbChildren();
529 ITmfTrace
[] trace
= { fTrace
};
530 // For experiment, gets all the traces within it
531 if (fTrace
instanceof TmfExperiment
) {
532 TmfExperiment experiment
= (TmfExperiment
) fTrace
;
533 numTraces
= experiment
.getTraces().length
;
534 trace
= experiment
.getTraces();
537 if (numTraces
== numNodeTraces
) {
540 * Checks if the experiment contains the same traces as when
541 * previously selected.
543 for (int i
= 0; i
< numTraces
; i
++) {
544 String traceName
= trace
[i
].getName();
545 if (!experimentTreeNode
.containsChild(traceName
)) {
552 // No need to reload data, all traces are already loaded
553 fTreeViewer
.setInput(experimentTreeNode
);
556 // Clears the old content to start over
557 experimentTreeNode
.reset();
560 // Creates a new tree
561 experimentTreeNode
= TmfStatisticsTreeManager
.addStatsTreeRoot(treeID
, getStatisticData());
564 // Sets the input to a clean data model
565 fTreeViewer
.setInput(experimentTreeNode
);
566 resetUpdateSynchronization();
570 * Tells if the viewer is listening to a trace from the selected experiment.
573 * The trace that the viewer may be listening
574 * @return true if the viewer is listening to the trace, false otherwise
576 protected boolean isListeningTo(String traceName
) {
577 if (fProcessAll
|| traceName
.equals(fTrace
.getName())) {
584 * Called when an experiment request has been completed successfully.
587 * Tells if the request is a global or time range (partial)
590 protected void modelComplete(boolean global
) {
599 * Called when an experiment request has failed or has been cancelled.
601 * @param isGlobalRequest
602 * Tells if the request is a global or time range (partial)
605 protected void modelIncomplete(boolean isGlobalRequest
) {
606 if (isGlobalRequest
) { // Clean the global statistics
608 * No need to reset the global number of events, since the index of
609 * the last requested event is known.
611 resetUpdateSynchronization();
613 } else { // Clean the partial statistics
614 resetTimeRangeValue();
621 * Sends the request to the experiment for the whole trace
624 * The experiment used to send the request
626 * The range to request to the experiment
628 protected void requestData(final TmfExperiment experiment
, final TmfTimeRange timeRange
) {
629 final Thread thread
= new Thread("Statistics view build") { //$NON-NLS-1$
632 buildStatisticsTree(experiment
, timeRange
, true);
639 * Sends the time range request from the experiment
642 * The experiment used to send the request
644 * The range to request to the experiment
646 protected void requestTimeRangeData(final TmfExperiment experiment
, final TmfTimeRange timeRange
) {
647 fRequestedTimerange
= timeRange
;
649 final Thread thread
= new Thread("Statistics view build") { //$NON-NLS-1$
652 buildStatisticsTree(experiment
, timeRange
, false);
659 * Requests all the data of the experiment to the state system which
660 * contains information about the statistics.
662 * Since the viewer may be listening to multiple traces, it have to receive
663 * the experiment rather than a single trace. The filtering is done with the
664 * method {@link #isListeningTo(String trace)}.
667 * The experiment for which a request must be done
669 * The time range that will be requested to the state system
671 * Tells if the request is for the global event count or the
674 private void buildStatisticsTree(final TmfExperiment experiment
, TmfTimeRange timeRange
, boolean isGlobal
) {
675 final TmfStatisticsTreeNode statTree
= TmfStatisticsTreeManager
.getStatTreeRoot(getTreeID());
676 final TmfStatisticsTree statsData
= TmfStatisticsTreeManager
.getStatTree(getTreeID());
677 if (statsData
== null) {
681 synchronized (statsData
) {
683 statTree
.resetGlobalValue();
685 statTree
.resetTimeRangeValue();
689 * Checks each trace in the experiment, since the viewer may be
690 * listening to multiple traces.
692 for (final ITmfTrace trace
: experiment
.getTraces()) {
693 if (!isListeningTo(trace
.getName())) {
697 /* Retrieves the statistics object */
698 final ITmfStatistics stats
= trace
.getStatistics();
701 * The state system is not accessible yet for this trace.
707 updateValues(statsData
, trace
, timeRange
, isGlobal
);
709 modelComplete(isGlobal
);
715 * Update the statistics values. It can be extended by subclasses if they
716 * want to show something other than the base information in their viewer.
717 * They can decide to show the base information too, by calling
718 * super.updateValues() or not.
721 * The statistics tree we are updating
723 * The trace related to these statistics
725 * The time range for which we are updating. For updates to the
726 * global data this should be the whole (available) time range of
729 * Are we updating the Global data (for the complete time range
730 * of the trace), or the selected time range data?
732 protected void updateValues(TmfStatisticsTree statsData
, ITmfTrace trace
,
733 TmfTimeRange timeRange
, boolean isGlobal
) {
734 ITmfStatistics stats
= trace
.getStatistics();
737 * "Global", "partial", "total", etc., it's all very confusing...
739 * The base view shows the total count for the trace and for
740 * each even types, organized in columns like this:
742 * | Global | Time range |
743 * trace name | A | B |
745 * <event 1> | C | D |
746 * <event 2> | ... | ... |
749 * Here, we called the cells like this:
752 * C : GlobalTypeCount(s)
753 * D : TimeRangeTypeCount(s)
756 /* The generic statistics are stored in nanoseconds, so we must make
757 * sure the time range is scaled correctly. */
758 ITmfTimestamp start
= timeRange
.getStartTime().normalize(0, TIME_SCALE
);
759 ITmfTimestamp end
= timeRange
.getEndTime().normalize(0, TIME_SCALE
);
760 String name
= trace
.getName();
763 * Fill in the Total row (cell A or B, depending if isGlobal)
764 * (we can still use .getEventsInRange(), even if it's global,
765 * start and end will cover the whole trace)
767 long globalTotal
= stats
.getEventsInRange(start
, end
);
768 statsData
.setTotal(name
, isGlobal
, globalTotal
);
770 /* Fill in an the event counts (either cells C or D) */
771 Map
<String
, Long
> map
= stats
.getEventTypesInRange(start
, end
);
772 for (Map
.Entry
<String
, Long
> entry
: map
.entrySet()) {
773 statsData
.setTypeCount(name
, entry
.getKey(), isGlobal
, entry
.getValue());
778 * Resets the number of events within the time range
780 protected void resetTimeRangeValue() {
781 TmfStatisticsTreeNode treeModelRoot
= TmfStatisticsTreeManager
.getStatTreeRoot(getTreeID());
782 if (treeModelRoot
!= null && treeModelRoot
.hasChildren()) {
783 treeModelRoot
.resetTimeRangeValue();
788 * When the experiment is loading the cursor will be different so the user
789 * knows that the processing is not finished yet.
791 * Calls to this method are stacked.
793 * @param waitRequested
794 * Indicates if we need to show the waiting cursor, or the
797 protected void waitCursor(final boolean waitRequested
) {
798 if ((fTreeViewer
== null) || (fTreeViewer
.getTree().isDisposed())) {
802 boolean needsUpdate
= false;
803 Display display
= fTreeViewer
.getControl().getDisplay();
806 if (fWaitCursor
== null) { // The cursor hasn't been initialized yet
807 fWaitCursor
= new Cursor(display
, SWT
.CURSOR_WAIT
);
809 if (fWaitCursorCount
== 1) { // The cursor is not in waiting mode
813 if (fWaitCursorCount
> 0) { // The cursor is in waiting mode
815 if (fWaitCursorCount
== 0) { // No more reason to wait
816 // Put back the default cursor
823 // Performs the updates on the UI thread
824 display
.asyncExec(new Runnable() {
827 if ((fTreeViewer
!= null)
828 && (!fTreeViewer
.getTree().isDisposed())) {
829 Cursor cursor
= null; // indicates default
831 cursor
= fWaitCursor
;
833 fTreeViewer
.getControl().setCursor(cursor
);
840 // ------------------------------------------------------------------------
841 // Methods reserved for the streaming functionality
842 // ------------------------------------------------------------------------
845 * Resets update synchronization information
847 protected void resetUpdateSynchronization() {
848 synchronized (fStatisticsUpdateSyncObj
) {
849 fStatisticsUpdateBusy
= false;
850 fStatisticsUpdatePending
= false;
851 fStatisticsUpdateRange
= null;
856 * Checks if statistics update is ongoing. If it is ongoing, the new time
857 * range is stored as pending
861 * @return true if statistic update is ongoing else false
863 protected boolean checkUpdateBusy(TmfTimeRange timeRange
) {
864 synchronized (fStatisticsUpdateSyncObj
) {
865 if (fStatisticsUpdateBusy
) {
866 fStatisticsUpdatePending
= true;
867 if (fStatisticsUpdateRange
== null
868 || timeRange
.getEndTime().compareTo(fStatisticsUpdateRange
.getEndTime()) > 0) {
869 fStatisticsUpdateRange
= timeRange
;
873 fStatisticsUpdateBusy
= true;
879 * Sends pending request (if any)
881 protected void sendPendingUpdate() {
882 synchronized (fStatisticsUpdateSyncObj
) {
883 fStatisticsUpdateBusy
= false;
884 if (fStatisticsUpdatePending
) {
885 fStatisticsUpdatePending
= false;
886 requestData(TmfExperiment
.getCurrentExperiment(), fStatisticsUpdateRange
);
887 fStatisticsUpdateRange
= null;