lttng: More luna annotation updates
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / viewers / statistics / TmfStatisticsViewer.java
CommitLineData
cfd22ad0 1/*******************************************************************************
c8422608 2 * Copyright (c) 2012, 2013 Ericsson
cfd22ad0
MD
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
0fcf3b09 12 * Patrick Tasse - Support selection range
cfd22ad0
MD
13 *******************************************************************************/
14
15package org.eclipse.linuxtools.tmf.ui.viewers.statistics;
16
17import java.util.List;
89c06060 18import java.util.Map;
cfd22ad0
MD
19
20import org.eclipse.jface.viewers.TreeViewer;
21import org.eclipse.jface.viewers.TreeViewerColumn;
22import org.eclipse.jface.viewers.Viewer;
23import org.eclipse.jface.viewers.ViewerComparator;
24import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
05627bda 25import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
05627bda
MD
26import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
27import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
1c0de632 28import org.eclipse.linuxtools.tmf.core.signal.TmfStatsUpdatedSignal;
0fcf3b09 29import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
faa38350 30import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal;
89c06060 31import org.eclipse.linuxtools.tmf.core.statistics.ITmfStatistics;
3bd46eef
AM
32import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
33import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
05627bda
MD
34import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
35import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
248af329 36import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
05627bda 37import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewer;
cfd22ad0
MD
38import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.ITmfColumnDataProvider;
39import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
40import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnDataProvider;
36033ff0
AM
41import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
42import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
cfd22ad0 43import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
cfd22ad0
MD
44import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfTreeContentProvider;
45import org.eclipse.swt.SWT;
46import org.eclipse.swt.events.SelectionAdapter;
47import org.eclipse.swt.events.SelectionEvent;
48import org.eclipse.swt.graphics.Color;
49import org.eclipse.swt.graphics.Cursor;
cfd22ad0
MD
50import org.eclipse.swt.widgets.Composite;
51import org.eclipse.swt.widgets.Control;
52import org.eclipse.swt.widgets.Display;
53import org.eclipse.swt.widgets.Event;
54import org.eclipse.swt.widgets.Listener;
55
56/**
57 * A basic viewer to display statistics in the statistics view.
58 *
8b60cb37
MD
59 * It is linked to a single ITmfTrace until its disposal.
60 *
cfd22ad0
MD
61 * @author Mathieu Denis
62 * @version 2.0
63 * @since 2.0
64 */
05627bda 65public class TmfStatisticsViewer extends TmfViewer {
cfd22ad0 66
05627bda
MD
67 /**
68 * Timestamp scale (nanosecond)
69 */
faa38350 70 public static final byte TIME_SCALE = ITmfTimestamp.NANOSECOND_SCALE;
05627bda
MD
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
cfd22ad0
MD
82 /**
83 * The actual tree viewer to display
84 */
85 protected TreeViewer fTreeViewer;
86
87 /**
05627bda
MD
88 * The statistics tree linked to this viewer
89 */
36033ff0 90 protected TmfStatisticsTree fStatisticsData;
05627bda
MD
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
3c934968
MD
115 /**
116 * Update range synchronization object.
117 */
118 protected final Object fStatisticsRangeUpdateSyncObj = new Object();
119
89c06060 120 /**
73fbf6be
MD
121 * The trace that is displayed by this viewer
122 */
123 protected ITmfTrace fTrace;
124
89c06060
AM
125 /**
126 * Stores the requested time range.
127 */
128 protected TmfTimeRange fRequestedTimerange;
129
05627bda
MD
130 /**
131 * Indicates to process all events
132 */
133 private boolean fProcessAll;
134
135 /**
136 * View instance counter (for multiple statistics views)
cfd22ad0
MD
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 /**
faa38350 146 * Object to store the cursor while waiting for the trace to load
cfd22ad0
MD
147 */
148 private Cursor fWaitCursor = null;
149
150 /**
05627bda
MD
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 /**
faa38350 158 * Tells to send a time range request when the trace gets updated.
05627bda
MD
159 */
160 private boolean fSendRangeRequest = true;
161
f0c0d2c2
AM
162 /** Reference to the trace manager */
163 private final TmfTraceManager fTraceManager;
164
05627bda
MD
165 /**
166 * Empty constructor. To be used in conjunction with
167 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
168 */
169 public TmfStatisticsViewer() {
170 super();
f0c0d2c2 171 fTraceManager = TmfTraceManager.getInstance();
05627bda
MD
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);
f0c0d2c2 188 fTraceManager = TmfTraceManager.getInstance();
05627bda
MD
189 }
190
191 /**
192 * Initialize the statistics viewer.
cfd22ad0
MD
193 *
194 * @param parent
05627bda
MD
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.
cfd22ad0 200 */
05627bda
MD
201 public void init(Composite parent, String viewerName, ITmfTrace trace) {
202 super.init(parent, viewerName);
cfd22ad0
MD
203 // Increment a counter to make sure the tree ID is unique.
204 fCountInstance++;
205 fInstanceNb = fCountInstance;
05627bda
MD
206 fTrace = trace;
207
faa38350 208 // The viewer will process all events if he is assigned to an experiment
05627bda
MD
209 fProcessAll = (trace instanceof TmfExperiment);
210
211 initContent(parent);
8b60cb37 212 initInput();
05627bda
MD
213 }
214
05627bda
MD
215 @Override
216 public void dispose() {
217 super.dispose();
218 if (fWaitCursor != null) {
219 fWaitCursor.dispose();
220 }
8b60cb37 221
66792052 222 // Clean the model for this viewer
36033ff0 223 TmfStatisticsTreeManager.removeStatTreeRoot(getTreeID());
05627bda
MD
224 }
225
1c0de632
AM
226 // ------------------------------------------------------------------------
227 // Signal handlers
228 // ------------------------------------------------------------------------
89c06060 229
05627bda 230 /**
faa38350 231 * Handles the signal about new trace range.
05627bda
MD
232 *
233 * @param signal
faa38350 234 * The trace range updated signal
05627bda
MD
235 */
236 @TmfSignalHandler
faa38350
PT
237 public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) {
238 ITmfTrace trace = signal.getTrace();
05627bda 239 // validate
faa38350 240 if (!isListeningTo(trace)) {
05627bda
MD
241 return;
242 }
243
3c934968
MD
244 synchronized (fStatisticsRangeUpdateSyncObj) {
245 // Sends the time range request only once from this method.
246 if (fSendRangeRequest) {
247 fSendRangeRequest = false;
0fcf3b09
PT
248 ITmfTimestamp begin = fTraceManager.getSelectionBeginTime();
249 ITmfTimestamp end = fTraceManager.getSelectionEndTime();
250 TmfTimeRange timeRange = new TmfTimeRange(begin, end);
251 requestTimeRangeData(trace, timeRange);
3c934968 252 }
05627bda 253 }
faa38350 254 requestData(trace, signal.getRange());
05627bda
MD
255 }
256
257 /**
89c06060 258 * Handles the time range updated signal. It updates the time range
05627bda
MD
259 * statistics.
260 *
261 * @param signal
262 * Contains the information about the new selected time range.
0fcf3b09
PT
263 * @deprecated
264 * As of 2.1, use {@link #timeSynchUpdated(TmfTimeSynchSignal)}
05627bda 265 */
0fcf3b09 266 @Deprecated
05627bda
MD
267 @TmfSignalHandler
268 public void timeRangeUpdated(TmfRangeSynchSignal signal) {
0fcf3b09
PT
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.
00ff7819 277 * @since 3.0
0fcf3b09
PT
278 */
279 @TmfSignalHandler
280 public void timeSynchUpdated(TmfTimeSynchSignal signal) {
faa38350
PT
281 if (fTrace == null) {
282 return;
283 }
0fcf3b09
PT
284 ITmfTimestamp begin = signal.getBeginTime();
285 ITmfTimestamp end = signal.getEndTime();
286 TmfTimeRange timeRange = new TmfTimeRange(begin, end);
287 requestTimeRangeData(fTrace, timeRange);
05627bda
MD
288 }
289
1c0de632
AM
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
05627bda
MD
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 */
36033ff0 397 public TmfStatisticsTree getStatisticData() {
05627bda 398 if (fStatisticsData == null) {
36033ff0 399 fStatisticsData = new TmfStatisticsTree();
05627bda
MD
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
3c934968
MD
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
05627bda
MD
441 /**
442 * Focus on the statistics tree of the viewer
443 */
444 public void setFocus() {
445 fTreeViewer.getTree().setFocus();
446 }
447
05627bda
MD
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(ITmfDataRequest 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 }
cfd22ad0 469
05627bda
MD
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) {
cfd22ad0 477 final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
cfd22ad0
MD
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
8b60cb37
MD
578 /**
579 * Initializes the input for the tree viewer.
8b60cb37
MD
580 */
581 protected void initInput() {
582 String treeID = getTreeID();
faa38350 583 TmfStatisticsTreeNode statisticsTreeNode;
36033ff0 584 if (TmfStatisticsTreeManager.containsTreeRoot(treeID)) {
faa38350
PT
585 // The statistics root is already present
586 statisticsTreeNode = TmfStatisticsTreeManager.getStatTreeRoot(treeID);
8b60cb37
MD
587
588 // Checks if the trace is already in the statistics tree.
faa38350 589 int numNodeTraces = statisticsTreeNode.getNbChildren();
8b60cb37 590
b9a5bf8f 591 ITmfTrace[] traces = TmfTraceManager.getTraceSet(fTrace);
fe0c44c4 592 int numTraces = traces.length;
8b60cb37
MD
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++) {
fe0c44c4 601 String traceName = traces[i].getName();
faa38350 602 if (!statisticsTreeNode.containsChild(traceName)) {
8b60cb37
MD
603 same = false;
604 break;
605 }
606 }
607
608 if (same) {
609 // No need to reload data, all traces are already loaded
faa38350 610 fTreeViewer.setInput(statisticsTreeNode);
8b60cb37
MD
611 return;
612 }
613 // Clears the old content to start over
faa38350 614 statisticsTreeNode.reset();
8b60cb37
MD
615 }
616 } else {
617 // Creates a new tree
faa38350 618 statisticsTreeNode = TmfStatisticsTreeManager.addStatsTreeRoot(treeID, getStatisticData());
8b60cb37
MD
619 }
620
621 // Sets the input to a clean data model
faa38350 622 fTreeViewer.setInput(statisticsTreeNode);
8b60cb37
MD
623 resetUpdateSynchronization();
624 }
625
cfd22ad0 626 /**
faa38350 627 * Tells if the viewer is listening to a trace.
cfd22ad0 628 *
1c0de632 629 * @param trace
05627bda
MD
630 * The trace that the viewer may be listening
631 * @return true if the viewer is listening to the trace, false otherwise
cfd22ad0 632 */
1c0de632
AM
633 protected boolean isListeningTo(ITmfTrace trace) {
634 if (fProcessAll || trace == fTrace) {
05627bda 635 return true;
cfd22ad0 636 }
05627bda 637 return false;
cfd22ad0
MD
638 }
639
640 /**
faa38350 641 * Called when an trace request has been completed successfully.
cfd22ad0 642 *
05627bda
MD
643 * @param global
644 * Tells if the request is a global or time range (partial)
645 * request.
cfd22ad0 646 */
05627bda
MD
647 protected void modelComplete(boolean global) {
648 refresh();
649 waitCursor(false);
650 if (global) {
651 sendPendingUpdate();
652 }
cfd22ad0
MD
653 }
654
655 /**
faa38350 656 * Called when an trace request has failed or has been cancelled.
cfd22ad0 657 *
05627bda
MD
658 * @param isGlobalRequest
659 * Tells if the request is a global or time range (partial)
660 * request.
cfd22ad0 661 */
05627bda
MD
662 protected void modelIncomplete(boolean isGlobalRequest) {
663 if (isGlobalRequest) { // Clean the global statistics
664 /*
763f4972
MD
665 * No need to reset the global number of events, since the index of
666 * the last requested event is known.
05627bda 667 */
05627bda
MD
668 resetUpdateSynchronization();
669 sendPendingUpdate();
670 } else { // Clean the partial statistics
671 resetTimeRangeValue();
672 }
673 refresh();
674 waitCursor(false);
cfd22ad0
MD
675 }
676
677 /**
faa38350 678 * Sends the request to the trace for the whole trace
cfd22ad0 679 *
faa38350
PT
680 * @param trace
681 * The trace used to send the request
8b260d9f 682 * @param timeRange
faa38350 683 * The range to request to the trace
cfd22ad0 684 */
faa38350
PT
685 protected void requestData(final ITmfTrace trace, final TmfTimeRange timeRange) {
686 buildStatisticsTree(trace, timeRange, true);
cfd22ad0
MD
687 }
688
689 /**
faa38350 690 * Sends the time range request from the trace
cfd22ad0 691 *
faa38350
PT
692 * @param trace
693 * The trace used to send the request
8b260d9f 694 * @param timeRange
faa38350 695 * The range to request to the trace
cfd22ad0 696 */
faa38350 697 protected void requestTimeRangeData(final ITmfTrace trace, final TmfTimeRange timeRange) {
89c06060 698 fRequestedTimerange = timeRange;
faa38350 699 buildStatisticsTree(trace, timeRange, false);
89c06060
AM
700 }
701
702 /**
faa38350 703 * Requests all the data of the trace to the state system which
89c06060
AM
704 * contains information about the statistics.
705 *
faa38350
PT
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
89c06060
AM
708 * method {@link #isListeningTo(String trace)}.
709 *
faa38350
PT
710 * @param trace
711 * The trace for which a request must be done
89c06060
AM
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 */
faa38350 718 private void buildStatisticsTree(final ITmfTrace trace, TmfTimeRange timeRange, boolean isGlobal) {
36033ff0
AM
719 final TmfStatisticsTreeNode statTree = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
720 final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
89c06060
AM
721 if (statsData == null) {
722 return;
723 }
724
725 synchronized (statsData) {
726 if (isGlobal) {
727 statTree.resetGlobalValue();
728 } else {
729 statTree.resetTimeRangeValue();
730 }
731
b9a5bf8f 732 for (final ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) {
faa38350 733 if (!isListeningTo(aTrace)) {
89c06060
AM
734 continue;
735 }
736
737 /* Retrieves the statistics object */
faa38350 738 final ITmfStatistics stats = aTrace.getStatistics();
89c06060
AM
739 if (stats == null) {
740 /*
1c0de632
AM
741 * The statistics provider for this trace is not accessible
742 * (yet?). Try the next one.
89c06060
AM
743 */
744 continue;
745 }
746
1c0de632
AM
747 /* The generic statistics are stored in nanoseconds, so we must make
748 * sure the time range is scaled correctly. */
8b260d9f
AM
749 long start = timeRange.getStartTime().normalize(0, TIME_SCALE).getValue();
750 long end = timeRange.getEndTime().normalize(0, TIME_SCALE).getValue();
89c06060 751
1c0de632
AM
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 */
faa38350 757 aTrace.getStatistics().updateStats(isGlobal, start, end);
89c06060 758 }
89c06060 759 }
cfd22ad0
MD
760 }
761
762 /**
05627bda 763 * Resets the number of events within the time range
cfd22ad0 764 */
05627bda 765 protected void resetTimeRangeValue() {
36033ff0 766 TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
05627bda
MD
767 if (treeModelRoot != null && treeModelRoot.hasChildren()) {
768 treeModelRoot.resetTimeRangeValue();
769 }
cfd22ad0
MD
770 }
771
772 /**
faa38350 773 * When the trace is loading the cursor will be different so the user
05627bda
MD
774 * knows that the processing is not finished yet.
775 *
776 * Calls to this method are stacked.
cfd22ad0 777 *
05627bda 778 * @param waitRequested
cfd22ad0 779 * Indicates if we need to show the waiting cursor, or the
05627bda 780 * default one.
cfd22ad0 781 */
05627bda 782 protected void waitCursor(final boolean waitRequested) {
cfd22ad0
MD
783 if ((fTreeViewer == null) || (fTreeViewer.getTree().isDisposed())) {
784 return;
785 }
786
05627bda 787 boolean needsUpdate = false;
cfd22ad0 788 Display display = fTreeViewer.getControl().getDisplay();
05627bda
MD
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 }
cfd22ad0
MD
805 }
806
05627bda
MD
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);
cfd22ad0 819 }
cfd22ad0 820 }
05627bda
MD
821 });
822 }
cfd22ad0
MD
823 }
824
05627bda
MD
825 // ------------------------------------------------------------------------
826 // Methods reserved for the streaming functionality
827 // ------------------------------------------------------------------------
828
cfd22ad0 829 /**
05627bda 830 * Resets update synchronization information
cfd22ad0 831 */
05627bda
MD
832 protected void resetUpdateSynchronization() {
833 synchronized (fStatisticsUpdateSyncObj) {
834 fStatisticsUpdateBusy = false;
835 fStatisticsUpdatePending = false;
836 fStatisticsUpdateRange = null;
837 }
cfd22ad0
MD
838 }
839
840 /**
05627bda
MD
841 * Checks if statistics update is ongoing. If it is ongoing, the new time
842 * range is stored as pending
cfd22ad0 843 *
05627bda
MD
844 * @param timeRange
845 * - new time range
846 * @return true if statistic update is ongoing else false
cfd22ad0 847 */
05627bda
MD
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;
faa38350 871 requestData(fTrace, fStatisticsUpdateRange);
05627bda
MD
872 fStatisticsUpdateRange = null;
873 }
874 }
cfd22ad0
MD
875 }
876}
This page took 0.074087 seconds and 5 git commands to generate.