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