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