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