/*******************************************************************************
- * Copyright (c) 2013, 2015 Ericsson
+ * Copyright (c) 2013, 2016 Ericsson and others.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
package org.eclipse.tracecompass.tmf.ui.views.callstack;
-import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
-
-import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
-import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
-import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ControlAdapter;
-import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.Tree;
-import org.eclipse.tracecompass.internal.tmf.core.callstack.FunctionNameMapper;
import org.eclipse.tracecompass.internal.tmf.ui.Activator;
import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants;
import org.eclipse.tracecompass.internal.tmf.ui.Messages;
import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type;
-import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
-import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
-import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
-import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampDelta;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
import org.eclipse.tracecompass.tmf.ui.editors.ITmfTraceEditor;
-import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
-import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
-import org.eclipse.tracecompass.tmf.ui.views.TmfView;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProvider;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProviderPreferencePage;
+import org.eclipse.tracecompass.tmf.ui.symbols.SymbolProviderConfigDialog;
+import org.eclipse.tracecompass.tmf.ui.symbols.SymbolProviderManager;
+import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractTimeGraphView;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphCombo;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphContentProvider;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphSelection;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
-import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchActionConstants;
/**
* Main implementation for the Call Stack view
*
* @author Patrick Tasse
*/
-public class CallStackView extends TmfView implements ITmfTimeAligned {
+public class CallStackView extends AbstractTimeGraphView {
// ------------------------------------------------------------------------
// Constants
/** View ID. */
public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.callstack"; //$NON-NLS-1$
- /**
- * Redraw state enum
- */
- private enum State {
- IDLE, BUSY, PENDING
- }
-
- private static final String[] COLUMN_TIMES = new String[] {
+ private static final String[] COLUMN_NAMES = new String[] {
Messages.CallStackView_FunctionColumn,
Messages.CallStackView_DepthColumn,
Messages.CallStackView_EntryTimeColumn,
Messages.CallStackView_DurationColumn
};
- private static final int[] COLUMN_WIDTHS = new int[] {
- 200,
- 50,
- 120,
- 120,
- 120
+ private static final String[] FILTER_COLUMN_NAMES = new String[] {
+ Messages.CallStackView_ThreadColumn
};
/** Timeout between updates in the build thread in ms */
// Fraction of a function duration to be added as spacing
private static final double SPACING_RATIO = 0.01;
+ private static final Image PROCESS_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/process_obj.gif"); //$NON-NLS-1$
private static final Image THREAD_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/thread_obj.gif"); //$NON-NLS-1$
private static final Image STACKFRAME_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/stckframe_obj.gif"); //$NON-NLS-1$
- private static final String IMPORT_MAPPING_ICON_PATH = "icons/etool16/import.gif"; //$NON-NLS-1$
private static final String IMPORT_BINARY_ICON_PATH = "icons/obj16/binaries_obj.gif"; //$NON-NLS-1$
private static final ImageDescriptor SORT_BY_NAME_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha.gif"); //$NON-NLS-1$
BY_NAME, BY_NAME_REV, BY_ID, BY_ID_REV, BY_TIME, BY_TIME_REV
}
- private SortOption fSortOption;
- private Comparator<ITimeGraphEntry> fThreadComparator = null;
+ private @NonNull SortOption fSortOption = SortOption.BY_NAME;
+ private @NonNull Comparator<ITimeGraphEntry> fThreadComparator = new ThreadNameComparator(false);
private Action fSortByNameAction;
private Action fSortByIdAction;
private Action fSortByTimeAction;
// Fields
// ------------------------------------------------------------------------
- // The time graph combo
- private TimeGraphCombo fTimeGraphCombo;
-
- // The selected trace
- private ITmfTrace fTrace;
-
- // The selected thread map
- private final Map<ITmfTrace, String> fSelectedThreadMap = new HashMap<>();
-
- // The time graph entry list
- private List<TraceEntry> fEntryList;
-
- // The trace to entry list hash map
- private final Map<ITmfTrace, List<TraceEntry>> fEntryListMap = new HashMap<>();
-
- // The trace to build thread hash map
- private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<>();
-
- /** The map to map function addresses to function names */
- private Map<String, String> fNameMapping;
-
- // The start time
- private long fStartTime;
-
- // The end time
- private long fEndTime;
-
- // The display width
- private int fDisplayWidth;
+ private final Map<ITmfTrace, ISymbolProvider> fSymbolProviders = new HashMap<>();
// The next event action
private Action fNextEventAction;
// The previous item action
private Action fPreviousItemAction;
- // The action to import a function-name mapping file
- private Action fImportMappingAction;
-
// The action to import a binary file mapping */
- private Action fImportBinaryFileMappingAction;
-
- // The zoom thread
- private ZoomThread fZoomThread;
-
- // The redraw state used to prevent unnecessary queuing of display runnables
- private State fRedrawState = State.IDLE;
-
- // The redraw synchronization object
- private final Object fSyncObj = new Object();
+ private Action fConfigureSymbolsAction;
// The saved time sync. signal used when switching off the pinning of a view
private TmfSelectionRangeUpdatedSignal fSavedTimeSyncSignal;
// a view
private TmfWindowRangeUpdatedSignal fSavedRangeSyncSignal;
+ // When set to true, syncToTime() will select the first call stack entry
+ // whose current state start time exactly matches the sync time.
+ private boolean fSyncSelection = false;
+
// ------------------------------------------------------------------------
// Classes
// ------------------------------------------------------------------------
- private class TraceEntry extends TimeGraphEntry {
+ private static class TraceEntry extends TimeGraphEntry {
public TraceEntry(String name, long startTime, long endTime) {
super(name, startTime, endTime);
}
}
}
- private class ThreadEntry extends TimeGraphEntry {
- // The call stack quark
- private final int fCallStackQuark;
- // The state system from which this entry comes
- private final ITmfStateSystem fSS;
+ private static class ProcessEntry extends TimeGraphEntry {
+
+ private final int fProcessId;
+
+ public ProcessEntry(String name, int processId, long startTime, long endTime) {
+ super(name, startTime, endTime);
+ fProcessId = processId;
+ }
+
+ @Override
+ public boolean hasTimeEvents() {
+ return false;
+ }
+ }
+
+ private static class ThreadEntry extends TimeGraphEntry {
// The thread id
private final long fThreadId;
- public ThreadEntry(ITmfStateSystem ss, String name, long threadId, int callStackQuark, long startTime, long endTime) {
+ public ThreadEntry(String name, long threadId, long startTime, long endTime) {
super(name, startTime, endTime);
- fCallStackQuark = callStackQuark;
fThreadId = threadId;
- fSS = ss;
}
@Override
return false;
}
- public int getCallStackQuark() {
- return fCallStackQuark;
- }
-
public long getThreadId() {
return fThreadId;
}
+ }
- @Nullable
- public ITmfStateSystem getStateSystem() {
- return fSS;
+ private class CallStackComparator implements Comparator<ITimeGraphEntry> {
+ @Override
+ public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
+ if (o1 instanceof ThreadEntry && o2 instanceof ThreadEntry) {
+ return fThreadComparator.compare(o1, o2);
+ } else if (o1 instanceof ProcessEntry && o2 instanceof ProcessEntry) {
+ return Integer.compare(((ProcessEntry) o1).fProcessId, ((ProcessEntry) o2).fProcessId);
+ }
+ return 0;
}
}
- private class ThreadNameComparator implements Comparator<ITimeGraphEntry> {
+ private static class ThreadNameComparator implements Comparator<ITimeGraphEntry> {
private boolean reverse;
public ThreadNameComparator(boolean reverse) {
}
}
- private class ThreadIdComparator implements Comparator<ITimeGraphEntry> {
+ private static class ThreadIdComparator implements Comparator<ITimeGraphEntry> {
private boolean reverse;
public ThreadIdComparator(boolean reverse) {
@Override
public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
- ThreadEntry t1 = (ThreadEntry) o1;
- ThreadEntry t2 = (ThreadEntry) o2;
- return reverse ? Long.compare(t2.getThreadId(), t1.getThreadId()) :
+ if (o1 instanceof ThreadEntry && o2 instanceof ThreadEntry) {
+ ThreadEntry t1 = (ThreadEntry) o1;
+ ThreadEntry t2 = (ThreadEntry) o2;
+ return reverse ? Long.compare(t2.getThreadId(), t1.getThreadId()) :
Long.compare(t1.getThreadId(), t2.getThreadId());
+ }
+ return 0;
}
}
- private class ThreadTimeComparator implements Comparator<ITimeGraphEntry> {
+ private static class ThreadTimeComparator implements Comparator<ITimeGraphEntry> {
private boolean reverse;
public ThreadTimeComparator(boolean reverse) {
}
}
- private class TreeLabelProvider implements ITableLabelProvider {
-
- @Override
- public void addListener(ILabelProviderListener listener) {
- }
-
- @Override
- public void dispose() {
- }
-
- @Override
- public boolean isLabelProperty(Object element, String property) {
- return false;
- }
-
- @Override
- public void removeListener(ILabelProviderListener listener) {
- }
+ private static class CallStackTreeLabelProvider extends TreeLabelProvider {
@Override
public Image getColumnImage(Object element, int columnIndex) {
if (columnIndex == 0) {
- if (element instanceof ThreadEntry) {
+ if (element instanceof ProcessEntry) {
+ return PROCESS_IMAGE;
+ } else if (element instanceof ThreadEntry) {
return THREAD_IMAGE;
} else if (element instanceof CallStackEntry) {
CallStackEntry entry = (CallStackEntry) element;
int depth = entry.getStackLevel();
return Integer.toString(depth);
} else if (columnIndex == 2 && entry.getFunctionName().length() > 0) {
- ITmfTimestamp ts = new TmfTimestamp(entry.getFunctionEntryTime(), ITmfTimestamp.NANOSECOND_SCALE);
+ ITmfTimestamp ts = TmfTimestamp.fromNanos(entry.getFunctionEntryTime());
return ts.toString();
} else if (columnIndex == 3 && entry.getFunctionName().length() > 0) {
- ITmfTimestamp ts = new TmfTimestamp(entry.getFunctionExitTime(), ITmfTimestamp.NANOSECOND_SCALE);
+ ITmfTimestamp ts = TmfTimestamp.fromNanos(entry.getFunctionExitTime());
return ts.toString();
} else if (columnIndex == 4 && entry.getFunctionName().length() > 0) {
ITmfTimestamp ts = new TmfTimestampDelta(entry.getFunctionExitTime() - entry.getFunctionEntryTime(), ITmfTimestamp.NANOSECOND_SCALE);
}
- private class BuildThread extends Thread {
- private final @NonNull ITmfTrace fBuildTrace;
- private final ITmfTrace fParentTrace;
- private final IProgressMonitor fMonitor;
-
- public BuildThread(@NonNull ITmfTrace trace, ITmfTrace parentTrace) {
- super("CallStackView build"); //$NON-NLS-1$
- fBuildTrace = trace;
- fParentTrace = parentTrace;
- fMonitor = new NullProgressMonitor();
- }
-
+ private class CallStackFilterContentProvider extends TimeGraphContentProvider {
@Override
- public void run() {
- buildThreadList(fBuildTrace, fParentTrace, fMonitor);
- synchronized (fBuildThreadMap) {
- fBuildThreadMap.remove(fBuildTrace);
+ public boolean hasChildren(Object element) {
+ if (element instanceof TraceEntry) {
+ return super.hasChildren(element);
}
- }
-
- public void cancel() {
- fMonitor.setCanceled(true);
- }
- }
-
- private class ZoomThread extends Thread {
- private final List<TraceEntry> fZoomEntryList;
- private final long fZoomStartTime;
- private final long fZoomEndTime;
- private final IProgressMonitor fMonitor;
-
- public ZoomThread(List<TraceEntry> entryList, long startTime, long endTime) {
- super("CallStackView zoom"); //$NON-NLS-1$
- fZoomEntryList = entryList;
- fZoomStartTime = startTime;
- fZoomEndTime = endTime;
- fMonitor = new NullProgressMonitor();
+ return false;
}
@Override
- public void run() {
- if (fZoomEntryList == null) {
- return;
- }
- long resolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
- for (TraceEntry traceEntry : fZoomEntryList) {
- for (ITimeGraphEntry threadEntry : traceEntry.getChildren()) {
- ITmfStateSystem ss = ((ThreadEntry) threadEntry).getStateSystem();
- if (ss == null) {
- continue;
- }
- ss.waitUntilBuilt();
- if (ss.isCancelled()) {
- continue;
- }
- for (ITimeGraphEntry child : threadEntry.getChildren()) {
- if (fMonitor.isCanceled()) {
- break;
- }
- CallStackEntry entry = (CallStackEntry) child;
- if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) {
- entry.setZoomedEventList(null);
- } else {
- List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, resolution, fMonitor);
- if (zoomedEventList != null) {
- entry.setZoomedEventList(zoomedEventList);
- }
- }
- redraw();
- }
- }
+ public ITimeGraphEntry[] getChildren(Object parentElement) {
+ if (parentElement instanceof TraceEntry) {
+ return super.getChildren(parentElement);
}
- }
-
- public void cancel() {
- fMonitor.setCanceled(true);
+ return new ITimeGraphEntry[0];
}
}
* Default constructor
*/
public CallStackView() {
- super(ID);
- fDisplayWidth = Display.getDefault().getBounds().width;
+ super(ID, new CallStackPresentationProvider());
+ getPresentationProvider().setCallStackView(this);
+ setTreeColumns(COLUMN_NAMES);
+ setTreeLabelProvider(new CallStackTreeLabelProvider());
+ setEntryComparator(new CallStackComparator());
+ setFilterColumns(FILTER_COLUMN_NAMES);
+ setFilterContentProvider(new CallStackFilterContentProvider());
+ setFilterLabelProvider(new CallStackTreeLabelProvider());
}
// ------------------------------------------------------------------------
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
- fTimeGraphCombo = new TimeGraphCombo(parent, SWT.NONE);
-
- fTimeGraphCombo.setTreeContentProvider(new TimeGraphContentProvider());
- fTimeGraphCombo.setTreeLabelProvider(new TreeLabelProvider());
-
- fTimeGraphCombo.setTreeColumns(COLUMN_TIMES);
-
- fTimeGraphCombo.getTreeViewer().getTree().getColumn(0).setWidth(COLUMN_WIDTHS[0]);
- fTimeGraphCombo.getTreeViewer().getTree().getColumn(1).setWidth(COLUMN_WIDTHS[1]);
- fTimeGraphCombo.getTreeViewer().getTree().getColumn(2).setWidth(COLUMN_WIDTHS[2]);
- fTimeGraphCombo.getTreeViewer().getTree().getColumn(3).setWidth(COLUMN_WIDTHS[3]);
- fTimeGraphCombo.getTreeViewer().getTree().getColumn(4).setWidth(COLUMN_WIDTHS[4]);
-
- fTimeGraphCombo.setTimeGraphContentProvider(new TimeGraphContentProvider());
- fTimeGraphCombo.setTimeGraphProvider(new CallStackPresentationProvider(this));
- fTimeGraphCombo.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
-
- fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
- @Override
- public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
- long startTime = event.getStartTime();
- long endTime = event.getEndTime();
- TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
- broadcast(new TmfWindowRangeUpdatedSignal(CallStackView.this, range));
- startZoomThread(startTime, endTime);
- }
- });
-
- fTimeGraphCombo.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
+ getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
@Override
public void timeSelected(TimeGraphTimeEvent event) {
- long beginTime = event.getBeginTime();
- long endTime = event.getEndTime();
- synchingToTime(beginTime);
- broadcast(new TmfSelectionRangeUpdatedSignal(CallStackView.this, new TmfNanoTimestamp(beginTime), new TmfNanoTimestamp(endTime)));
+ synchingToTime(event.getBeginTime());
}
});
- fTimeGraphCombo.getTimeGraphViewer().getControl().addControlListener(new ControlAdapter() {
- @Override
- public void controlResized(ControlEvent e) {
- fDisplayWidth = fTimeGraphCombo.getTimeGraphViewer().getControl().getSize().x;
- if (fEntryList != null) {
- startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
- }
- }
- });
-
- fTimeGraphCombo.getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
+ getTimeGraphCombo().getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
long spacingTime = (long) ((exitTime - entryTime) * SPACING_RATIO);
entryTime -= spacingTime;
exitTime += spacingTime;
- TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(entryTime), new TmfNanoTimestamp(exitTime));
+ TmfTimeRange range = new TmfTimeRange(TmfTimestamp.fromNanos(entryTime), TmfTimestamp.fromNanos(exitTime));
broadcast(new TmfWindowRangeUpdatedSignal(CallStackView.this, range));
- fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(entryTime, exitTime);
+ getTimeGraphViewer().setStartFinishTime(entryTime, exitTime);
startZoomThread(entryTime, exitTime);
}
}
}
});
- fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl().addMouseListener(new MouseAdapter() {
+ getTimeGraphViewer().getTimeGraphControl().addMouseListener(new MouseAdapter() {
@Override
public void mouseDoubleClick(MouseEvent e) {
- TimeGraphControl timeGraphControl = fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl();
+ TimeGraphControl timeGraphControl = getTimeGraphViewer().getTimeGraphControl();
ISelection selection = timeGraphControl.getSelection();
if (selection instanceof TimeGraphSelection) {
Object o = ((TimeGraphSelection) selection).getFirstElement();
long spacingTime = (long) ((endTime - startTime) * SPACING_RATIO);
startTime -= spacingTime;
endTime += spacingTime;
- TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
+ TmfTimeRange range = new TmfTimeRange(TmfTimestamp.fromNanos(startTime), TmfTimestamp.fromNanos(endTime));
broadcast(new TmfWindowRangeUpdatedSignal(CallStackView.this, range));
- fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
+ getTimeGraphViewer().setStartFinishTime(startTime, endTime);
startZoomThread(startTime, endTime);
}
}
}
});
- IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
- fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
-
- // View Action Handling
- makeActions();
contributeToActionBars();
- createContextMenu();
loadSortOption();
IEditorPart editor = getSite().getPage().getActiveEditor();
}
}
- @Override
- public void setFocus() {
- fTimeGraphCombo.setFocus();
- }
-
- // ------------------------------------------------------------------------
- // Signal handlers
- // ------------------------------------------------------------------------
- /**
- * Handler for the trace opened signal.
- *
- * @param signal
- * The incoming signal
- */
- @TmfSignalHandler
- public void traceOpened(TmfTraceOpenedSignal signal) {
- fTrace = signal.getTrace();
- loadTrace();
- }
-
- /**
- * Handler for the trace selected signal
- *
- * @param signal
- * The incoming signal
- */
- @TmfSignalHandler
- public void traceSelected(final TmfTraceSelectedSignal signal) {
- if (signal.getTrace() == fTrace) {
- return;
- }
- fTrace = signal.getTrace();
- loadTrace();
- }
-
- /**
- * Trace is closed: clear the data structures and the view
- *
- * @param signal
- * the signal received
- */
- @TmfSignalHandler
- public void traceClosed(final TmfTraceClosedSignal signal) {
- synchronized (fBuildThreadMap) {
- for (ITmfTrace trace : TmfTraceManager.getTraceSet(signal.getTrace())) {
- BuildThread buildThread = fBuildThreadMap.remove(trace);
- if (buildThread != null) {
- buildThread.cancel();
- }
- }
- }
- synchronized (fEntryListMap) {
- fEntryListMap.remove(signal.getTrace());
- }
- fSelectedThreadMap.remove(signal.getTrace());
- if (signal.getTrace() == fTrace) {
- fTrace = null;
- fStartTime = 0;
- fEndTime = 0;
- refresh();
- }
- }
-
/**
* Handler for the selection range signal.
*
* The incoming signal
* @since 1.0
*/
+ @Override
@TmfSignalHandler
public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal) {
fSavedTimeSyncSignal = isPinned() ? new TmfSelectionRangeUpdatedSignal(signal.getSource(), signal.getBeginTime(), signal.getEndTime()) : null;
- if (signal.getSource() == this || fTrace == null || isPinned()) {
+ if (signal.getSource() == this || getTrace() == null || isPinned()) {
return;
}
- final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+ final long beginTime = signal.getBeginTime().toNanos();
+ final long endTime = signal.getEndTime().toNanos();
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
- if (fTimeGraphCombo.isDisposed()) {
+ if (getTimeGraphCombo().isDisposed()) {
return;
}
if (beginTime == endTime) {
- fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(beginTime, true);
+ getTimeGraphViewer().setSelectedTime(beginTime, true);
} else {
- fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(beginTime, endTime);
+ getTimeGraphViewer().setSelectionRange(beginTime, endTime, true);
}
+ fSyncSelection = true;
synchingToTime(beginTime);
- startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
- if (fEntryList == null) {
- return;
- }
- TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
- for (TraceEntry traceEntry : fEntryList) {
- for (ITimeGraphEntry child : traceEntry.getChildren()) {
- ThreadEntry threadEntry = (ThreadEntry) child;
- ITmfStateSystem ss = threadEntry.getStateSystem();
- if (ss == null || beginTime < ss.getStartTime() || beginTime > ss.getCurrentEndTime()) {
- continue;
- }
- try {
- int quark = threadEntry.getCallStackQuark();
- ITmfStateInterval stackInterval = ss.querySingleState(beginTime, quark);
- if (beginTime == stackInterval.getStartTime()) {
- int stackLevel = stackInterval.getStateValue().unboxInt();
- ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
- fTimeGraphCombo.setSelection(selectedEntry);
- viewer.getTimeGraphControl().fireSelectionChanged();
- break;
- }
- } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
- Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
- }
- }
- }
+ fSyncSelection = false;
+ startZoomThread(getTimeGraphViewer().getTime0(), getTimeGraphViewer().getTime1());
}
});
+
}
/**
- * Handler for the window range signal.
- *
- * @param signal
- * The incoming signal
- * @since 1.0
+ * @since 2.0
*/
+ @Override
@TmfSignalHandler
public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal) {
if (isPinned()) {
- fSavedRangeSyncSignal =
- new TmfWindowRangeUpdatedSignal(signal.getSource(), new TmfTimeRange(signal.getCurrentRange().getStartTime(), signal.getCurrentRange().getEndTime()));
-
+ fSavedRangeSyncSignal = new TmfWindowRangeUpdatedSignal(signal.getSource(), signal.getCurrentRange());
fSavedTimeSyncSignal = null;
}
- if (signal.getSource() == this || fTrace == null || isPinned()) {
+ if ((signal.getSource() == this) || isPinned()) {
return;
}
- if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
- return;
- }
- final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- Display.getDefault().asyncExec(new Runnable() {
- @Override
- public void run() {
- if (fTimeGraphCombo.isDisposed()) {
- return;
- }
- fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
- startZoomThread(startTime, endTime);
- }
- });
+ super.windowRangeUpdated(signal);
}
// ------------------------------------------------------------------------
// Internal
// ------------------------------------------------------------------------
- private void loadTrace() {
- synchronized (fEntryListMap) {
- fEntryList = fEntryListMap.get(fTrace);
- if (fEntryList == null) {
- fStartTime = Long.MAX_VALUE;
- fEndTime = Long.MIN_VALUE;
- refresh();
- synchronized (fBuildThreadMap) {
- for (ITmfTrace trace : TmfTraceManager.getTraceSet(fTrace)) {
- trace = checkNotNull(trace);
- BuildThread buildThread = new BuildThread(trace, fTrace);
- fBuildThreadMap.put(trace, buildThread);
- buildThread.start();
- }
- }
- } else {
- fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- refresh();
+ /**
+ * @since 2.1
+ */
+ @Override
+ protected CallStackPresentationProvider getPresentationProvider() {
+ /* Set to this type by the constructor */
+ return (CallStackPresentationProvider) super.getPresentationProvider();
+ }
+
+ @Override
+ @TmfSignalHandler
+ public void traceClosed(TmfTraceClosedSignal signal) {
+ super.traceClosed(signal);
+ synchronized(fSymbolProviders){
+ for(ITmfTrace trace : getTracesToBuild(signal.getTrace())){
+ fSymbolProviders.remove(trace);
}
}
}
- private void buildThreadList(final @NonNull ITmfTrace trace, final ITmfTrace parentTrace, IProgressMonitor monitor) {
+ /**
+ * @since 2.0
+ */
+ @Override
+ protected void refresh() {
+ super.refresh();
+ updateConfigureSymbolsAction();
+ }
+
+ @Override
+ protected void buildEntryList(final ITmfTrace trace, final ITmfTrace parentTrace, final IProgressMonitor monitor) {
if (monitor.isCanceled()) {
return;
}
+
+ /*
+ * Load the symbol provider for the current trace, even if it does not
+ * provide a call stack analysis module. See
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=494212
+ */
+ ISymbolProvider provider = fSymbolProviders.get(trace);
+ if (provider == null) {
+ provider = SymbolProviderManager.getInstance().getSymbolProvider(trace);
+ provider.loadConfiguration(null);
+ fSymbolProviders.put(trace, provider);
+ }
+
+ /* Continue with the call stack view specific operations */
AbstractCallStackAnalysis module = getCallStackModule(trace);
if (module == null) {
addUnavailableEntry(trace, parentTrace);
}
Map<ITmfTrace, TraceEntry> traceEntryMap = new HashMap<>();
+ Map<Integer, ProcessEntry> processEntryMap = new HashMap<>();
Map<Integer, ThreadEntry> threadEntryMap = new HashMap<>();
- String[] threadPaths = module.getThreadsPattern();
long start = ss.getStartTime();
if (start == end && !complete) { // when complete execute one last time regardless of end time
continue;
}
- List<Integer> threadQuarks = ss.getQuarks(threadPaths);
+
TraceEntry traceEntry = traceEntryMap.get(trace);
if (traceEntry == null) {
traceEntry = new TraceEntry(trace.getName(), start, end + 1);
} else {
traceEntry.updateEndTime(end);
}
- for (int i = 0; i < threadQuarks.size(); i++) {
- if (monitor.isCanceled()) {
- return;
- }
- int threadQuark = threadQuarks.get(i);
- try {
- String[] callStackPath = module.getCallStackPath();
- int callStackQuark = ss.getQuarkRelative(threadQuark, callStackPath);
- String threadName = ss.getAttributeName(threadQuark);
- long threadEnd = end + 1;
- ITmfStateInterval endInterval = ss.querySingleState(ss.getCurrentEndTime(), callStackQuark);
- if (endInterval.getStateValue().isNull() && endInterval.getStartTime() != ss.getStartTime()) {
- threadEnd = endInterval.getStartTime();
- }
- ThreadEntry threadEntry = threadEntryMap.get(threadQuark);
- if (threadEntry == null) {
- long threadId = ss.querySingleState(ss.getCurrentEndTime(), threadQuark).getStateValue().unboxLong();
- long threadStart = start;
- ITmfStateInterval startInterval = ss.querySingleState(start, callStackQuark);
- if (startInterval.getStateValue().isNull()) {
- threadStart = Math.min(startInterval.getEndTime() + 1, end + 1);
+
+ try {
+ List<ITmfStateInterval> endStates = ss.queryFullState(ss.getCurrentEndTime());
+
+ List<Integer> processQuarks = ss.getQuarks(module.getProcessesPattern());
+ for (int processQuark : processQuarks) {
+
+ /*
+ * Default to trace entry, overwrite if a process entry exists.
+ */
+ TimeGraphEntry threadParent = traceEntry;
+ int processId = -1;
+ if (processQuark != ITmfStateSystem.ROOT_ATTRIBUTE) {
+ /* Create the entry for the process */
+ ProcessEntry processEntry = processEntryMap.get(processQuark);
+ if (processEntry == null) {
+ String processName = ss.getAttributeName(processQuark);
+ ITmfStateValue processStateValue = endStates.get(processQuark).getStateValue();
+ if (processStateValue.getType() == Type.INTEGER) {
+ processId = processStateValue.unboxInt();
+ } else {
+ try {
+ processId = Integer.parseInt(processName);
+ } catch (NumberFormatException e) {
+ /* use default processId */
+ }
+ }
+ processEntry = new ProcessEntry(processName, processId, start, end);
+ processEntryMap.put(processQuark, processEntry);
+ traceEntry.addChild(processEntry);
+ } else {
+ processEntry.updateEndTime(end);
}
- threadEntry = new ThreadEntry(ss, threadName, threadId, callStackQuark, threadStart, threadEnd);
- threadEntryMap.put(threadQuark, threadEntry);
- traceEntry.addChild(threadEntry);
- } else {
- threadEntry.updateEndTime(threadEnd);
+ /* The parent of the thread entries will be a process */
+ threadParent = processEntry;
}
- int level = 1;
- for (int stackLevelQuark : ss.getSubAttributes(callStackQuark, false)) {
- if (level > threadEntry.getChildren().size()) {
- CallStackEntry callStackEntry = new CallStackEntry(threadName, stackLevelQuark, level, trace, ss);
- threadEntry.addChild(callStackEntry);
+
+ /* Create the threads under the process */
+ List<Integer> threadQuarks = ss.getQuarks(processQuark, module.getThreadsPattern());
+
+ /*
+ * Only query startStates if necessary (threadEntry == null)
+ */
+ List<ITmfStateInterval> startStates = null;
+ for (int threadQuark : threadQuarks) {
+ if (monitor.isCanceled()) {
+ return;
+ }
+
+ String[] callStackPath = module.getCallStackPath();
+ int callStackQuark = ss.getQuarkRelative(threadQuark, callStackPath);
+ String threadName = ss.getAttributeName(threadQuark);
+ long threadEnd = end + 1;
+ ITmfStateInterval endInterval = endStates.get(callStackQuark);
+ if (endInterval.getStateValue().isNull() && endInterval.getStartTime() != ss.getStartTime()) {
+ threadEnd = endInterval.getStartTime();
+ }
+ /*
+ * Default to process/trace entry, overwrite if a thread entry exists.
+ */
+ TimeGraphEntry callStackParent = threadParent;
+ if (threadQuark != processQuark) {
+ ThreadEntry threadEntry = threadEntryMap.get(threadQuark);
+ if (threadEntry == null) {
+ if (startStates == null) {
+ startStates = ss.queryFullState(ss.getStartTime());
+ }
+ long threadId = -1;
+ ITmfStateValue threadStateValue = endStates.get(threadQuark).getStateValue();
+ if (threadStateValue.getType() == Type.LONG || threadStateValue.getType() == Type.INTEGER) {
+ threadId = threadStateValue.unboxLong();
+ } else {
+ try {
+ threadId = Long.parseLong(threadName);
+ } catch (NumberFormatException e) {
+ /* use default threadId */
+ }
+ }
+ long threadStart = start;
+ ITmfStateInterval startInterval = startStates.get(callStackQuark);
+ if (startInterval.getStateValue().isNull()) {
+ threadStart = Math.min(startInterval.getEndTime() + 1, end + 1);
+ }
+ threadEntry = new ThreadEntry(threadName, threadId, threadStart, threadEnd);
+ threadEntryMap.put(threadQuark, threadEntry);
+ threadParent.addChild(threadEntry);
+ } else {
+ threadEntry.updateEndTime(threadEnd);
+ }
+ /* The parent of the call stack entries will be a thread */
+ callStackParent = threadEntry;
+ }
+ int level = 1;
+ for (int stackLevelQuark : ss.getSubAttributes(callStackQuark, false)) {
+ if (level > callStackParent.getChildren().size()) {
+ CallStackEntry callStackEntry = new CallStackEntry(threadName, stackLevelQuark, level, processId, trace, ss);
+ callStackParent.addChild(callStackEntry);
+ }
+ level++;
}
- level++;
}
- } catch (AttributeNotFoundException e) {
- Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
- } catch (StateSystemDisposedException e) {
- /* Ignored */
}
+ } catch (AttributeNotFoundException e) {
+ Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
+ } catch (StateSystemDisposedException e) {
+ /* Ignored */
}
- if (parentTrace == fTrace) {
- synchronized (fEntryListMap) {
- fStartTime = Math.min(fStartTime, start);
- fEndTime = Math.max(fEndTime, end + 1);
+
+ if (parentTrace == getTrace()) {
+ synchronized (this) {
+ setStartTime(getStartTime() == SWT.DEFAULT ? start : Math.min(getStartTime(), start));
+ setEndTime(getEndTime() == SWT.DEFAULT ? end + 1 : Math.max(getEndTime(), end + 1));
}
+ synchingToTime(getTimeGraphViewer().getSelectionBegin());
refresh();
}
- for (ITimeGraphEntry threadEntry : traceEntry.getChildren()) {
- for (ITimeGraphEntry callStackEntry : threadEntry.getChildren()) {
+
+ Consumer<TimeGraphEntry> consumer = new Consumer<TimeGraphEntry>() {
+ @Override
+ public void accept(TimeGraphEntry entry) {
if (monitor.isCanceled()) {
return;
}
- buildStatusEvents(parentTrace, (CallStackEntry) callStackEntry, monitor, start, end);
+ if (entry instanceof CallStackEntry) {
+ buildStatusEvents(parentTrace, (CallStackEntry) entry, monitor, ss.getStartTime(), end);
+ return;
+ }
+ entry.getChildren().forEach(this);
}
- }
- start = end;
- }
- }
+ };
+ traceEntry.getChildren().forEach(consumer);
- private void addToEntryList(ITmfTrace trace, List<TraceEntry> list) {
- synchronized (fEntryListMap) {
- List<TraceEntry> entryList = fEntryListMap.get(trace);
- if (entryList == null) {
- fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
- } else {
- entryList.addAll(list);
- }
+ start = end;
}
}
String name = Messages.CallStackView_StackInfoNotAvailable + ' ' + '(' + trace.getName() + ')';
TraceEntry unavailableEntry = new TraceEntry(name, 0, 0);
addToEntryList(parentTrace, Collections.singletonList(unavailableEntry));
- if (parentTrace == fTrace) {
+ if (parentTrace == getTrace()) {
refresh();
}
}
- private void buildStatusEvents(ITmfTrace trace, CallStackEntry entry, IProgressMonitor monitor, long start, long end) {
+ private void buildStatusEvents(ITmfTrace trace, CallStackEntry entry, @NonNull IProgressMonitor monitor, long start, long end) {
ITmfStateSystem ss = entry.getStateSystem();
- long resolution = Math.max(1, (end - ss.getStartTime()) / fDisplayWidth);
+ long resolution = Math.max(1, (end - ss.getStartTime()) / getDisplayWidth());
List<ITimeEvent> eventList = getEventList(entry, start, end + 1, resolution, monitor);
if (eventList != null) {
- for (ITimeEvent event : eventList) {
- entry.addEvent(event);
- }
+ entry.setEventList(eventList);
}
- if (trace == fTrace) {
+ if (trace == getTrace()) {
redraw();
}
}
- private static List<ITimeEvent> getEventList(CallStackEntry entry,
- long startTime, long endTime, long resolution,
- IProgressMonitor monitor) {
+ /**
+ * @since 1.2
+ */
+ @Override
+ protected final List<ITimeEvent> getEventList(TimeGraphEntry tgentry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
+ if (!(tgentry instanceof CallStackEntry)) {
+ return null;
+ }
+ CallStackEntry entry = (CallStackEntry) tgentry;
ITmfStateSystem ss = entry.getStateSystem();
long start = Math.max(startTime, ss.getStartTime());
long end = Math.min(endTime, ss.getCurrentEndTime() + 1);
if (end <= start) {
return null;
}
+ boolean isZoomThread = Thread.currentThread() instanceof ZoomThread;
List<ITimeEvent> eventList = null;
try {
List<ITmfStateInterval> stackIntervals = StateSystemUtils.queryHistoryRange(ss, entry.getQuark(), start, end - 1, resolution, monitor);
eventList = new ArrayList<>(stackIntervals.size());
long lastEndTime = -1;
- boolean lastIsNull = true;
+ boolean lastIsNull = false;
for (ITmfStateInterval statusInterval : stackIntervals) {
if (monitor.isCanceled()) {
return null;
eventList.add(new CallStackEvent(entry, time, duration, value));
lastIsNull = false;
} else {
- if (lastEndTime == -1) {
+ if (lastEndTime == -1 && isZoomThread) {
// add null event if it intersects the start time
eventList.add(new NullTimeEvent(entry, time, duration));
} else {
// add unknown event if between two null states
eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
}
- if (time + duration >= endTime) {
+ if (time + duration >= endTime && isZoomThread) {
// add null event if it intersects the end time
eventList.add(new NullTimeEvent(entry, time, duration));
}
return eventList;
}
- private void synchingToTime(long time) {
- if (fEntryList == null) {
+ /**
+ * @since 1.2
+ */
+ @Override
+ protected void synchingToTime(final long time) {
+ List<TimeGraphEntry> traceEntries = getEntryList(getTrace());
+ Map<ITmfStateSystem, List<ITmfStateInterval>> fullStateMap = new HashMap<>();
+ if (traceEntries == null) {
return;
}
- for (TraceEntry traceEntry : fEntryList) {
- for (ITimeGraphEntry threadEntry : traceEntry.getChildren()) {
- ITmfStateSystem ss = ((ThreadEntry) threadEntry).getStateSystem();
- if (ss == null) {
- continue;
- }
- if (ss.isCancelled()) {
- continue;
- }
- if (time < ss.getStartTime() || time > ss.getCurrentEndTime()) {
- continue;
- }
- for (ITimeGraphEntry child : threadEntry.getChildren()) {
- CallStackEntry callStackEntry = (CallStackEntry) child;
+ Consumer<TimeGraphEntry> consumer = new Consumer<TimeGraphEntry>() {
+ @Override
+ public void accept(TimeGraphEntry entry) {
+ if (entry instanceof CallStackEntry) {
+ CallStackEntry callStackEntry = (CallStackEntry) entry;
+ ITmfStateSystem ss = callStackEntry.getStateSystem();
+ if (time < ss.getStartTime() || time > ss.getCurrentEndTime()) {
+ return;
+ }
+ ITmfTrace trace = callStackEntry.getTrace();
try {
- ITmfStateInterval stackLevelInterval = ss.querySingleState(time, callStackEntry.getQuark());
+ List<ITmfStateInterval> fullState = getFullState(ss);
+ ITmfStateInterval stackLevelInterval = fullState.get(callStackEntry.getQuark());
ITmfStateValue nameValue = stackLevelInterval.getStateValue();
- String name = ""; //$NON-NLS-1$
- try {
- if (nameValue.getType() == Type.STRING) {
- String address = nameValue.unboxStr();
- name = getFunctionName(address);
- } else if (nameValue.getType() == Type.INTEGER) {
- name = "0x" + Integer.toHexString(nameValue.unboxInt()); //$NON-NLS-1$
- } else if (nameValue.getType() == Type.LONG) {
- name = "0x" + Long.toHexString(nameValue.unboxLong()); //$NON-NLS-1$
- }
- } catch (StateValueTypeException e) {
- }
+
+ String name = getFunctionName(trace, callStackEntry.getProcessId(), time, nameValue);
callStackEntry.setFunctionName(name);
- if (name.length() > 0) {
+ if (!name.isEmpty()) {
callStackEntry.setFunctionEntryTime(stackLevelInterval.getStartTime());
callStackEntry.setFunctionExitTime(stackLevelInterval.getEndTime() + 1);
}
- } catch (AttributeNotFoundException e) {
- Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
+ if (fSyncSelection) {
+ int callStackQuark = ss.getParentAttributeQuark(callStackEntry.getQuark());
+ ITmfStateInterval stackInterval = fullState.get(callStackQuark);
+ if (time == stackInterval.getStartTime()) {
+ ITmfStateValue stackLevelState = stackInterval.getStateValue();
+ if (stackLevelState.unboxInt() == callStackEntry.getStackLevel() || stackLevelState.isNull()) {
+ Display.getDefault().asyncExec(() -> {
+ getTimeGraphCombo().setSelection(callStackEntry);
+ getTimeGraphViewer().getTimeGraphControl().fireSelectionChanged();
+ fSyncSelection = false;
+ });
+ }
+ }
+ }
} catch (StateSystemDisposedException e) {
/* Ignored */
}
+ return;
}
+ entry.getChildren().forEach(this);
}
- }
- fTimeGraphCombo.refresh();
- }
- private void refresh() {
- Display.getDefault().asyncExec(new Runnable() {
- @Override
- public void run() {
- if (fTimeGraphCombo.isDisposed()) {
- return;
- }
- synchronized (fEntryListMap) {
- fEntryList = fEntryListMap.get(fTrace);
- if (fEntryList == null) {
- fEntryList = new ArrayList<>();
- }
- for (TraceEntry traceEntry : fEntryList) {
- traceEntry.sortChildren(fThreadComparator);
- }
+ private List<ITmfStateInterval> getFullState(ITmfStateSystem ss) throws StateSystemDisposedException {
+ List<ITmfStateInterval> fullState = fullStateMap.get(ss);
+ if (fullState == null) {
+ fullState = ss.queryFullState(time);
+ fullStateMap.put(ss, fullState);
}
- if (fEntryList != fTimeGraphCombo.getInput()) {
- fTimeGraphCombo.setInput(fEntryList);
- } else {
- fTimeGraphCombo.refresh();
- }
- fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
-
- TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
- long selectionBeginTime = fTrace == null ? 0 : ctx.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- long selectionEndTime = fTrace == null ? 0 : ctx.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- long startTime = fTrace == null ? 0 : ctx.getWindowRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- long endTime = fTrace == null ? 0 : ctx.getWindowRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- startTime = Math.max(startTime, fStartTime);
- endTime = Math.min(endTime, fEndTime);
- fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
- synchingToTime(selectionBeginTime);
- fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
- startZoomThread(startTime, endTime);
+ return fullState;
}
- });
+ };
+ traceEntries.forEach(consumer);
+ if (Display.getCurrent() != null) {
+ getTimeGraphCombo().refresh();
+ }
}
- private void redraw() {
- synchronized (fSyncObj) {
- if (fRedrawState == State.IDLE) {
- fRedrawState = State.BUSY;
- } else {
- fRedrawState = State.PENDING;
- return;
- }
- }
- Display.getDefault().asyncExec(new Runnable() {
- @Override
- public void run() {
- if (fTimeGraphCombo.isDisposed()) {
- return;
+ String getFunctionName(ITmfTrace trace, int processId, long timestamp, ITmfStateValue nameValue) {
+ long address = Long.MAX_VALUE;
+ String name = ""; //$NON-NLS-1$
+ try {
+ if (nameValue.getType() == Type.STRING) {
+ name = nameValue.unboxStr();
+ try {
+ address = Long.parseLong(name, 16);
+ } catch (NumberFormatException e) {
+ // ignore
}
- fTimeGraphCombo.redraw();
- fTimeGraphCombo.update();
- synchronized (fSyncObj) {
- if (fRedrawState == State.PENDING) {
- fRedrawState = State.IDLE;
- redraw();
- } else {
- fRedrawState = State.IDLE;
- }
+ } else if (nameValue.getType() == Type.INTEGER) {
+ name = "0x" + Integer.toUnsignedString(nameValue.unboxInt(), 16); //$NON-NLS-1$
+ address = nameValue.unboxInt();
+ } else if (nameValue.getType() == Type.LONG) {
+ name = "0x" + Long.toUnsignedString(nameValue.unboxLong(), 16); //$NON-NLS-1$
+ address = nameValue.unboxLong();
+ }
+ } catch (StateValueTypeException e) {
+ }
+ if (address != Long.MAX_VALUE) {
+ ISymbolProvider provider = fSymbolProviders.get(trace);
+ if (provider != null) {
+ String symbol = provider.getSymbolText(processId, timestamp, address);
+ if (symbol != null) {
+ name = symbol;
}
}
- });
- }
-
- private void startZoomThread(long startTime, long endTime) {
- if (fZoomThread != null) {
- fZoomThread.cancel();
}
- fZoomThread = new ZoomThread(fEntryList, startTime, endTime);
- fZoomThread.start();
+ return name;
}
private void makeActions() {
- fPreviousItemAction = fTimeGraphCombo.getTimeGraphViewer().getPreviousItemAction();
+ fPreviousItemAction = getTimeGraphViewer().getPreviousItemAction();
fPreviousItemAction.setText(Messages.TmfTimeGraphViewer_PreviousItemActionNameText);
fPreviousItemAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousItemActionToolTipText);
- fNextItemAction = fTimeGraphCombo.getTimeGraphViewer().getNextItemAction();
+ fNextItemAction = getTimeGraphViewer().getNextItemAction();
fNextItemAction.setText(Messages.TmfTimeGraphViewer_NextItemActionNameText);
fNextItemAction.setToolTipText(Messages.TmfTimeGraphViewer_NextItemActionToolTipText);
}
private void contributeToActionBars() {
- IActionBars bars = getViewSite().getActionBars();
- fillLocalToolBar(bars.getToolBarManager());
-
// Create pin action
contributePinActionToToolBar();
fPinAction.addPropertyChangeListener(new IPropertyChangeListener() {
});
}
- private void fillLocalToolBar(IToolBarManager manager) {
- manager.add(getImportBinaryAction());
- manager.add(getImportMappingAction());
+ /**
+ * @since 1.2
+ */
+ @Override
+ protected void fillLocalToolBar(IToolBarManager manager) {
+ makeActions();
+ manager.add(getConfigureSymbolsAction());
manager.add(new Separator());
manager.add(getSortByNameAction());
manager.add(getSortByIdAction());
manager.add(getSortByTimeAction());
manager.add(new Separator());
- manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction());
+ manager.add(getTimeGraphCombo().getShowFilterDialogAction());
+ manager.add(new Separator());
+ manager.add(getTimeGraphViewer().getResetScaleAction());
manager.add(getPreviousEventAction());
manager.add(getNextEventAction());
+ manager.add(new Separator());
+ manager.add(getTimeGraphViewer().getToggleBookmarkAction());
+ manager.add(getTimeGraphViewer().getPreviousMarkerAction());
+ manager.add(getTimeGraphViewer().getNextMarkerAction());
+ manager.add(new Separator());
manager.add(fPreviousItemAction);
manager.add(fNextItemAction);
- manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomInAction());
- manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomOutAction());
- manager.add(new Separator());
+ manager.add(getTimeGraphViewer().getZoomInAction());
+ manager.add(getTimeGraphViewer().getZoomOutAction());
}
- private void createContextMenu() {
- final MenuManager contextMenu = new MenuManager();
+ /**
+ * @since 2.0
+ */
+ @Override
+ protected void fillTimeGraphEntryContextMenu(IMenuManager contextMenu) {
+ contextMenu.add(new GroupMarker(IWorkbenchActionConstants.GROUP_REORGANIZE));
contextMenu.add(getSortByNameAction());
contextMenu.add(getSortByIdAction());
contextMenu.add(getSortByTimeAction());
-
- Tree tree = fTimeGraphCombo.getTreeViewer().getTree();
- Menu menu = contextMenu.createContextMenu(tree);
- tree.setMenu(menu);
}
/**
fNextEventAction = new Action() {
@Override
public void run() {
- TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
+ TimeGraphViewer viewer = getTimeGraphViewer();
ITimeGraphEntry entry = viewer.getSelection();
if (entry instanceof CallStackEntry) {
try {
CallStackEntry callStackEntry = (CallStackEntry) entry;
ITmfStateSystem ss = callStackEntry.getStateSystem();
long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
- ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
+ TimeGraphEntry parentEntry = callStackEntry.getParent();
int quark = ss.getParentAttributeQuark(callStackEntry.getQuark());
ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
long newTime = stackInterval.getEndTime() + 1;
viewer.setSelectedTimeNotify(newTime, true);
stackInterval = ss.querySingleState(Math.min(ss.getCurrentEndTime(), newTime), quark);
int stackLevel = stackInterval.getStateValue().unboxInt();
- ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
- fTimeGraphCombo.setSelection(selectedEntry);
+ ITimeGraphEntry selectedEntry = parentEntry.getChildren().get(Math.max(0, stackLevel - 1));
+ getTimeGraphCombo().setSelection(selectedEntry);
viewer.getTimeGraphControl().fireSelectionChanged();
startZoomThread(viewer.getTime0(), viewer.getTime1());
- } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
+ } catch (TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
}
}
}
};
- fNextEventAction.setText(Messages.TmfTimeGraphViewer_NextEventActionNameText);
- fNextEventAction.setToolTipText(Messages.TmfTimeGraphViewer_NextEventActionToolTipText);
- fNextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_EVENT));
+ fNextEventAction.setText(Messages.TmfTimeGraphViewer_NextStateChangeActionNameText);
+ fNextEventAction.setToolTipText(Messages.TmfTimeGraphViewer_NextStateChangeActionToolTipText);
+ fNextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_STATE_CHANGE));
}
return fNextEventAction;
fPrevEventAction = new Action() {
@Override
public void run() {
- TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
+ TimeGraphViewer viewer = getTimeGraphCombo().getTimeGraphViewer();
ITimeGraphEntry entry = viewer.getSelection();
if (entry instanceof CallStackEntry) {
try {
CallStackEntry callStackEntry = (CallStackEntry) entry;
ITmfStateSystem ss = callStackEntry.getStateSystem();
long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
- ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
+ TimeGraphEntry parentEntry = callStackEntry.getParent();
int quark = ss.getParentAttributeQuark(callStackEntry.getQuark());
ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
if (stackInterval.getStartTime() == time && time > ss.getStartTime()) {
}
viewer.setSelectedTimeNotify(stackInterval.getStartTime(), true);
int stackLevel = stackInterval.getStateValue().unboxInt();
- ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
- fTimeGraphCombo.setSelection(selectedEntry);
+ ITimeGraphEntry selectedEntry = parentEntry.getChildren().get(Math.max(0, stackLevel - 1));
+ getTimeGraphCombo().setSelection(selectedEntry);
viewer.getTimeGraphControl().fireSelectionChanged();
startZoomThread(viewer.getTime0(), viewer.getTime1());
- } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
+ } catch (TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
}
}
}
};
- fPrevEventAction.setText(Messages.TmfTimeGraphViewer_PreviousEventActionNameText);
- fPrevEventAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousEventActionToolTipText);
- fPrevEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_EVENT));
+ fPrevEventAction.setText(Messages.TmfTimeGraphViewer_PreviousStateChangeActionNameText);
+ fPrevEventAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousStateChangeActionToolTipText);
+ fPrevEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_STATE_CHANGE));
}
return fPrevEventAction;
AbstractCallStackAnalysis module = it.next();
/* This analysis is not automatic, we need to schedule it on-demand */
module.schedule();
- module.waitForInitialization();
+ if (!module.waitForInitialization()) {
+ /* The initialization did not succeed */
+ return null;
+ }
return module;
}
// Methods related to function name mapping
// ------------------------------------------------------------------------
- /**
- * Common code for all import file mapping actions
- */
- private abstract class AbstractImportFileMappingAction extends Action {
- private final String fDialogTitle;
-
- private AbstractImportFileMappingAction(String dialogTitle) {
- fDialogTitle = dialogTitle;
- }
-
- @Override
- public void run() {
- FileDialog dialog = new FileDialog(getViewSite().getShell());
- dialog.setText(fDialogTitle);
- final String filePath = dialog.open();
- if (filePath == null) {
- /* No file was selected, don't change anything */
- return;
- }
-
- /*
- * Start the mapping import in a separate thread (we do not want to
- * UI thread to do this).
- */
- Job job = new Job(Messages.CallStackView_ImportMappingJobName) {
- @Override
- public IStatus run(IProgressMonitor monitor) {
- fNameMapping = doMapping(new File(filePath));
-
- /* Refresh call stack entries and event labels */
- Display.getDefault().asyncExec(new Runnable() {
- @Override
- public void run() {
- synchingToTime(fTimeGraphCombo.getTimeGraphViewer().getSelectionBegin());
- }
- });
- return Status.OK_STATUS;
- }
- };
- job.schedule();
- }
-
- abstract Map<String, String> doMapping(File file);
- }
-
- /**
- * Toolbar icon to import the function address-to-name mapping file.
- */
- private Action getImportMappingAction() {
- if (fImportMappingAction != null) {
- return fImportMappingAction;
- }
- fImportMappingAction = new AbstractImportFileMappingAction(Messages.CallStackView_ImportMappingDialogTitle) {
- @Override
- Map<String, String> doMapping(File file) {
- return FunctionNameMapper.mapFromNmTextFile(file);
- }
- };
-
- fImportMappingAction.setText(Messages.CallStackView_ImportMappingButtonText);
- fImportMappingAction.setToolTipText(Messages.CallStackView_ImportMappingButtonTooltip);
- fImportMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_MAPPING_ICON_PATH));
-
- return fImportMappingAction;
- }
-
private Action getSortByNameAction() {
if (fSortByNameAction == null) {
fSortByNameAction = new Action(Messages.CallStackView_SortByThreadName, IAction.AS_CHECK_BOX) {
}
section.put(SORT_OPTION_KEY, sortOption.name());
loadSortOption();
- if (fEntryList == null) {
+ List<TimeGraphEntry> entryList = getEntryList(getTrace());
+ if (entryList == null) {
return;
}
- for (TraceEntry traceEntry : fEntryList) {
+ for (TimeGraphEntry traceEntry : entryList) {
traceEntry.sortChildren(fThreadComparator);
}
refresh();
}
- /**
- * Toolbar icon to import the function address-to-name mapping binary file.
- */
- private Action getImportBinaryAction() {
- if (fImportBinaryFileMappingAction != null) {
- return fImportBinaryFileMappingAction;
+ private Action getConfigureSymbolsAction() {
+ if (fConfigureSymbolsAction != null) {
+ return fConfigureSymbolsAction;
}
- fImportBinaryFileMappingAction = new AbstractImportFileMappingAction(Messages.CallStackView_ImportBinaryFileDialogTitle) {
+ fConfigureSymbolsAction = new Action(Messages.CallStackView_ConfigureSymbolProvidersText) {
@Override
- Map<String, String> doMapping(File file) {
- return FunctionNameMapper.mapFromBinaryFile(file);
+ public void run() {
+ SymbolProviderConfigDialog dialog = new SymbolProviderConfigDialog(getSite().getShell(), getProviderPages());
+ if (dialog.open() == IDialogConstants.OK_ID) {
+ getPresentationProvider().resetFunctionNames();
+ refresh();
+ }
}
};
- fImportBinaryFileMappingAction.setText(Messages.CallStackView_ImportBinaryFileButtonText);
- fImportBinaryFileMappingAction.setToolTipText(Messages.CallStackView_ImportBinaryFileButtonTooltip);
- fImportBinaryFileMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_BINARY_ICON_PATH));
+ fConfigureSymbolsAction.setToolTipText(Messages.CallStackView_ConfigureSymbolProvidersTooltip);
+ fConfigureSymbolsAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_BINARY_ICON_PATH));
- return fImportBinaryFileMappingAction;
- }
+ /*
+ * The updateConfigureSymbolsAction() method (called by refresh()) will
+ * set the action to true if applicable after the symbol provider has
+ * been properly loaded.
+ */
+ fConfigureSymbolsAction.setEnabled(false);
- String getFunctionName(String address) {
- if (fNameMapping == null) {
- /* No mapping available, just print the addresses */
- return address;
- }
- String ret = fNameMapping.get(address);
- if (ret == null) {
- /*
- * We didn't find this address in the mapping file, just use the
- * address
- */
- return address;
- }
- return ret;
+ return fConfigureSymbolsAction;
}
/**
- * @since 1.0
+ * @return an array of {@link ISymbolProviderPreferencePage} that will
+ * configure the current traces
*/
- @Override
- public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
- if (fTimeGraphCombo == null) {
- return null;
+ private ISymbolProviderPreferencePage[] getProviderPages() {
+ List<ISymbolProviderPreferencePage> pages = new ArrayList<>();
+ ITmfTrace trace = getTrace();
+ if (trace != null) {
+ for (ITmfTrace subTrace : getTracesToBuild(trace)) {
+ ISymbolProvider provider = fSymbolProviders.get(subTrace);
+ if (provider != null) {
+ ISymbolProviderPreferencePage page = provider.createPreferencePage();
+ if (page != null) {
+ pages.add(page);
+ }
+ }
+ }
}
- return fTimeGraphCombo.getTimeViewAlignmentInfo();
+ return pages.toArray(new ISymbolProviderPreferencePage[pages.size()]);
}
/**
- * @since 1.0
+ * Update the enable status of the configure symbols action
*/
- @Override
- public int getAvailableWidth(int requestedOffset) {
- if (fTimeGraphCombo == null) {
- return 0;
- }
- return fTimeGraphCombo.getAvailableWidth(requestedOffset);
+ private void updateConfigureSymbolsAction() {
+ ISymbolProviderPreferencePage[] providerPages = getProviderPages();
+ getConfigureSymbolsAction().setEnabled(providerPages.length > 0);
}
- /**
- * @since 1.0
- */
- @Override
- public void performAlign(int offset, int width) {
- fTimeGraphCombo.performAlign(offset, width);
- }
}