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