tmf: Merge TmfDataProvider and TmfEventProvider together
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / viewers / statistics / TmfStatisticsViewer.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 Ericsson
3 *
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
8 *
9 * Contributors:
10 * Mathieu Denis <mathieu.denis@polymtl.ca> - Initial API and implementation
11 * Alexandre Montplaisir - Port to ITmfStatistics provider
12 * Patrick Tasse - Support selection range
13 *******************************************************************************/
14
15 package org.eclipse.linuxtools.tmf.ui.viewers.statistics;
16
17 import java.util.List;
18 import java.util.Map;
19
20 import org.eclipse.jface.viewers.TreeViewer;
21 import org.eclipse.jface.viewers.TreeViewerColumn;
22 import org.eclipse.jface.viewers.Viewer;
23 import org.eclipse.jface.viewers.ViewerComparator;
24 import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
25 import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
26 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
27 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
28 import org.eclipse.linuxtools.tmf.core.signal.TmfStatsUpdatedSignal;
29 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
30 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal;
31 import org.eclipse.linuxtools.tmf.core.statistics.ITmfStatistics;
32 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
33 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
34 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
35 import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
36 import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
37 import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewer;
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.TmfStatisticsTree;
42 import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
43 import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
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;
55
56 /**
57 * A basic viewer to display statistics in the statistics view.
58 *
59 * It is linked to a single ITmfTrace until its disposal.
60 *
61 * @author Mathieu Denis
62 * @version 2.0
63 * @since 2.0
64 */
65 public class TmfStatisticsViewer extends TmfViewer {
66
67 /**
68 * Timestamp scale (nanosecond)
69 */
70 public static final byte TIME_SCALE = ITmfTimestamp.NANOSECOND_SCALE;
71
72 /**
73 * Default PAGE_SIZE for background requests.
74 */
75 protected static final int PAGE_SIZE = 50000;
76
77 /**
78 * Refresh frequency.
79 */
80 protected final Long STATS_INPUT_CHANGED_REFRESH = 5000L;
81
82 /**
83 * The actual tree viewer to display
84 */
85 protected TreeViewer fTreeViewer;
86
87 /**
88 * The statistics tree linked to this viewer
89 */
90 protected TmfStatisticsTree fStatisticsData;
91
92 /**
93 * Update synchronization parameter (used for streaming): Update busy
94 * indicator.
95 */
96 protected boolean fStatisticsUpdateBusy = false;
97
98 /**
99 * Update synchronization parameter (used for streaming): Update pending
100 * indicator.
101 */
102 protected boolean fStatisticsUpdatePending = false;
103
104 /**
105 * Update synchronization parameter (used for streaming): Pending Update
106 * time range.
107 */
108 protected TmfTimeRange fStatisticsUpdateRange = null;
109
110 /**
111 * Update synchronization object.
112 */
113 protected final Object fStatisticsUpdateSyncObj = new Object();
114
115 /**
116 * Update range synchronization object.
117 */
118 protected final Object fStatisticsRangeUpdateSyncObj = new Object();
119
120 /**
121 * The trace that is displayed by this viewer
122 */
123 protected ITmfTrace fTrace;
124
125 /**
126 * Stores the requested time range.
127 */
128 protected TmfTimeRange fRequestedTimerange;
129
130 /**
131 * Indicates to process all events
132 */
133 private boolean fProcessAll;
134
135 /**
136 * View instance counter (for multiple statistics views)
137 */
138 private static int fCountInstance = 0;
139
140 /**
141 * Number of this instance. Used as an instance ID.
142 */
143 private int fInstanceNb;
144
145 /**
146 * Object to store the cursor while waiting for the trace to load
147 */
148 private Cursor fWaitCursor = null;
149
150 /**
151 * Counts the number of times waitCursor() has been called. It avoids
152 * removing the waiting cursor, since there may be multiple requests running
153 * at the same time.
154 */
155 private int fWaitCursorCount = 0;
156
157 /**
158 * Tells to send a time range request when the trace gets updated.
159 */
160 private boolean fSendRangeRequest = true;
161
162 /** Reference to the trace manager */
163 private final TmfTraceManager fTraceManager;
164
165 /**
166 * Empty constructor. To be used in conjunction with
167 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
168 */
169 public TmfStatisticsViewer() {
170 super();
171 fTraceManager = TmfTraceManager.getInstance();
172 }
173
174 /**
175 * Create a basic statistics viewer. To be used in conjunction with
176 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
177 *
178 * @param parent
179 * The parent composite that will hold the viewer
180 * @param viewerName
181 * The name that will be assigned to this viewer
182 * @param trace
183 * The trace that is displayed by this viewer
184 * @see TmfComponent
185 */
186 public TmfStatisticsViewer(Composite parent, String viewerName, ITmfTrace trace) {
187 init(parent, viewerName, trace);
188 fTraceManager = TmfTraceManager.getInstance();
189 }
190
191 /**
192 * Initialize the statistics viewer.
193 *
194 * @param parent
195 * The parent component of the viewer.
196 * @param viewerName
197 * The name to give to the viewer.
198 * @param trace
199 * The trace that will be displayed by the viewer.
200 */
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.
204 fCountInstance++;
205 fInstanceNb = fCountInstance;
206 fTrace = trace;
207
208 // The viewer will process all events if he is assigned to an experiment
209 fProcessAll = (trace instanceof TmfExperiment);
210
211 initContent(parent);
212 initInput();
213 }
214
215 @Override
216 public void dispose() {
217 super.dispose();
218 if (fWaitCursor != null) {
219 fWaitCursor.dispose();
220 }
221
222 // Clean the model for this viewer
223 TmfStatisticsTreeManager.removeStatTreeRoot(getTreeID());
224 }
225
226 // ------------------------------------------------------------------------
227 // Signal handlers
228 // ------------------------------------------------------------------------
229
230 /**
231 * Handles the signal about new trace range.
232 *
233 * @param signal
234 * The trace range updated signal
235 */
236 @TmfSignalHandler
237 public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) {
238 ITmfTrace trace = signal.getTrace();
239 // validate
240 if (!isListeningTo(trace)) {
241 return;
242 }
243
244 synchronized (fStatisticsRangeUpdateSyncObj) {
245 // Sends the time range request only once from this method.
246 if (fSendRangeRequest) {
247 fSendRangeRequest = false;
248 ITmfTimestamp begin = fTraceManager.getSelectionBeginTime();
249 ITmfTimestamp end = fTraceManager.getSelectionEndTime();
250 TmfTimeRange timeRange = new TmfTimeRange(begin, end);
251 requestTimeRangeData(trace, timeRange);
252 }
253 }
254 requestData(trace, signal.getRange());
255 }
256
257 /**
258 * Handles the time range updated signal. It updates the time range
259 * statistics.
260 *
261 * @param signal
262 * Contains the information about the new selected time range.
263 * @deprecated
264 * As of 2.1, use {@link #timeSynchUpdated(TmfTimeSynchSignal)}
265 */
266 @Deprecated
267 @TmfSignalHandler
268 public void timeRangeUpdated(TmfRangeSynchSignal signal) {
269 }
270
271 /**
272 * Handles the time synch updated signal. It updates the time range
273 * statistics.
274 *
275 * @param signal
276 * Contains the information about the new selected time range.
277 * @since 2.1
278 */
279 @TmfSignalHandler
280 public void timeSynchUpdated(TmfTimeSynchSignal signal) {
281 if (fTrace == null) {
282 return;
283 }
284 ITmfTimestamp begin = signal.getBeginTime();
285 ITmfTimestamp end = signal.getEndTime();
286 TmfTimeRange timeRange = new TmfTimeRange(begin, end);
287 requestTimeRangeData(fTrace, timeRange);
288 }
289
290 /**
291 * Whenever a trace's statistics back-end finishes computing the statistics
292 * for a given interval, it will send the StatsUpdated signal. This method
293 * will receive this signal and update the statistics view accordingly.
294 *
295 * @param sig
296 * The signal that is received
297 */
298 @TmfSignalHandler
299 public void statsUpdated(TmfStatsUpdatedSignal sig) {
300 /* Only handle this signal if it's about the trace we represent. */
301 if (!isListeningTo(sig.getTrace())) {
302 return;
303 }
304
305 final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
306 Map<String, Long> map = sig.getEventsPerType();
307 String name = sig.getTrace().getName();
308 boolean isGlobal = sig.isGlobal();
309
310 /*
311 * "Global", "partial", "total", etc., it's all very confusing...
312 *
313 * The base view shows the total count for the trace and for
314 * each even types, organized in columns like this:
315 *
316 * | Global | Time range |
317 * trace name | A | B |
318 * Event Type | | |
319 * <event 1> | C | D |
320 * <event 2> | ... | ... |
321 * ... | | |
322 *
323 * Here, we called the cells like this:
324 * A : GlobalTotal
325 * B : TimeRangeTotal
326 * C : GlobalTypeCount(s)
327 * D : TimeRangeTypeCount(s)
328 */
329
330 /* Fill in an the event counts (either cells C or D) */
331 for (Map.Entry<String, Long> entry : map.entrySet()) {
332 statsData.setTypeCount(name, entry.getKey(), isGlobal, entry.getValue());
333 }
334
335 /*
336 * Calculate the totals (cell A or B, depending if isGlobal). We will
337 * use the results of the previous request instead of sending another
338 * one.
339 */
340 long globalTotal = 0;
341 for (long val : map.values()) {
342 globalTotal += val;
343 }
344 statsData.setTotal(name, isGlobal, globalTotal);
345
346 modelComplete(isGlobal);
347 }
348
349 // ------------------------------------------------------------------------
350 // Class methods
351 // ------------------------------------------------------------------------
352
353 /*
354 * Returns the primary control associated with this viewer.
355 *
356 * @return the SWT control which displays this viewer's content
357 */
358 @Override
359 public Control getControl() {
360 return fTreeViewer.getControl();
361 }
362
363 /**
364 * Get the input of the viewer.
365 *
366 * @return an object representing the input of the statistics viewer.
367 */
368 public Object getInput() {
369 return fTreeViewer.getInput();
370 }
371
372 /**
373 * Return the size of the request when performing background request.
374 *
375 * @return the block size for background request.
376 */
377 public int getPageSize() {
378 return PAGE_SIZE;
379 }
380
381 /**
382 * Return the number of events to receive before a refresh of the viewer is
383 * performed.
384 *
385 * @return the input refresh rate
386 */
387 public long getRefreshRate() {
388 return STATS_INPUT_CHANGED_REFRESH;
389 }
390
391 /**
392 * This method can be overridden to implement another way of representing
393 * the statistics data and to retrieve the information for display.
394 *
395 * @return a TmfStatisticsData object.
396 */
397 public TmfStatisticsTree getStatisticData() {
398 if (fStatisticsData == null) {
399 fStatisticsData = new TmfStatisticsTree();
400 }
401 return fStatisticsData;
402 }
403
404 /**
405 * Returns a unique ID based on name to be associated with the statistics
406 * tree for this viewer. For a same name, it will always return the same ID.
407 *
408 * @return a unique statistics tree ID.
409 */
410 public String getTreeID() {
411 return getName() + fInstanceNb;
412 }
413
414 @Override
415 public void refresh() {
416 final Control viewerControl = getControl();
417 // Ignore update if disposed
418 if (viewerControl.isDisposed()) {
419 return;
420 }
421
422 viewerControl.getDisplay().asyncExec(new Runnable() {
423 @Override
424 public void run() {
425 if (!viewerControl.isDisposed()) {
426 fTreeViewer.refresh();
427 }
428 }
429 });
430 }
431
432 /**
433 * Will force a request on the partial event count if one is needed.
434 */
435 public void sendPartialRequestOnNextUpdate() {
436 synchronized (fStatisticsRangeUpdateSyncObj) {
437 fSendRangeRequest = true;
438 }
439 }
440
441 /**
442 * Focus on the statistics tree of the viewer
443 */
444 public void setFocus() {
445 fTreeViewer.getTree().setFocus();
446 }
447
448 /**
449 * Cancels the request if it is not already completed
450 *
451 * @param request
452 * The request to be canceled
453 */
454 protected void cancelOngoingRequest(ITmfEventRequest request) {
455 if (request != null && !request.isCompleted()) {
456 request.cancel();
457 }
458 }
459
460 /**
461 * This method can be overridden to change the representation of the data in
462 * the columns.
463 *
464 * @return an object implementing ITmfBaseColumnDataProvider.
465 */
466 protected ITmfColumnDataProvider getColumnDataProvider() {
467 return new TmfBaseColumnDataProvider();
468 }
469
470 /**
471 * Initialize the content that will be drawn in this viewer
472 *
473 * @param parent
474 * The parent of the control to create
475 */
476 protected void initContent(Composite parent) {
477 final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
478
479 fTreeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
480 fTreeViewer.setContentProvider(new TmfTreeContentProvider());
481 fTreeViewer.getTree().setHeaderVisible(true);
482 fTreeViewer.setUseHashlookup(true);
483
484 // Creates the columns defined by the column data provider
485 for (final TmfBaseColumnData columnData : columnDataList) {
486 final TreeViewerColumn treeColumn = new TreeViewerColumn(fTreeViewer, columnData.getAlignment());
487 treeColumn.getColumn().setText(columnData.getHeader());
488 treeColumn.getColumn().setWidth(columnData.getWidth());
489 treeColumn.getColumn().setToolTipText(columnData.getTooltip());
490
491 if (columnData.getComparator() != null) { // A comparator is defined.
492 // Adds a listener on the columns header for sorting purpose.
493 treeColumn.getColumn().addSelectionListener(new SelectionAdapter() {
494
495 private ViewerComparator reverseComparator;
496
497 @Override
498 public void widgetSelected(SelectionEvent e) {
499 // Initializes the reverse comparator once.
500 if (reverseComparator == null) {
501 reverseComparator = new ViewerComparator() {
502 @Override
503 public int compare(Viewer viewer, Object e1, Object e2) {
504 return -1 * columnData.getComparator().compare(viewer, e1, e2);
505 }
506 };
507 }
508
509 if (fTreeViewer.getTree().getSortDirection() == SWT.UP
510 || fTreeViewer.getTree().getSortColumn() != treeColumn.getColumn()) {
511 /*
512 * Puts the descendant order if the old order was
513 * up or if the selected column has changed.
514 */
515 fTreeViewer.setComparator(columnData.getComparator());
516 fTreeViewer.getTree().setSortDirection(SWT.DOWN);
517 } else {
518 /*
519 * Puts the ascendant ordering if the selected
520 * column hasn't changed.
521 */
522 fTreeViewer.setComparator(reverseComparator);
523 fTreeViewer.getTree().setSortDirection(SWT.UP);
524 }
525 fTreeViewer.getTree().setSortColumn(treeColumn.getColumn());
526 }
527 });
528 }
529 treeColumn.setLabelProvider(columnData.getLabelProvider());
530 }
531
532 // Handler that will draw the bar charts.
533 fTreeViewer.getTree().addListener(SWT.EraseItem, new Listener() {
534 @Override
535 public void handleEvent(Event event) {
536 if (columnDataList.get(event.index).getPercentageProvider() != null) {
537 TmfStatisticsTreeNode node = (TmfStatisticsTreeNode) event.item.getData();
538
539 double percentage = columnDataList.get(event.index).getPercentageProvider().getPercentage(node);
540 if (percentage == 0) { // No bar to draw
541 return;
542 }
543
544 if ((event.detail & SWT.SELECTED) > 0) { // The item is selected.
545 // Draws our own background to avoid overwritten the bar.
546 event.gc.fillRectangle(event.x, event.y, event.width, event.height);
547 event.detail &= ~SWT.SELECTED;
548 }
549
550 int barWidth = (int) ((fTreeViewer.getTree().getColumn(event.index).getWidth() - 8) * percentage);
551 int oldAlpha = event.gc.getAlpha();
552 Color oldForeground = event.gc.getForeground();
553 Color oldBackground = event.gc.getBackground();
554 /*
555 * Draws a transparent gradient rectangle from the color of
556 * foreground and background.
557 */
558 event.gc.setAlpha(64);
559 event.gc.setForeground(event.item.getDisplay().getSystemColor(SWT.COLOR_BLUE));
560 event.gc.setBackground(event.item.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
561 event.gc.fillGradientRectangle(event.x, event.y, barWidth, event.height, true);
562 event.gc.drawRectangle(event.x, event.y, barWidth, event.height);
563 // Restores old values
564 event.gc.setForeground(oldForeground);
565 event.gc.setBackground(oldBackground);
566 event.gc.setAlpha(oldAlpha);
567 event.detail &= ~SWT.BACKGROUND;
568 }
569 }
570 });
571
572 // Initializes the comparator parameters
573 fTreeViewer.setComparator(columnDataList.get(0).getComparator());
574 fTreeViewer.getTree().setSortColumn(fTreeViewer.getTree().getColumn(0));
575 fTreeViewer.getTree().setSortDirection(SWT.DOWN);
576 }
577
578 /**
579 * Initializes the input for the tree viewer.
580 */
581 protected void initInput() {
582 String treeID = getTreeID();
583 TmfStatisticsTreeNode statisticsTreeNode;
584 if (TmfStatisticsTreeManager.containsTreeRoot(treeID)) {
585 // The statistics root is already present
586 statisticsTreeNode = TmfStatisticsTreeManager.getStatTreeRoot(treeID);
587
588 // Checks if the trace is already in the statistics tree.
589 int numNodeTraces = statisticsTreeNode.getNbChildren();
590
591 ITmfTrace[] traces = TmfTraceManager.getTraceSet(fTrace);
592 int numTraces = traces.length;
593
594 if (numTraces == numNodeTraces) {
595 boolean same = true;
596 /*
597 * Checks if the experiment contains the same traces as when
598 * previously selected.
599 */
600 for (int i = 0; i < numTraces; i++) {
601 String traceName = traces[i].getName();
602 if (!statisticsTreeNode.containsChild(traceName)) {
603 same = false;
604 break;
605 }
606 }
607
608 if (same) {
609 // No need to reload data, all traces are already loaded
610 fTreeViewer.setInput(statisticsTreeNode);
611 return;
612 }
613 // Clears the old content to start over
614 statisticsTreeNode.reset();
615 }
616 } else {
617 // Creates a new tree
618 statisticsTreeNode = TmfStatisticsTreeManager.addStatsTreeRoot(treeID, getStatisticData());
619 }
620
621 // Sets the input to a clean data model
622 fTreeViewer.setInput(statisticsTreeNode);
623 resetUpdateSynchronization();
624 }
625
626 /**
627 * Tells if the viewer is listening to a trace.
628 *
629 * @param trace
630 * The trace that the viewer may be listening
631 * @return true if the viewer is listening to the trace, false otherwise
632 */
633 protected boolean isListeningTo(ITmfTrace trace) {
634 if (fProcessAll || trace == fTrace) {
635 return true;
636 }
637 return false;
638 }
639
640 /**
641 * Called when an trace request has been completed successfully.
642 *
643 * @param global
644 * Tells if the request is a global or time range (partial)
645 * request.
646 */
647 protected void modelComplete(boolean global) {
648 refresh();
649 waitCursor(false);
650 if (global) {
651 sendPendingUpdate();
652 }
653 }
654
655 /**
656 * Called when an trace request has failed or has been cancelled.
657 *
658 * @param isGlobalRequest
659 * Tells if the request is a global or time range (partial)
660 * request.
661 */
662 protected void modelIncomplete(boolean isGlobalRequest) {
663 if (isGlobalRequest) { // Clean the global statistics
664 /*
665 * No need to reset the global number of events, since the index of
666 * the last requested event is known.
667 */
668 resetUpdateSynchronization();
669 sendPendingUpdate();
670 } else { // Clean the partial statistics
671 resetTimeRangeValue();
672 }
673 refresh();
674 waitCursor(false);
675 }
676
677 /**
678 * Sends the request to the trace for the whole trace
679 *
680 * @param trace
681 * The trace used to send the request
682 * @param timeRange
683 * The range to request to the trace
684 */
685 protected void requestData(final ITmfTrace trace, final TmfTimeRange timeRange) {
686 buildStatisticsTree(trace, timeRange, true);
687 }
688
689 /**
690 * Sends the time range request from the trace
691 *
692 * @param trace
693 * The trace used to send the request
694 * @param timeRange
695 * The range to request to the trace
696 */
697 protected void requestTimeRangeData(final ITmfTrace trace, final TmfTimeRange timeRange) {
698 fRequestedTimerange = timeRange;
699 buildStatisticsTree(trace, timeRange, false);
700 }
701
702 /**
703 * Requests all the data of the trace to the state system which
704 * contains information about the statistics.
705 *
706 * Since the viewer may be listening to multiple traces, it may receive
707 * an experiment rather than a single trace. The filtering is done with the
708 * method {@link #isListeningTo(String trace)}.
709 *
710 * @param trace
711 * The trace for which a request must be done
712 * @param timeRange
713 * The time range that will be requested to the state system
714 * @param isGlobal
715 * Tells if the request is for the global event count or the
716 * partial one.
717 */
718 private void buildStatisticsTree(final ITmfTrace trace, TmfTimeRange timeRange, boolean isGlobal) {
719 final TmfStatisticsTreeNode statTree = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
720 final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
721 if (statsData == null) {
722 return;
723 }
724
725 synchronized (statsData) {
726 if (isGlobal) {
727 statTree.resetGlobalValue();
728 } else {
729 statTree.resetTimeRangeValue();
730 }
731
732 for (final ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) {
733 if (!isListeningTo(aTrace)) {
734 continue;
735 }
736
737 /* Retrieves the statistics object */
738 final ITmfStatistics stats = aTrace.getStatistics();
739 if (stats == null) {
740 /*
741 * The statistics provider for this trace is not accessible
742 * (yet?). Try the next one.
743 */
744 continue;
745 }
746
747 /* The generic statistics are stored in nanoseconds, so we must make
748 * sure the time range is scaled correctly. */
749 long start = timeRange.getStartTime().normalize(0, TIME_SCALE).getValue();
750 long end = timeRange.getEndTime().normalize(0, TIME_SCALE).getValue();
751
752 /*
753 * Send a request to update the statistics view. The result will
754 * be sent through a {@link TmfStatsUpdatedSignal}, and will be
755 * processed by the signal handler.
756 */
757 aTrace.getStatistics().updateStats(isGlobal, start, end);
758 }
759 }
760 }
761
762 /**
763 * Resets the number of events within the time range
764 */
765 protected void resetTimeRangeValue() {
766 TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
767 if (treeModelRoot != null && treeModelRoot.hasChildren()) {
768 treeModelRoot.resetTimeRangeValue();
769 }
770 }
771
772 /**
773 * When the trace is loading the cursor will be different so the user
774 * knows that the processing is not finished yet.
775 *
776 * Calls to this method are stacked.
777 *
778 * @param waitRequested
779 * Indicates if we need to show the waiting cursor, or the
780 * default one.
781 */
782 protected void waitCursor(final boolean waitRequested) {
783 if ((fTreeViewer == null) || (fTreeViewer.getTree().isDisposed())) {
784 return;
785 }
786
787 boolean needsUpdate = false;
788 Display display = fTreeViewer.getControl().getDisplay();
789 if (waitRequested) {
790 fWaitCursorCount++;
791 if (fWaitCursor == null) { // The cursor hasn't been initialized yet
792 fWaitCursor = new Cursor(display, SWT.CURSOR_WAIT);
793 }
794 if (fWaitCursorCount == 1) { // The cursor is not in waiting mode
795 needsUpdate = true;
796 }
797 } else {
798 if (fWaitCursorCount > 0) { // The cursor is in waiting mode
799 fWaitCursorCount--;
800 if (fWaitCursorCount == 0) { // No more reason to wait
801 // Put back the default cursor
802 needsUpdate = true;
803 }
804 }
805 }
806
807 if (needsUpdate) {
808 // Performs the updates on the UI thread
809 display.asyncExec(new Runnable() {
810 @Override
811 public void run() {
812 if ((fTreeViewer != null)
813 && (!fTreeViewer.getTree().isDisposed())) {
814 Cursor cursor = null; // indicates default
815 if (waitRequested) {
816 cursor = fWaitCursor;
817 }
818 fTreeViewer.getControl().setCursor(cursor);
819 }
820 }
821 });
822 }
823 }
824
825 // ------------------------------------------------------------------------
826 // Methods reserved for the streaming functionality
827 // ------------------------------------------------------------------------
828
829 /**
830 * Resets update synchronization information
831 */
832 protected void resetUpdateSynchronization() {
833 synchronized (fStatisticsUpdateSyncObj) {
834 fStatisticsUpdateBusy = false;
835 fStatisticsUpdatePending = false;
836 fStatisticsUpdateRange = null;
837 }
838 }
839
840 /**
841 * Checks if statistics update is ongoing. If it is ongoing, the new time
842 * range is stored as pending
843 *
844 * @param timeRange
845 * - new time range
846 * @return true if statistic update is ongoing else false
847 */
848 protected boolean checkUpdateBusy(TmfTimeRange timeRange) {
849 synchronized (fStatisticsUpdateSyncObj) {
850 if (fStatisticsUpdateBusy) {
851 fStatisticsUpdatePending = true;
852 if (fStatisticsUpdateRange == null
853 || timeRange.getEndTime().compareTo(fStatisticsUpdateRange.getEndTime()) > 0) {
854 fStatisticsUpdateRange = timeRange;
855 }
856 return true;
857 }
858 fStatisticsUpdateBusy = true;
859 return false;
860 }
861 }
862
863 /**
864 * Sends pending request (if any)
865 */
866 protected void sendPendingUpdate() {
867 synchronized (fStatisticsUpdateSyncObj) {
868 fStatisticsUpdateBusy = false;
869 if (fStatisticsUpdatePending) {
870 fStatisticsUpdatePending = false;
871 requestData(fTrace, fStatisticsUpdateRange);
872 fStatisticsUpdateRange = null;
873 }
874 }
875 }
876 }
This page took 0.05177 seconds and 6 git commands to generate.