tmf: Fix integer overflow in time graph calculations
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.timing.ui / src / org / eclipse / tracecompass / internal / analysis / timing / ui / flamegraph / FlameGraphView.java
CommitLineData
74ccf789
SF
1/*******************************************************************************
2 * Copyright (c) 2016 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * 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 * Author:
10 * Sonia Farrah
11 *******************************************************************************/
12package org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph;
13
14import org.eclipse.core.runtime.IProgressMonitor;
15import org.eclipse.core.runtime.IStatus;
16import org.eclipse.core.runtime.Status;
17import org.eclipse.core.runtime.jobs.Job;
f13aa9cd
MK
18import org.eclipse.jdt.annotation.NonNull;
19import org.eclipse.jface.action.Action;
20import org.eclipse.jface.action.GroupMarker;
e162d9ae 21import org.eclipse.jface.action.IAction;
f13aa9cd
MK
22import org.eclipse.jface.action.IMenuListener;
23import org.eclipse.jface.action.IMenuManager;
e162d9ae 24import org.eclipse.jface.action.IToolBarManager;
f13aa9cd 25import org.eclipse.jface.action.MenuManager;
e162d9ae
BH
26import org.eclipse.jface.action.Separator;
27import org.eclipse.jface.dialogs.IDialogSettings;
28import org.eclipse.jface.resource.ImageDescriptor;
f13aa9cd
MK
29import org.eclipse.jface.viewers.ISelection;
30import org.eclipse.jface.viewers.IStructuredSelection;
74ccf789 31import org.eclipse.swt.SWT;
f13aa9cd
MK
32import org.eclipse.swt.events.MenuDetectEvent;
33import org.eclipse.swt.events.MenuDetectListener;
74ccf789
SF
34import org.eclipse.swt.widgets.Composite;
35import org.eclipse.swt.widgets.Display;
f13aa9cd 36import org.eclipse.swt.widgets.Menu;
74ccf789 37import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.CallGraphAnalysis;
e162d9ae 38import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator;
74ccf789 39import org.eclipse.tracecompass.internal.analysis.timing.ui.callgraph.CallGraphAnalysisUI;
f13aa9cd
MK
40import org.eclipse.tracecompass.segmentstore.core.ISegment;
41import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
74ccf789
SF
42import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
43import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
44import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
45import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
f13aa9cd 46import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
74ccf789 47import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
74ccf789
SF
48import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
49import org.eclipse.tracecompass.tmf.ui.editors.ITmfTraceEditor;
50import org.eclipse.tracecompass.tmf.ui.views.TmfView;
51import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
52import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
f13aa9cd 53import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
e162d9ae 54import org.eclipse.ui.IActionBars;
74ccf789 55import org.eclipse.ui.IEditorPart;
f13aa9cd 56import org.eclipse.ui.IWorkbenchActionConstants;
74ccf789
SF
57
58/**
59 * View to display the flame graph .This uses the flameGraphNode tree generated
60 * by CallGraphAnalysisUI.
61 *
62 * @author Sonia Farrah
63 */
64public class FlameGraphView extends TmfView {
65
66 /**
67 *
68 */
69 public static final String ID = FlameGraphView.class.getPackage().getName() + ".flamegraphView"; //$NON-NLS-1$
70
e162d9ae
BH
71 private static final String SORT_OPTION_KEY = "sort.option"; //$NON-NLS-1$
72 private static final ImageDescriptor SORT_BY_NAME_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha.gif"); //$NON-NLS-1$
73 private static final ImageDescriptor SORT_BY_NAME_REV_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha_rev.gif"); //$NON-NLS-1$
74 private static final ImageDescriptor SORT_BY_ID_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_num.gif"); //$NON-NLS-1$
75 private static final ImageDescriptor SORT_BY_ID_REV_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_num_rev.gif"); //$NON-NLS-1$
76
77
74ccf789
SF
78 private TimeGraphViewer fTimeGraphViewer;
79
80 private FlameGraphContentProvider fTimeGraphContentProvider;
81
82 private TimeGraphPresentationProvider fPresentationProvider;
83
84 private ITmfTrace fTrace;
85
f13aa9cd 86 private final @NonNull MenuManager fEventMenuManager = new MenuManager();
e162d9ae
BH
87 private Action fSortByNameAction;
88 private Action fSortByIdAction;
f13aa9cd 89
74ccf789
SF
90 /**
91 * Constructor
92 */
93 public FlameGraphView() {
94 super(ID);
95 }
96
97 @Override
98 public void createPartControl(Composite parent) {
99 super.createPartControl(parent);
100 fTimeGraphViewer = new TimeGraphViewer(parent, SWT.NONE);
101 fTimeGraphContentProvider = new FlameGraphContentProvider();
102 fPresentationProvider = new FlameGraphPresentationProvider();
103 fTimeGraphViewer.setTimeGraphContentProvider(fTimeGraphContentProvider);
104 fTimeGraphViewer.setTimeGraphProvider(fPresentationProvider);
105 IEditorPart editor = getSite().getPage().getActiveEditor();
106 if (editor instanceof ITmfTraceEditor) {
107 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
108 if (trace != null) {
109 traceSelected(new TmfTraceSelectedSignal(this, trace));
110 }
111 }
e162d9ae
BH
112 contributeToActionBars();
113 loadSortOption();
114
f13aa9cd
MK
115 getSite().setSelectionProvider(fTimeGraphViewer.getSelectionProvider());
116 createTimeEventContextMenu();
74ccf789
SF
117 }
118
e162d9ae 119
74ccf789
SF
120 /**
121 * Handler for the trace opened signal
122 *
123 * @param signal
124 * The incoming signal
125 */
126 @TmfSignalHandler
127 public void TraceOpened(TmfTraceOpenedSignal signal) {
128 fTrace = signal.getTrace();
129 if (fTrace != null) {
130 CallGraphAnalysis flamegraphModule = TmfTraceUtils.getAnalysisModuleOfClass(fTrace, CallGraphAnalysis.class, CallGraphAnalysisUI.ID);
131 buildFlameGraph(flamegraphModule);
132 }
133 }
134
135 /**
136 * Handler for the trace selected signal
137 *
138 * @param signal
139 * The incoming signal
140 */
141 @TmfSignalHandler
142 public void traceSelected(final TmfTraceSelectedSignal signal) {
143 fTrace = signal.getTrace();
144 if (fTrace != null) {
145 CallGraphAnalysis flamegraphModule = TmfTraceUtils.getAnalysisModuleOfClass(fTrace, CallGraphAnalysis.class, CallGraphAnalysisUI.ID);
146 buildFlameGraph(flamegraphModule);
147 }
148 }
149
150 /**
151 * Get the necessary data for the flame graph and display it
152 *
153 * @param flamegraphModule
154 * the callGraphAnalysis
155 */
156 private void buildFlameGraph(CallGraphAnalysis callGraphAnalysis) {
157 fTimeGraphViewer.setInput(null);
158 callGraphAnalysis.schedule();
159 Job j = new Job(Messages.CallGraphAnalysis_Execution) {
160
161 @Override
162 protected IStatus run(IProgressMonitor monitor) {
163 if (monitor.isCanceled()) {
164 return Status.CANCEL_STATUS;
165 }
166 callGraphAnalysis.waitForCompletion(monitor);
167 Display.getDefault().asyncExec(() -> {
168 fTimeGraphViewer.setInput(callGraphAnalysis.getThreadNodes());
169 });
170 return Status.OK_STATUS;
171 }
172 };
173 j.schedule();
174 }
175
176 /**
177 * Trace is closed: clear the data structures and the view
178 *
179 * @param signal
180 * the signal received
181 */
182 @TmfSignalHandler
183 public void traceClosed(final TmfTraceClosedSignal signal) {
184 if (signal.getTrace() == fTrace) {
185 fTimeGraphViewer.setInput(null);
186 }
187 }
188
189 @Override
190 public void setFocus() {
191 fTimeGraphViewer.setFocus();
192 }
193
e162d9ae
BH
194 // ------------------------------------------------------------------------
195 // Helper methods
196 // ------------------------------------------------------------------------
197
f13aa9cd
MK
198 private void createTimeEventContextMenu() {
199 fEventMenuManager.setRemoveAllWhenShown(true);
200 TimeGraphControl timeGraphControl = fTimeGraphViewer.getTimeGraphControl();
201 final Menu timeEventMenu = fEventMenuManager.createContextMenu(timeGraphControl);
202
203 timeGraphControl.addTimeGraphEntryMenuListener(new MenuDetectListener() {
204 @Override
205 public void menuDetected(MenuDetectEvent event) {
206 /*
207 * The TimeGraphControl will call the TimeGraphEntryMenuListener
208 * before the TimeEventMenuListener. We need to clear the menu
209 * for the case the selection was done on the namespace where
210 * the time event listener below won't be called afterwards.
211 */
212 timeGraphControl.setMenu(null);
213 event.doit = false;
214 }
215 });
216 timeGraphControl.addTimeEventMenuListener(new MenuDetectListener() {
217 @Override
218 public void menuDetected(MenuDetectEvent event) {
219 Menu menu = timeEventMenu;
220 if (event.data instanceof FlamegraphEvent) {
221 timeGraphControl.setMenu(menu);
222 return;
223 }
224 timeGraphControl.setMenu(null);
225 event.doit = false;
226 }
227 });
228
229 fEventMenuManager.addMenuListener(new IMenuListener() {
230 @Override
231 public void menuAboutToShow(IMenuManager manager) {
232 fillTimeEventContextMenu(fEventMenuManager);
233 fEventMenuManager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
234 }
235 });
236 getSite().registerContextMenu(fEventMenuManager, fTimeGraphViewer.getSelectionProvider());
237 }
238
239 /**
240 * Fill context menu
241 *
242 * @param menuManager
243 * a menuManager to fill
244 */
245 protected void fillTimeEventContextMenu(@NonNull IMenuManager menuManager) {
246 ISelection selection = getSite().getSelectionProvider().getSelection();
247 if (selection instanceof IStructuredSelection) {
248 for (Object object : ((IStructuredSelection) selection).toList()) {
249 if (object instanceof FlamegraphEvent) {
250 final FlamegraphEvent flamegraphEvent = (FlamegraphEvent) object;
251 menuManager.add(new Action(Messages.FlameGraphView_GotoMaxDuration) {
252 @Override
253 public void run() {
254 ISegment maxSeg = flamegraphEvent.getStatistics().getMaxSegment();
255 TmfSelectionRangeUpdatedSignal sig = new TmfSelectionRangeUpdatedSignal(this, TmfTimestamp.fromNanos(maxSeg.getStart()), TmfTimestamp.fromNanos(maxSeg.getEnd()));
256 broadcast(sig);
257 }
258 });
259
260 menuManager.add(new Action(Messages.FlameGraphView_GotoMinDuration) {
261 @Override
262 public void run() {
263 ISegment minSeg = flamegraphEvent.getStatistics().getMinSegment();
264 TmfSelectionRangeUpdatedSignal sig = new TmfSelectionRangeUpdatedSignal(this, TmfTimestamp.fromNanos(minSeg.getStart()), TmfTimestamp.fromNanos(minSeg.getEnd()));
265 broadcast(sig);
266 }
267 });
268 }
269 }
270 }
271 }
e162d9ae
BH
272
273 private void contributeToActionBars() {
274 IActionBars bars = getViewSite().getActionBars();
275 fillLocalToolBar(bars.getToolBarManager());
276 }
277
278 private void fillLocalToolBar(IToolBarManager manager) {
279 manager.add(getSortByNameAction());
280 manager.add(getSortByIdAction());
281 manager.add(new Separator());
282 }
283
284 private Action getSortByNameAction() {
285 if (fSortByNameAction == null) {
286 fSortByNameAction = new Action(Messages.FlameGraph_SortByThreadName, IAction.AS_CHECK_BOX) {
287 @Override
288 public void run() {
289 SortOption sortOption = fTimeGraphContentProvider.getSortOption();
290 if (sortOption == SortOption.BY_NAME) {
291 setSortOption(SortOption.BY_NAME_REV);
292 } else {
293 setSortOption(SortOption.BY_NAME);
294 }
295 }
296 };
297 fSortByNameAction.setToolTipText(Messages.FlameGraph_SortByThreadName);
298 fSortByNameAction.setImageDescriptor(SORT_BY_NAME_ICON);
299 }
300 return fSortByNameAction;
301 }
302
303 private Action getSortByIdAction() {
304 if (fSortByIdAction == null) {
305 fSortByIdAction = new Action(Messages.FlameGraph_SortByThreadId, IAction.AS_CHECK_BOX) {
306 @Override
307 public void run() {
308 SortOption sortOption = fTimeGraphContentProvider.getSortOption();
309 if (sortOption == SortOption.BY_ID) {
310 setSortOption(SortOption.BY_ID_REV);
311 } else {
312 setSortOption(SortOption.BY_ID);
313 }
314 }
315 };
316 fSortByIdAction.setToolTipText(Messages.FlameGraph_SortByThreadId);
317 fSortByIdAction.setImageDescriptor(SORT_BY_ID_ICON);
318 }
319 return fSortByIdAction;
320 }
321
322 private void setSortOption(SortOption sortOption) {
323 // reset defaults
324 getSortByNameAction().setChecked(false);
325 getSortByNameAction().setImageDescriptor(SORT_BY_NAME_ICON);
326 getSortByIdAction().setChecked(false);
327 getSortByIdAction().setImageDescriptor(SORT_BY_ID_ICON);
328
329 if (sortOption.equals(SortOption.BY_NAME)) {
330 fTimeGraphContentProvider.setSortOption(SortOption.BY_NAME);
331 getSortByNameAction().setChecked(true);
332 } else if (sortOption.equals(SortOption.BY_NAME_REV)) {
333 fTimeGraphContentProvider.setSortOption(SortOption.BY_NAME_REV);
334 getSortByNameAction().setChecked(true);
335 getSortByNameAction().setImageDescriptor(SORT_BY_NAME_REV_ICON);
336 } else if (sortOption.equals(SortOption.BY_ID)) {
337 fTimeGraphContentProvider.setSortOption(SortOption.BY_ID);
338 getSortByIdAction().setChecked(true);
339 } else if (sortOption.equals(SortOption.BY_ID_REV)) {
340 fTimeGraphContentProvider.setSortOption(SortOption.BY_ID_REV);
341 getSortByIdAction().setChecked(true);
342 getSortByIdAction().setImageDescriptor(SORT_BY_ID_REV_ICON);
343 }
344 saveSortOption();
345 fTimeGraphViewer.refresh();
346 }
347
348 private void saveSortOption() {
349 SortOption sortOption = fTimeGraphContentProvider.getSortOption();
350 IDialogSettings settings = Activator.getDefault().getDialogSettings();
351 IDialogSettings section = settings.getSection(getClass().getName());
352 if (section == null) {
353 section = settings.addNewSection(getClass().getName());
354 }
355 section.put(SORT_OPTION_KEY, sortOption.name());
356 }
357
358 private void loadSortOption() {
359 IDialogSettings settings = Activator.getDefault().getDialogSettings();
360 IDialogSettings section = settings.getSection(getClass().getName());
361 if (section == null) {
362 return;
363 }
364 String sortOption = section.get(SORT_OPTION_KEY);
365 if (sortOption == null) {
366 return;
367 }
368 setSortOption(SortOption.fromName(sortOption));
369 }
370
74ccf789 371}
This page took 0.047785 seconds and 5 git commands to generate.