Commit | Line | Data |
---|---|---|
6e512b93 ASL |
1 | /******************************************************************************* |
2 | * Copyright (c) 2009 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: | |
dfaf8391 FC |
10 | * Yann N. Dauphin (dhaemon@gmail.com) - Implementation |
11 | * Francois Chouinard (fchouinard@gmail.com) - Initial API | |
6e512b93 ASL |
12 | *******************************************************************************/ |
13 | ||
14 | package org.eclipse.linuxtools.lttng.ui.views.statistics; | |
15 | ||
dfaf8391 FC |
16 | import java.text.DecimalFormat; |
17 | import java.util.Arrays; | |
3037adf3 | 18 | import java.util.Collections; |
dfaf8391 | 19 | import java.util.HashSet; |
3037adf3 FC |
20 | import java.util.Iterator; |
21 | import java.util.LinkedList; | |
dfaf8391 FC |
22 | import java.util.Set; |
23 | ||
24 | import org.eclipse.jface.viewers.ColumnLabelProvider; | |
25 | import org.eclipse.jface.viewers.ITreeContentProvider; | |
26 | import org.eclipse.jface.viewers.TreeViewer; | |
27 | import org.eclipse.jface.viewers.TreeViewerColumn; | |
28 | import org.eclipse.jface.viewers.Viewer; | |
29 | import org.eclipse.jface.viewers.ViewerComparator; | |
6c13869b FC |
30 | import org.eclipse.linuxtools.lttng.core.control.LttngCoreProviderFactory; |
31 | import org.eclipse.linuxtools.lttng.core.event.LttngEvent; | |
32 | import org.eclipse.linuxtools.lttng.core.model.LTTngTreeNode; | |
33 | import org.eclipse.linuxtools.lttng.core.request.ILttngSyntEventRequest; | |
34 | import org.eclipse.linuxtools.lttng.core.state.evProcessor.AbsEventToHandlerResolver; | |
35 | import org.eclipse.linuxtools.lttng.core.state.experiment.StateManagerFactory; | |
8827c197 FC |
36 | import org.eclipse.linuxtools.lttng.ui.TraceDebug; |
37 | import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer; | |
38 | import org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView; | |
39 | import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater; | |
dfaf8391 | 40 | import org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor.StatsTimeCountHandlerFactory; |
b12f4544 | 41 | import org.eclipse.linuxtools.lttng.ui.views.statistics.model.KernelStatisticsData; |
dfaf8391 | 42 | import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeNode; |
8827c197 | 43 | import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeRootFactory; |
6c13869b FC |
44 | import org.eclipse.linuxtools.tmf.core.event.TmfEvent; |
45 | import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; | |
46 | import org.eclipse.linuxtools.tmf.core.experiment.TmfExperiment; | |
47 | import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest.ExecutionType; | |
48 | import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal; | |
49 | import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal; | |
50 | import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; | |
51 | import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; | |
8827c197 | 52 | import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; |
dfaf8391 FC |
53 | import org.eclipse.swt.SWT; |
54 | import org.eclipse.swt.events.SelectionAdapter; | |
55 | import org.eclipse.swt.events.SelectionEvent; | |
56 | import org.eclipse.swt.graphics.Color; | |
8827c197 | 57 | import org.eclipse.swt.graphics.Cursor; |
dfaf8391 FC |
58 | import org.eclipse.swt.graphics.Image; |
59 | import org.eclipse.swt.layout.FillLayout; | |
6e512b93 | 60 | import org.eclipse.swt.widgets.Composite; |
8827c197 | 61 | import org.eclipse.swt.widgets.Display; |
dfaf8391 FC |
62 | import org.eclipse.swt.widgets.Event; |
63 | import org.eclipse.swt.widgets.Listener; | |
64 | import org.eclipse.ui.ISharedImages; | |
65 | import org.eclipse.ui.PlatformUI; | |
6e512b93 ASL |
66 | |
67 | /** | |
68 | * <b><u>StatisticsView</u></b> | |
69 | * <p> | |
dfaf8391 FC |
70 | * The Statistics View displays statistics for traces. |
71 | * | |
72 | * It is implemented according to the MVC pattern. - The model is a | |
73 | * StatisticsTreeNode built by the State Manager. - The view is built with a | |
74 | * TreeViewer. - The controller that keeps model and view synchronised is an | |
75 | * observer of the model. | |
6e512b93 | 76 | */ |
8827c197 | 77 | public class StatisticsView extends AbsTimeUpdateView { |
3b38ea61 | 78 | public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.statistics"; //$NON-NLS-1$ |
dfaf8391 FC |
79 | private TreeViewer treeViewer; |
80 | ||
81 | // Table column names | |
a2e53983 FC |
82 | private final String LEVEL_COLUMN = Messages.StatisticsView_LevelColumn; |
83 | private final String EVENTS_COUNT_COLUMN = Messages.StatisticsView_NbEventsColumn; | |
84 | private final String CPU_TIME_COLUMN = Messages.StatisticsView_CPUTimeColumn; | |
85 | private final String CUMULATIVE_CPU_TIME_COLUMN = Messages.StatisticsView_CumCPUTimeColumn; | |
86 | private final String ELAPSED_TIME_COLUMN = Messages.StatisticsView_ElapsedTimeColumn; | |
dfaf8391 FC |
87 | |
88 | // Table column tooltips | |
a2e53983 FC |
89 | private final String LEVEL_COLUMN_TIP = Messages.StatisticsView_LevelColumnTip; |
90 | private final String EVENTS_COUNT_COLUMN_TIP = Messages.StatisticsView_NbEventsTip; | |
91 | private final String CPU_TIME_COLUMN_TIP = Messages.StatisticsView_CPUTimeTip; | |
92 | private final String CUMULATIVE_CPU_TIME_COLUMN_TIP = Messages.StatisticsView_CumCPUTimeTip; | |
93 | private final String ELAPSED_TIME_COLUMN_TIP = Messages.StatisticsView_ElapsedTimeTip; | |
6e512b93 | 94 | |
dfaf8391 | 95 | // Level for which statistics should not be displayed. |
b12f4544 FC |
96 | private Set<Integer> folderLevels = new HashSet<Integer>(Arrays |
97 | .asList(new Integer[] { KernelStatisticsData.HEADER_CPUS_INT, | |
98 | KernelStatisticsData.HEADER_EVENT_TYPES_INT, | |
99 | KernelStatisticsData.HEADER_FUNCTIONS_INT, | |
100 | KernelStatisticsData.HEADER_MODES_INT, | |
101 | KernelStatisticsData.HEADER_PROCESSES_INT, | |
102 | KernelStatisticsData.HEADER_SUBMODES_INT })); | |
6e512b93 | 103 | |
dfaf8391 | 104 | // Levels for which sub-levels should not contain time-related statistics. |
b12f4544 FC |
105 | private Set<Integer> levelsWithEmptyTime = new HashSet<Integer>(Arrays |
106 | .asList(new Integer[] { KernelStatisticsData.HEADER_EVENT_TYPES_INT })); | |
dfaf8391 | 107 | |
a2e53983 | 108 | private DecimalFormat decimalFormat = new DecimalFormat("0.#########"); //$NON-NLS-1$ |
b12f4544 | 109 | |
8827c197 | 110 | private Cursor fwaitCursor = null; |
dfaf8391 | 111 | |
c1c69938 FC |
112 | private static final Long STATS_INPUT_CHANGED_REFRESH = 5000L; |
113 | ||
dfaf8391 FC |
114 | // Used to draw bar charts in columns. |
115 | private interface ColumnPercentageProvider { | |
116 | public double getPercentage(StatisticsTreeNode node); | |
117 | } | |
118 | ||
a79913eb FC |
119 | private boolean fStatisticsUpdateBusy = false; |
120 | private boolean fStatisticsUpdatePending = false; | |
121 | private TmfTimeRange fStatisticsUpdateRange = null; | |
122 | private final Object fStatisticsUpdateSyncObj = new Object(); | |
123 | ||
dfaf8391 FC |
124 | /** |
125 | * Contains all the information necessary to build a column of the table. | |
126 | */ | |
127 | private class ColumnData { | |
128 | // Name of the column. | |
129 | public final String header; | |
130 | // Width of the column. | |
131 | public final int width; | |
132 | // Alignment of the column. | |
133 | public final int alignment; | |
134 | // Tooltip of the column. | |
135 | public final String tooltip; | |
136 | // Adapts a StatisticsTreeNode into the content of it's corresponding | |
137 | // cell for that column. | |
138 | public final ColumnLabelProvider labelProvider; | |
139 | // Used to sort elements of this column. Can be null. | |
140 | public final ViewerComparator comparator; | |
141 | // Used to draw bar charts in this column. Can be null. | |
142 | public final ColumnPercentageProvider percentageProvider; | |
143 | ||
144 | public ColumnData(String h, int w, int a, String t, | |
145 | ColumnLabelProvider l, ViewerComparator c, | |
146 | ColumnPercentageProvider p) { | |
147 | header = h; | |
148 | width = w; | |
149 | alignment = a; | |
150 | tooltip = t; | |
151 | labelProvider = l; | |
152 | comparator = c; | |
153 | percentageProvider = p; | |
154 | } | |
155 | }; | |
156 | ||
157 | // List that will be used to create the table. | |
158 | private ColumnData[] columnDataList = new ColumnData[] { | |
159 | new ColumnData(LEVEL_COLUMN, 200, SWT.LEFT, LEVEL_COLUMN_TIP, | |
160 | new ColumnLabelProvider() { | |
161 | @Override | |
162 | public String getText(Object element) { | |
b12f4544 FC |
163 | StatisticsTreeNode node = (StatisticsTreeNode) element; |
164 | if (folderLevels.contains(node.getKey())) { | |
165 | return (KernelStatisticsData.getCategoryFromId(node.getKey().intValue())); | |
166 | } else { | |
167 | return node.getName(); | |
168 | } | |
dfaf8391 FC |
169 | } |
170 | ||
171 | @Override | |
172 | public Image getImage(Object element) { | |
173 | StatisticsTreeNode node = (StatisticsTreeNode) element; | |
174 | if (folderLevels.contains(node.getKey())) { | |
175 | return PlatformUI.getWorkbench() | |
176 | .getSharedImages().getImage( | |
177 | ISharedImages.IMG_OBJ_FOLDER); | |
178 | } else { | |
179 | return PlatformUI.getWorkbench() | |
180 | .getSharedImages().getImage( | |
181 | ISharedImages.IMG_OBJ_ELEMENT); | |
182 | } | |
183 | } | |
184 | }, new ViewerComparator() { | |
185 | @Override | |
186 | public int compare(Viewer viewer, Object e1, Object e2) { | |
187 | StatisticsTreeNode n1 = (StatisticsTreeNode) e1; | |
188 | StatisticsTreeNode n2 = (StatisticsTreeNode) e2; | |
b12f4544 FC |
189 | |
190 | // return n1.getKey().compareTo(n2.getKey()); | |
191 | return n1.compareTo(n2); | |
dfaf8391 FC |
192 | } |
193 | }, null), | |
194 | new ColumnData(EVENTS_COUNT_COLUMN, 125, SWT.LEFT, | |
195 | EVENTS_COUNT_COLUMN_TIP, new ColumnLabelProvider() { | |
196 | @Override | |
197 | public String getText(Object element) { | |
198 | StatisticsTreeNode node = (StatisticsTreeNode) element; | |
199 | if (!folderLevels.contains(node.getKey())) { | |
200 | return Long.toString(node.getValue().nbEvents); | |
201 | } else { | |
3b38ea61 | 202 | return ""; //$NON-NLS-1$ |
dfaf8391 FC |
203 | } |
204 | } | |
205 | }, new ViewerComparator() { | |
206 | @Override | |
207 | public int compare(Viewer viewer, Object e1, Object e2) { | |
208 | StatisticsTreeNode n1 = (StatisticsTreeNode) e1; | |
209 | StatisticsTreeNode n2 = (StatisticsTreeNode) e2; | |
210 | ||
211 | return (int) (n1.getValue().nbEvents - n2 | |
212 | .getValue().nbEvents); | |
213 | } | |
214 | }, new ColumnPercentageProvider() { | |
d4011df2 | 215 | @Override |
dfaf8391 FC |
216 | public double getPercentage(StatisticsTreeNode node) { |
217 | StatisticsTreeNode parent = node; | |
218 | do { | |
219 | parent = parent.getParent(); | |
220 | } while (parent != null | |
221 | && parent.getValue().nbEvents == 0); | |
222 | ||
223 | if (parent == null) { | |
224 | return 0; | |
225 | } else { | |
226 | return (double) node.getValue().nbEvents | |
227 | / parent.getValue().nbEvents; | |
228 | } | |
229 | } | |
230 | }), | |
231 | new ColumnData(CPU_TIME_COLUMN, 125, SWT.LEFT, CPU_TIME_COLUMN_TIP, | |
232 | new ColumnLabelProvider() { | |
233 | @Override | |
234 | public String getText(Object element) { | |
235 | StatisticsTreeNode node = (StatisticsTreeNode) element; | |
236 | ||
237 | if (folderLevels.contains(node.getKey())) { | |
3b38ea61 | 238 | return ""; //$NON-NLS-1$ |
dfaf8391 FC |
239 | } else if (node.getParent() != null |
240 | && levelsWithEmptyTime.contains(node | |
241 | .getParent().getKey())) { | |
3b38ea61 | 242 | return ""; //$NON-NLS-1$ |
dfaf8391 FC |
243 | } else { |
244 | return decimalFormat | |
245 | .format(node.getValue().cpuTime | |
246 | / Math.pow(10, 9)); | |
247 | } | |
248 | } | |
249 | }, null, null), | |
250 | new ColumnData(CUMULATIVE_CPU_TIME_COLUMN, 155, SWT.LEFT, | |
251 | CUMULATIVE_CPU_TIME_COLUMN_TIP, new ColumnLabelProvider() { | |
252 | @Override | |
253 | public String getText(Object element) { | |
254 | StatisticsTreeNode node = (StatisticsTreeNode) element; | |
255 | if (folderLevels.contains(node.getKey())) { | |
3b38ea61 | 256 | return ""; //$NON-NLS-1$ |
dfaf8391 FC |
257 | } else if (node.getParent() != null |
258 | && levelsWithEmptyTime.contains(node | |
259 | .getParent().getKey())) { | |
3b38ea61 | 260 | return ""; //$NON-NLS-1$ |
dfaf8391 FC |
261 | } else { |
262 | return decimalFormat | |
263 | .format(node.getValue().cumulativeCpuTime | |
264 | / Math.pow(10, 9)); | |
265 | } | |
266 | } | |
267 | }, null, null), | |
268 | new ColumnData(ELAPSED_TIME_COLUMN, 100, SWT.LEFT, | |
269 | ELAPSED_TIME_COLUMN_TIP, new ColumnLabelProvider() { | |
270 | @Override | |
271 | public String getText(Object element) { | |
272 | StatisticsTreeNode node = (StatisticsTreeNode) element; | |
273 | if (folderLevels.contains(node.getKey())) { | |
3b38ea61 | 274 | return ""; //$NON-NLS-1$ |
dfaf8391 FC |
275 | } else if (node.getParent() != null |
276 | && levelsWithEmptyTime.contains(node | |
277 | .getParent().getKey())) { | |
3b38ea61 | 278 | return ""; //$NON-NLS-1$ |
dfaf8391 FC |
279 | } else { |
280 | return decimalFormat | |
281 | .format(node.getValue().elapsedTime | |
282 | / Math.pow(10, 9)); | |
283 | } | |
284 | } | |
285 | }, null, null) }; | |
286 | ||
287 | /** | |
288 | * Adapter TreeViewers can use to interact with StatisticsTreeNode objects. | |
6e512b93 | 289 | * |
dfaf8391 | 290 | * @see org.eclipse.jface.viewers.ITreeContentProvider |
6e512b93 | 291 | */ |
dfaf8391 FC |
292 | class TreeContentProvider implements ITreeContentProvider { |
293 | /* | |
294 | * (non-Javadoc) | |
295 | * | |
296 | * @see | |
297 | * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang | |
298 | * .Object) | |
299 | */ | |
d4011df2 | 300 | @Override |
dfaf8391 FC |
301 | public Object[] getChildren(Object parentElement) { |
302 | return ((StatisticsTreeNode) parentElement).getChildren().toArray(); | |
303 | } | |
304 | ||
305 | /* | |
306 | * (non-Javadoc) | |
307 | * | |
308 | * @see | |
309 | * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang | |
310 | * .Object) | |
311 | */ | |
d4011df2 | 312 | @Override |
dfaf8391 FC |
313 | public Object getParent(Object element) { |
314 | return ((StatisticsTreeNode) element).getParent(); | |
315 | } | |
316 | ||
317 | /* | |
318 | * (non-Javadoc) | |
319 | * | |
320 | * @see | |
321 | * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang | |
322 | * .Object) | |
323 | */ | |
d4011df2 | 324 | @Override |
dfaf8391 FC |
325 | public boolean hasChildren(Object element) { |
326 | return ((StatisticsTreeNode) element).hasChildren(); | |
327 | } | |
328 | ||
329 | /* | |
330 | * (non-Javadoc) | |
331 | * | |
332 | * @see | |
333 | * org.eclipse.jface.viewers.IStructuredContentProvider#getElements( | |
334 | * java.lang.Object) | |
335 | */ | |
d4011df2 | 336 | @Override |
dfaf8391 FC |
337 | public Object[] getElements(Object inputElement) { |
338 | return getChildren(inputElement); | |
339 | } | |
340 | ||
341 | /* | |
342 | * (non-Javadoc) | |
343 | * | |
344 | * @see org.eclipse.jface.viewers.IContentProvider#dispose() | |
345 | */ | |
d4011df2 | 346 | @Override |
dfaf8391 FC |
347 | public void dispose() { |
348 | } | |
349 | ||
350 | /* | |
351 | * (non-Javadoc) | |
352 | * | |
353 | * @see | |
354 | * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse | |
355 | * .jface.viewers.Viewer, java.lang.Object, java.lang.Object) | |
356 | */ | |
357 | // @Override | |
d4011df2 | 358 | @Override |
dfaf8391 FC |
359 | public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { |
360 | } | |
6e512b93 ASL |
361 | } |
362 | ||
fc6ccf6f | 363 | public StatisticsView(String viewName) { |
951d134a FC |
364 | super(viewName); |
365 | } | |
366 | ||
3b38ea61 | 367 | private static final String STATISTICS_VIEW = "StatisticsView"; //$NON-NLS-1$ |
951d134a | 368 | public StatisticsView() { |
3b38ea61 | 369 | this(STATISTICS_VIEW); |
fc6ccf6f FC |
370 | } |
371 | ||
dfaf8391 FC |
372 | /* |
373 | * (non-Javadoc) | |
374 | * | |
375 | * @see | |
376 | * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets | |
377 | * .Composite) | |
6e512b93 ASL |
378 | */ |
379 | @Override | |
380 | public void createPartControl(Composite parent) { | |
dfaf8391 FC |
381 | parent.setLayout(new FillLayout()); |
382 | ||
383 | treeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | |
384 | | SWT.V_SCROLL); | |
385 | treeViewer.setContentProvider(new TreeContentProvider()); | |
386 | treeViewer.getTree().setHeaderVisible(true); | |
387 | treeViewer.setUseHashlookup(true); | |
388 | ||
389 | for (final ColumnData columnData : columnDataList) { | |
390 | final TreeViewerColumn treeColumn = new TreeViewerColumn( | |
391 | treeViewer, columnData.alignment); | |
392 | treeColumn.getColumn().setText(columnData.header); | |
393 | treeColumn.getColumn().setWidth(columnData.width); | |
394 | treeColumn.getColumn().setToolTipText(columnData.tooltip); | |
395 | if (columnData.comparator != null) { | |
396 | treeColumn.getColumn().addSelectionListener( | |
397 | new SelectionAdapter() { | |
398 | @Override | |
399 | public void widgetSelected(SelectionEvent e) { | |
400 | if (treeViewer.getTree().getSortDirection() == SWT.UP | |
401 | || treeViewer.getTree().getSortColumn() != treeColumn | |
402 | .getColumn()) { | |
403 | treeViewer | |
404 | .setComparator(columnData.comparator); | |
405 | treeViewer.getTree().setSortDirection( | |
406 | SWT.DOWN); | |
407 | } else { | |
408 | treeViewer | |
409 | .setComparator(new ViewerComparator() { | |
410 | @Override | |
411 | public int compare( | |
412 | Viewer viewer, | |
413 | Object e1, Object e2) { | |
414 | return -1 | |
415 | * columnData.comparator | |
416 | .compare( | |
417 | viewer, | |
418 | e1, | |
419 | e2); | |
420 | } | |
421 | }); | |
422 | treeViewer.getTree().setSortDirection( | |
423 | SWT.UP); | |
424 | } | |
425 | treeViewer.getTree().setSortColumn( | |
426 | treeColumn.getColumn()); | |
427 | } | |
428 | }); | |
429 | } | |
430 | treeColumn.setLabelProvider(columnData.labelProvider); | |
431 | } | |
432 | ||
433 | // Handler that will draw the bar charts. | |
434 | treeViewer.getTree().addListener(SWT.EraseItem, new Listener() { | |
435 | // @Override | |
d4011df2 | 436 | @Override |
dfaf8391 FC |
437 | public void handleEvent(Event event) { |
438 | if (columnDataList[event.index].percentageProvider != null) { | |
439 | StatisticsTreeNode node = (StatisticsTreeNode) event.item | |
440 | .getData(); | |
441 | ||
442 | double percentage = columnDataList[event.index].percentageProvider | |
443 | .getPercentage(node); | |
444 | if (percentage == 0) { | |
445 | return; | |
446 | } | |
447 | ||
448 | if ((event.detail & SWT.SELECTED) > 0) { | |
449 | Color oldForeground = event.gc.getForeground(); | |
450 | event.gc.setForeground(event.item.getDisplay() | |
451 | .getSystemColor(SWT.COLOR_LIST_SELECTION)); | |
452 | event.gc.fillRectangle(event.x, event.y, event.width, | |
453 | event.height); | |
454 | event.gc.setForeground(oldForeground); | |
455 | event.detail &= ~SWT.SELECTED; | |
456 | } | |
457 | ||
458 | int barWidth = (int) ((treeViewer.getTree().getColumn(1) | |
459 | .getWidth() - 8) * percentage); | |
460 | int oldAlpha = event.gc.getAlpha(); | |
461 | Color oldForeground = event.gc.getForeground(); | |
462 | Color oldBackground = event.gc.getBackground(); | |
463 | event.gc.setAlpha(64); | |
464 | event.gc.setForeground(event.item.getDisplay() | |
465 | .getSystemColor(SWT.COLOR_BLUE)); | |
466 | event.gc.setBackground(event.item.getDisplay() | |
467 | .getSystemColor(SWT.COLOR_LIST_BACKGROUND)); | |
468 | event.gc.fillGradientRectangle(event.x, event.y, barWidth, | |
469 | event.height, true); | |
470 | event.gc.drawRectangle(event.x, event.y, barWidth, | |
471 | event.height); | |
472 | event.gc.setForeground(oldForeground); | |
473 | event.gc.setBackground(oldBackground); | |
474 | event.gc.setAlpha(oldAlpha); | |
475 | event.detail &= ~SWT.BACKGROUND; | |
476 | } | |
477 | } | |
478 | }); | |
479 | ||
480 | treeViewer.setComparator(columnDataList[0].comparator); | |
481 | treeViewer.getTree().setSortColumn(treeViewer.getTree().getColumn(0)); | |
482 | treeViewer.getTree().setSortDirection(SWT.DOWN); | |
483 | ||
dfaf8391 | 484 | // Read current data if any available |
8827c197 FC |
485 | TmfExperiment<?> experiment = TmfExperiment.getCurrentExperiment(); |
486 | if (experiment != null) { | |
a79913eb FC |
487 | |
488 | @SuppressWarnings({ "rawtypes", "unchecked" }) | |
489 | TmfExperimentSelectedSignal<?> signal = new TmfExperimentSelectedSignal(this, experiment); | |
490 | experimentSelected(signal); | |
491 | ||
8827c197 | 492 | } else { |
3b38ea61 | 493 | TraceDebug.debug("No selected experiment information available"); //$NON-NLS-1$ |
8827c197 | 494 | } |
dfaf8391 | 495 | } |
8827c197 | 496 | |
dfaf8391 FC |
497 | @Override |
498 | public void dispose() { | |
499 | super.dispose(); | |
8827c197 FC |
500 | if (fwaitCursor != null) { |
501 | fwaitCursor.dispose(); | |
502 | } | |
6e512b93 | 503 | |
8827c197 FC |
504 | // clean the model |
505 | StatisticsTreeRootFactory.removeAll(); | |
6e512b93 ASL |
506 | } |
507 | ||
dfaf8391 FC |
508 | /* |
509 | * (non-Javadoc) | |
510 | * | |
6e512b93 ASL |
511 | * @see org.eclipse.ui.part.WorkbenchPart#setFocus() |
512 | */ | |
513 | @Override | |
514 | public void setFocus() { | |
dfaf8391 FC |
515 | treeViewer.getTree().setFocus(); |
516 | } | |
517 | ||
c1c69938 FC |
518 | |
519 | /* | |
520 | * (non-Javadoc) | |
521 | * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#getInputChangedRefresh() | |
522 | */ | |
523 | @Override | |
524 | protected Long getInputChangedRefresh() { | |
525 | return STATS_INPUT_CHANGED_REFRESH; | |
526 | } | |
6e512b93 | 527 | |
8827c197 FC |
528 | /** |
529 | * @return | |
530 | */ | |
550d787e | 531 | @Override |
8827c197 FC |
532 | public AbsEventToHandlerResolver getEventProcessor() { |
533 | return StatsTimeCountHandlerFactory.getInstance(); | |
6e512b93 ASL |
534 | } |
535 | ||
8827c197 FC |
536 | /* |
537 | * (non-Javadoc) | |
538 | * | |
539 | * @see | |
540 | * org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#waitCursor | |
541 | * (boolean) | |
542 | */ | |
550d787e | 543 | @Override |
8827c197 | 544 | protected void waitCursor(final boolean waitInd) { |
db1ea19b | 545 | if ((treeViewer == null) || (treeViewer.getTree().isDisposed())) { |
8827c197 FC |
546 | return; |
547 | } | |
548 | ||
549 | Display display = treeViewer.getControl().getDisplay(); | |
550 | if (fwaitCursor == null) { | |
551 | fwaitCursor = new Cursor(display, SWT.CURSOR_WAIT); | |
552 | } | |
553 | ||
554 | // Perform the updates on the UI thread | |
555 | display.asyncExec(new Runnable() { | |
d4011df2 | 556 | @Override |
8827c197 | 557 | public void run() { |
db1ea19b FC |
558 | if ((treeViewer != null) && (!treeViewer.getTree().isDisposed())) { |
559 | Cursor cursor = null; /* indicates default */ | |
560 | if (waitInd) { | |
561 | cursor = fwaitCursor; | |
562 | } | |
563 | treeViewer.getControl().setCursor(cursor); | |
8827c197 | 564 | } |
8827c197 FC |
565 | } |
566 | }); | |
567 | } | |
568 | ||
569 | @Override | |
570 | public void ModelUpdatePrep(TmfTimeRange timeRange, boolean clearAllData) { | |
571 | Object input = treeViewer.getInput(); | |
db1ea19b | 572 | if ((input != null) && (input instanceof StatisticsTreeNode) && (!treeViewer.getTree().isDisposed())) { |
a79913eb FC |
573 | if (clearAllData) { |
574 | ((StatisticsTreeNode) input).reset(); | |
575 | } | |
8827c197 FC |
576 | treeViewer.getTree().getDisplay().asyncExec(new Runnable() { |
577 | // @Override | |
d4011df2 | 578 | @Override |
8827c197 | 579 | public void run() { |
db1ea19b FC |
580 | if (!treeViewer.getTree().isDisposed()) |
581 | treeViewer.refresh(); | |
8827c197 FC |
582 | } |
583 | }); | |
584 | } | |
585 | } | |
586 | ||
587 | @Override | |
588 | public void modelInputChanged(ILttngSyntEventRequest request, boolean complete) { | |
db1ea19b FC |
589 | // Ignore update if disposed |
590 | if (treeViewer.getTree().isDisposed()) return; | |
b12f4544 | 591 | |
3037adf3 FC |
592 | if(TraceDebug.isSV() && complete) { |
593 | // print results | |
594 | ||
595 | TmfExperiment<?> experiment = TmfExperiment.getCurrentExperiment(); | |
596 | if(experiment != null) { | |
597 | StatisticsTreeNode node = StatisticsTreeRootFactory.getStatTreeRoot(experiment.getName()); | |
598 | printRecursively(node); | |
599 | ||
b12f4544 | 600 | } |
3037adf3 | 601 | } |
db1ea19b | 602 | |
dfaf8391 FC |
603 | treeViewer.getTree().getDisplay().asyncExec(new Runnable() { |
604 | // @Override | |
d4011df2 | 605 | @Override |
dfaf8391 | 606 | public void run() { |
db1ea19b FC |
607 | if (!treeViewer.getTree().isDisposed()) |
608 | treeViewer.refresh(); | |
dfaf8391 FC |
609 | } |
610 | }); | |
a79913eb FC |
611 | |
612 | if (complete) { | |
613 | synchronized (fStatisticsUpdateSyncObj) { | |
614 | fStatisticsUpdateBusy = false; | |
615 | if (fStatisticsUpdatePending) { | |
616 | fStatisticsUpdatePending = false; | |
617 | requestData(TmfExperiment.getCurrentExperiment(), fStatisticsUpdateRange, false); | |
618 | } | |
619 | } | |
db1ea19b | 620 | } |
b12f4544 | 621 | |
a79913eb FC |
622 | } |
623 | ||
3037adf3 | 624 | private static int level = 0; |
b12f4544 FC |
625 | private void printRecursively(StatisticsTreeNode node) { |
626 | String tab = ""; //$NON-NLS-1$ | |
627 | for (int i = 0; i < level; i++) { | |
3037adf3 FC |
628 | tab += "\t"; //$NON-NLS-1$ |
629 | } | |
b12f4544 | 630 | level++; |
3037adf3 FC |
631 | TraceDebug.traceSV(tab + node.getContent()); |
632 | if (node.hasChildren()) { | |
633 | LinkedList<StatisticsTreeNode> childreen = (LinkedList<StatisticsTreeNode>)node.getChildren(); | |
634 | Collections.sort(childreen); | |
b12f4544 | 635 | |
3037adf3 FC |
636 | for (Iterator<StatisticsTreeNode> iterator = childreen.iterator(); iterator.hasNext();) { |
637 | StatisticsTreeNode statisticsTreeNode = (StatisticsTreeNode) iterator.next(); | |
638 | printRecursively(statisticsTreeNode); | |
639 | } | |
640 | } | |
641 | level--; | |
642 | } | |
8827c197 FC |
643 | |
644 | /* | |
645 | * (non-Javadoc) | |
646 | * | |
647 | * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# | |
648 | * modelIncomplete | |
649 | * (org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest) | |
650 | */ | |
651 | @Override | |
652 | public void modelIncomplete(ILttngSyntEventRequest request) { | |
653 | Object input = treeViewer.getInput(); | |
654 | if (input != null && input instanceof StatisticsTreeNode) { | |
655 | // The data from this experiment is invalid and shall be removed to | |
656 | // refresh upon next selection | |
c1c69938 | 657 | String name = request.getExperimentName(); |
8827c197 FC |
658 | StatisticsTreeRootFactory.removeStatTreeRoot(name); |
659 | } | |
660 | } | |
661 | ||
662 | /** | |
663 | * @param signal | |
664 | */ | |
665 | @TmfSignalHandler | |
666 | public void experimentSelected(TmfExperimentSelectedSignal<? extends TmfEvent> signal) { | |
667 | if (signal != null) { | |
668 | TmfExperiment<?> experiment = signal.getExperiment(); | |
669 | String experimentName = experiment.getName(); | |
670 | ||
671 | if (StatisticsTreeRootFactory.containsTreeRoot(experimentName)) { | |
672 | // The experiment root is already present | |
673 | StatisticsTreeNode experimentTreeNode = StatisticsTreeRootFactory.getStatTreeRoot(experimentName); | |
674 | ||
675 | ITmfTrace[] traces = experiment.getTraces(); | |
b12f4544 FC |
676 | |
677 | LTTngTreeNode expNode = StateManagerFactory.getExperimentManager().getSelectedExperiment(); | |
678 | ||
8827c197 FC |
679 | // check if there is partial data loaded in the experiment |
680 | int numTraces = experiment.getTraces().length; | |
681 | int numNodeTraces = experimentTreeNode.getNbChildren(); | |
682 | ||
683 | if (numTraces == numNodeTraces) { | |
684 | boolean same = true; | |
685 | // Detect if the experiment contains the same traces as when | |
686 | // previously selected | |
687 | for (int i = 0; i < numTraces; i++) { | |
688 | String traceName = traces[i].getName(); | |
b12f4544 FC |
689 | LTTngTreeNode child = expNode.getChildByName(traceName); |
690 | if ((child == null) || (!experimentTreeNode.containsChild(child.getId().intValue()))) { | |
9b635e61 FC |
691 | same = false; |
692 | break; | |
8827c197 FC |
693 | } |
694 | } | |
695 | ||
696 | if (same) { | |
697 | // no need to reload data, all traces are already loaded | |
698 | treeViewer.setInput(experimentTreeNode); | |
a79913eb FC |
699 | synchronized (fStatisticsUpdateSyncObj) { |
700 | fStatisticsUpdateBusy = false; | |
701 | fStatisticsUpdatePending = false; | |
702 | } | |
8827c197 FC |
703 | return; |
704 | } | |
705 | } | |
706 | } | |
707 | ||
a79913eb FC |
708 | StatisticsTreeNode treeModelRoot = StatisticsTreeRootFactory.getStatTreeRoot(experiment.getName()); |
709 | ||
710 | // if the model has contents, clear to start over | |
711 | if (treeModelRoot.hasChildren()) { | |
712 | treeModelRoot.reset(); | |
713 | } | |
714 | ||
715 | // set input to a clean data model | |
716 | treeViewer.setInput(treeModelRoot); | |
717 | ||
718 | synchronized (fStatisticsUpdateSyncObj) { | |
719 | fStatisticsUpdateBusy = false; | |
720 | fStatisticsUpdatePending = false; | |
721 | } | |
722 | ||
8827c197 | 723 | // if the data is not available or has changed, reload it |
a79913eb FC |
724 | requestData(experiment, experiment.getTimeRange(), true); |
725 | } | |
726 | } | |
727 | ||
728 | /** | |
729 | * @param signal | |
730 | */ | |
731 | @SuppressWarnings("unchecked") | |
732 | @TmfSignalHandler | |
733 | public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) { | |
734 | TmfExperiment<LttngEvent> experiment = (TmfExperiment<LttngEvent>) signal.getExperiment(); | |
735 | // validate | |
736 | if (! experiment.equals(TmfExperiment.getCurrentExperiment())) { | |
737 | return; | |
8827c197 | 738 | } |
a79913eb FC |
739 | |
740 | requestData(experiment, signal.getRange(), false); | |
8827c197 FC |
741 | } |
742 | ||
743 | /** | |
744 | * @param experiment | |
745 | */ | |
a79913eb | 746 | private void requestData(TmfExperiment<?> experiment, TmfTimeRange range, boolean clearingData) { |
8827c197 | 747 | if (experiment != null) { |
a79913eb FC |
748 | synchronized (fStatisticsUpdateSyncObj) { |
749 | if (fStatisticsUpdateBusy) { | |
750 | fStatisticsUpdatePending = true; | |
751 | fStatisticsUpdateRange = range; | |
752 | return; | |
753 | } else { | |
754 | fStatisticsUpdateBusy = true; | |
755 | } | |
8827c197 FC |
756 | } |
757 | ||
a79913eb FC |
758 | int index = 0; |
759 | for (StatisticsTreeNode node : ((StatisticsTreeNode) treeViewer.getInput()).getChildren()) { | |
760 | index += (int) node.getValue().nbEvents; | |
761 | } | |
8827c197 FC |
762 | |
763 | // send the initial request, to start filling up model | |
a79913eb FC |
764 | //eventRequest(fStatisticsUpdateIndex, nbRequested, fStatisticsUpdateStartTime, clearingData, ExecutionType.BACKGROUND); |
765 | eventRequest(index, range, clearingData, ExecutionType.BACKGROUND); | |
8827c197 | 766 | } else { |
3b38ea61 | 767 | TraceDebug.debug("No selected experiment information available"); //$NON-NLS-1$ |
8827c197 FC |
768 | } |
769 | } | |
770 | ||
771 | /* | |
772 | * (non-Javadoc) | |
773 | * | |
774 | * @see | |
775 | * org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#displayModel | |
776 | * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model. | |
777 | * ITmfTimeAnalysisEntry[], long, long, boolean, long, long, | |
778 | * java.lang.Object) | |
779 | */ | |
780 | @Override | |
781 | protected void displayModel(ITmfTimeAnalysisEntry[] items, long startBoundTime, long endBoundTime, | |
782 | boolean updateTimeBounds, long startVisibleWindow, long endVisibleWindow, Object source) { | |
783 | // No applicable to statistics view | |
784 | } | |
785 | ||
786 | /* | |
787 | * (non-Javadoc) | |
788 | * | |
789 | * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# | |
790 | * getParamsUpdater() | |
791 | */ | |
792 | @Override | |
793 | protected ParamsUpdater getParamsUpdater() { | |
794 | // Not applicable to statistics view | |
795 | return null; | |
796 | } | |
797 | ||
798 | @Override | |
799 | protected ItemContainer<?> getItemContainer() { | |
800 | // Not applicable to statistics view | |
801 | return null; | |
802 | } | |
c1c69938 FC |
803 | |
804 | /* | |
805 | * (non-Javadoc) | |
806 | * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#getProviderId() | |
807 | */ | |
808 | @Override | |
809 | protected int getProviderId() { | |
810 | return LttngCoreProviderFactory.STATISTICS_LTTNG_SYTH_EVENT_PROVIDER; | |
811 | } | |
b12f4544 | 812 | } |