tmf: Split the state system in a separate plugin
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / callstack / CallStackView.java
index 038fd723db753fa2ed2e1cd80706b0ee8d5d4678..1c7cc98ee477dbd3a4c8f2c661d9c019c12b6fed 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013 Ericsson
+ * Copyright (c) 2013, 2014 Ericsson
  *
  * 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.linuxtools.tmf.ui.views.callstack;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 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.Nullable;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IStatusLineManager;
 import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.action.Separator;
 import org.eclipse.jface.util.IPropertyChangeListener;
@@ -37,28 +44,28 @@ import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.linuxtools.internal.tmf.ui.Activator;
 import org.eclipse.linuxtools.internal.tmf.ui.ITmfImageConstants;
 import org.eclipse.linuxtools.internal.tmf.ui.Messages;
+import org.eclipse.linuxtools.statesystem.core.ITmfStateSystem;
+import org.eclipse.linuxtools.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.StateValueTypeException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.TimeRangeException;
+import org.eclipse.linuxtools.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.linuxtools.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.linuxtools.statesystem.core.statevalue.ITmfStateValue.Type;
 import org.eclipse.linuxtools.tmf.core.callstack.CallStackStateProvider;
-import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTimestamp;
-import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
-import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
-import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
-import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
-import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
-import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
-import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
-import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue.Type;
 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.timestamp.TmfNanoTimestamp;
 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestampDelta;
 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
-import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
+import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
 import org.eclipse.linuxtools.tmf.ui.editors.ITmfTraceEditor;
 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
@@ -82,6 +89,7 @@ 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.ui.IActionBars;
 import org.eclipse.ui.IEditorPart;
 
@@ -105,7 +113,7 @@ public class CallStackView extends TmfView {
      */
     private enum State { IDLE, BUSY, PENDING }
 
-    private final String[] COLUMN_NAMES = new String[] {
+    private static final String[] COLUMN_NAMES = new String[] {
             Messages.CallStackView_FunctionColumn,
             Messages.CallStackView_DepthColumn,
             Messages.CallStackView_EntryTimeColumn,
@@ -113,30 +121,46 @@ public class CallStackView extends TmfView {
             Messages.CallStackView_DurationColumn
     };
 
+    private static final int[] COLUMN_WIDTHS = new int[] {
+            200,
+            50,
+            120,
+            120,
+            120
+    };
+
+    // Fraction of a function duration to be added as spacing
+    private static final double SPACING_RATIO = 0.01;
+
     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$
+
     // ------------------------------------------------------------------------
     // Fields
     // ------------------------------------------------------------------------
 
     // The time graph combo
-    TimeGraphCombo fTimeGraphCombo;
+    private TimeGraphCombo fTimeGraphCombo;
 
     // The selected trace
     private ITmfTrace fTrace;
 
     // The selected thread map
-    final private HashMap<ITmfTrace, String> fSelectedThreadMap = new HashMap<ITmfTrace, String>();
+    private final Map<ITmfTrace, String> fSelectedThreadMap = new HashMap<>();
 
     // The time graph entry list
-    private ArrayList<ThreadEntry> fEntryList;
+    private List<ThreadEntry> fEntryList;
 
     // The trace to entry list hash map
-    final private HashMap<ITmfTrace, ArrayList<ThreadEntry>> fEntryListMap = new HashMap<ITmfTrace, ArrayList<ThreadEntry>>();
+    private final Map<ITmfTrace, ArrayList<ThreadEntry>> fEntryListMap = new HashMap<>();
 
     // The trace to build thread hash map
-    final private HashMap<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<ITmfTrace, BuildThread>();
+    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;
@@ -159,6 +183,9 @@ public class CallStackView extends TmfView {
     // The previous item action
     private Action fPreviousItemAction;
 
+    /** The action to import a function-name mapping file */
+    private Action fImportMappingAction;
+
     // The zoom thread
     private ZoomThread fZoomThread;
 
@@ -166,7 +193,7 @@ public class CallStackView extends TmfView {
     private State fRedrawState = State.IDLE;
 
     // The redraw synchronization object
-    final private Object fSyncObj = new Object();
+    private final Object fSyncObj = new Object();
 
     // The saved time sync. signal used when switching off the pinning of a view
     private TmfTimeSynchSignal fSavedTimeSyncSignal;
@@ -179,8 +206,6 @@ public class CallStackView extends TmfView {
     // ------------------------------------------------------------------------
 
     private class ThreadEntry implements ITimeGraphEntry {
-        // The Trace
-        private final ITmfTrace fThreadTrace;
         // The start time
         private final long fTraceStartTime;
         // The end time
@@ -191,14 +216,17 @@ public class CallStackView extends TmfView {
         private final String fName;
         // The thread attribute quark
         private final int fThreadQuark;
+        // The state system from which this entry comes
+        private final ITmfStateSystem fSS;
 
         public ThreadEntry(ITmfTrace trace, String name, int threadQuark, long startTime, long endTime) {
-            fThreadTrace = trace;
-            fChildren = new ArrayList<CallStackEntry>();
+            fChildren = new ArrayList<>();
             fName = name;
             fTraceStartTime = startTime;
             fTraceEndTime = endTime;
             fThreadQuark = threadQuark;
+
+            fSS = getCallStackStateSystem(trace);
         }
 
         @Override
@@ -209,15 +237,18 @@ public class CallStackView extends TmfView {
         @Override
         public boolean hasChildren() {
             if (fChildren == null) {
-                ITmfStateSystem ss = fThreadTrace.getStateSystems().get(CallStackStateProvider.ID);
+                ITmfStateSystem ss = getStateSystem();
+                if (ss == null) {
+                    return false;
+                }
                 try {
                     int eventStackQuark = ss.getQuarkRelative(fThreadQuark, CallStackStateProvider.CALL_STACK);
                     ITmfStateInterval eventStackInterval = ss.querySingleState(ss.getStartTime(), eventStackQuark);
                     return ! eventStackInterval.getStateValue().isNull() || eventStackInterval.getEndTime() != ss.getCurrentEndTime();
                 } catch (AttributeNotFoundException e) {
-                    e.printStackTrace();
+                    Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                 } catch (TimeRangeException e) {
-                    e.printStackTrace();
+                    Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                 } catch (StateSystemDisposedException e) {
                     /* Ignored */
                 }
@@ -264,8 +295,9 @@ public class CallStackView extends TmfView {
             return fThreadQuark;
         }
 
-        public ITmfTrace getTrace() {
-            return fThreadTrace;
+        @Nullable
+        public ITmfStateSystem getStateSystem() {
+            return fSS;
         }
 
         public void addChild(CallStackEntry entry) {
@@ -353,26 +385,18 @@ public class CallStackView extends TmfView {
                 CallStackEntry entry = (CallStackEntry) element;
                 if (columnIndex == 0) {
                     return entry.getFunctionName();
-                } else if (columnIndex == 1) {
-                    if (entry.getFunctionName().length() > 0) {
-                        int depth = entry.getStackLevel();
-                        return Integer.toString(depth);
-                    }
-                } else if (columnIndex == 2) {
-                    if (entry.getFunctionName().length() > 0) {
-                        ITmfTimestamp ts = new TmfTimestamp(entry.getStartTime(), ITmfTimestamp.NANOSECOND_SCALE);
-                        return ts.toString();
-                    }
-                } else if (columnIndex == 3) {
-                    if (entry.getFunctionName().length() > 0) {
-                        ITmfTimestamp ts = new TmfTimestamp(entry.getEndTime(), ITmfTimestamp.NANOSECOND_SCALE);
-                        return ts.toString();
-                    }
-                } else if (columnIndex == 4) {
-                    if (entry.getFunctionName().length() > 0) {
-                        ITmfTimestamp ts = new TmfTimestampDelta(entry.getEndTime() - entry.getStartTime(), ITmfTimestamp.NANOSECOND_SCALE);
-                        return ts.toString();
-                    }
+                } else if (columnIndex == 1 && entry.getFunctionName().length() > 0) {
+                    int depth = entry.getStackLevel();
+                    return Integer.toString(depth);
+                } else if (columnIndex == 2 && entry.getFunctionName().length() > 0) {
+                    ITmfTimestamp ts = new TmfTimestamp(entry.getStartTime(), ITmfTimestamp.NANOSECOND_SCALE);
+                    return ts.toString();
+                } else if (columnIndex == 3 && entry.getFunctionName().length() > 0) {
+                    ITmfTimestamp ts = new TmfTimestamp(entry.getEndTime(), ITmfTimestamp.NANOSECOND_SCALE);
+                    return ts.toString();
+                } else if (columnIndex == 4 && entry.getFunctionName().length() > 0) {
+                    ITmfTimestamp ts = new TmfTimestampDelta(entry.getEndTime() - entry.getStartTime(), ITmfTimestamp.NANOSECOND_SCALE);
+                    return ts.toString();
                 }
             }
             return ""; //$NON-NLS-1$
@@ -404,12 +428,12 @@ public class CallStackView extends TmfView {
     }
 
     private class ZoomThread extends Thread {
-        private final ArrayList<ThreadEntry> fZoomEntryList;
+        private final List<ThreadEntry> fZoomEntryList;
         private final long fZoomStartTime;
         private final long fZoomEndTime;
         private final IProgressMonitor fMonitor;
 
-        public ZoomThread(ArrayList<ThreadEntry> entryList, long startTime, long endTime) {
+        public ZoomThread(List<ThreadEntry> entryList, long startTime, long endTime) {
             super("ResourcesView zoom"); //$NON-NLS-1$
             fZoomEntryList = entryList;
             fZoomStartTime = startTime;
@@ -424,8 +448,12 @@ public class CallStackView extends TmfView {
             }
             long resolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
             for (ThreadEntry threadEntry : fZoomEntryList) {
-                ITmfStateSystem ss = threadEntry.fThreadTrace.getStateSystems().get(CallStackStateProvider.ID);
-                if (ss == null || !ss.waitUntilBuilt()) {
+                ITmfStateSystem ss = threadEntry.getStateSystem();
+                if (ss == null) {
+                    continue;
+                }
+                ss.waitUntilBuilt();
+                if (ss.isCancelled()) {
                     continue;
                 }
                 for (ITimeGraphEntry child : threadEntry.getChildren()) {
@@ -477,13 +505,13 @@ public class CallStackView extends TmfView {
 
         fTimeGraphCombo.setTreeColumns(COLUMN_NAMES);
 
-        fTimeGraphCombo.getTreeViewer().getTree().getColumn(0).setWidth(200);
-        fTimeGraphCombo.getTreeViewer().getTree().getColumn(1).setWidth(50);
-        fTimeGraphCombo.getTreeViewer().getTree().getColumn(2).setWidth(120);
-        fTimeGraphCombo.getTreeViewer().getTree().getColumn(3).setWidth(120);
-        fTimeGraphCombo.getTreeViewer().getTree().getColumn(4).setWidth(120);
+        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.setTimeGraphProvider(new CallStackPresentationProvider());
+        fTimeGraphCombo.setTimeGraphProvider(new CallStackPresentationProvider(this));
         fTimeGraphCombo.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
 
         fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
@@ -491,9 +519,8 @@ public class CallStackView extends TmfView {
             public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
                 long startTime = event.getStartTime();
                 long endTime = event.getEndTime();
-                TmfTimeRange range = new TmfTimeRange(new CtfTmfTimestamp(startTime), new CtfTmfTimestamp(endTime));
-                TmfTimestamp time = new CtfTmfTimestamp(fTimeGraphCombo.getTimeGraphViewer().getSelectedTime());
-                broadcast(new TmfRangeSynchSignal(CallStackView.this, range, time));
+                TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
+                broadcast(new TmfRangeSynchSignal(CallStackView.this, range));
                 startZoomThread(startTime, endTime);
             }
         });
@@ -501,9 +528,10 @@ public class CallStackView extends TmfView {
         fTimeGraphCombo.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
             @Override
             public void timeSelected(TimeGraphTimeEvent event) {
-                long time = event.getTime();
-                selectTime(time);
-                broadcast(new TmfTimeSynchSignal(CallStackView.this, new CtfTmfTimestamp(time)));
+                long beginTime = event.getBeginTime();
+                long endTime = event.getEndTime();
+                selectTime(beginTime);
+                broadcast(new TmfTimeSynchSignal(CallStackView.this, new TmfNanoTimestamp(beginTime), new TmfNanoTimestamp(endTime)));
             }
         });
 
@@ -526,12 +554,11 @@ public class CallStackView extends TmfView {
                     if (entry.getFunctionName().length() > 0) {
                         long startTime = entry.getStartTime();
                         long endTime = entry.getEndTime();
-                        long spacingTime = (long) ((endTime - startTime) * 0.01);
+                        long spacingTime = (long) ((endTime - startTime) * SPACING_RATIO);
                         startTime -= spacingTime;
                         endTime += spacingTime;
-                        TmfTimeRange range = new TmfTimeRange(new CtfTmfTimestamp(startTime), new CtfTmfTimestamp(endTime));
-                        TmfTimestamp time = new CtfTmfTimestamp(fTimeGraphCombo.getTimeGraphViewer().getSelectedTime());
-                        broadcast(new TmfRangeSynchSignal(CallStackView.this, range, time));
+                        TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
+                        broadcast(new TmfRangeSynchSignal(CallStackView.this, range));
                         fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
                         startZoomThread(startTime, endTime);
                     }
@@ -550,12 +577,11 @@ public class CallStackView extends TmfView {
                         CallStackEvent event = (CallStackEvent) o;
                         long startTime = event.getTime();
                         long endTime = startTime + event.getDuration();
-                        long spacingTime = (long) ((endTime - startTime) * 0.01);
+                        long spacingTime = (long) ((endTime - startTime) * SPACING_RATIO);
                         startTime -= spacingTime;
                         endTime += spacingTime;
-                        TmfTimeRange range = new TmfTimeRange(new CtfTmfTimestamp(startTime), new CtfTmfTimestamp(endTime));
-                        TmfTimestamp time = new CtfTmfTimestamp(fTimeGraphCombo.getTimeGraphViewer().getSelectedTime());
-                        broadcast(new TmfRangeSynchSignal(CallStackView.this, range, time));
+                        TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
+                        broadcast(new TmfRangeSynchSignal(CallStackView.this, range));
                         fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
                         startZoomThread(startTime, endTime);
                     }
@@ -563,6 +589,9 @@ public class CallStackView extends TmfView {
             }
         });
 
+        IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
+        fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
+
         // View Action Handling
         makeActions();
         contributeToActionBars();
@@ -645,33 +674,39 @@ public class CallStackView extends TmfView {
     @TmfSignalHandler
     public void synchToTime(final TmfTimeSynchSignal signal) {
 
-        fSavedTimeSyncSignal = isPinned() ? new TmfTimeSynchSignal(signal.getSource(), signal.getCurrentTime()) : null;
+        fSavedTimeSyncSignal = isPinned() ? new TmfTimeSynchSignal(signal.getSource(), signal.getBeginTime(), signal.getEndTime()) : null;
 
         if (signal.getSource() == this || fTrace == null || isPinned()) {
             return;
         }
-        final long time = signal.getCurrentTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+        final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+        final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
         Display.getDefault().asyncExec(new Runnable() {
             @Override
             public void run() {
                 if (fTimeGraphCombo.isDisposed()) {
                     return;
                 }
-                selectTime(time);
+                if (beginTime == endTime) {
+                    fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(beginTime, true);
+                } else {
+                    fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(beginTime, endTime);
+                }
+                selectTime(beginTime);
                 startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
                 if (fEntryList == null) {
                     return;
                 }
                 TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
                 for (ThreadEntry threadEntry : fEntryList) {
-                    ITmfStateSystem ss = threadEntry.getTrace().getStateSystems().get(CallStackStateProvider.ID);
-                    if (ss == null || time < ss.getStartTime() || time > ss.getCurrentEndTime()) {
+                    ITmfStateSystem ss = threadEntry.getStateSystem();
+                    if (ss == null || beginTime < ss.getStartTime() || beginTime > ss.getCurrentEndTime()) {
                         continue;
                     }
                     try {
                         int quark = ss.getQuarkRelative(threadEntry.getThreadQuark(), CallStackStateProvider.CALL_STACK);
-                        ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
-                        if (time == stackInterval.getStartTime()) {
+                        ITmfStateInterval stackInterval = ss.querySingleState(beginTime, quark);
+                        if (beginTime == stackInterval.getStartTime()) {
                             int stackLevel = stackInterval.getStateValue().unboxInt();
                             CallStackEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
                             fTimeGraphCombo.setSelection(selectedEntry);
@@ -679,13 +714,13 @@ public class CallStackView extends TmfView {
                             break;
                         }
                     } catch (AttributeNotFoundException e) {
-                        e.printStackTrace();
+                        Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                     } catch (TimeRangeException e) {
-                        e.printStackTrace();
+                        Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                     } catch (StateSystemDisposedException e) {
-                        e.printStackTrace();
+                        Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                     } catch (StateValueTypeException e) {
-                        e.printStackTrace();
+                        Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                     }
                 }
             }
@@ -703,7 +738,7 @@ public class CallStackView extends TmfView {
 
         if (isPinned()) {
             fSavedRangeSyncSignal =
-                    new TmfRangeSynchSignal(signal.getSource(), new TmfTimeRange(signal.getCurrentRange().getStartTime(), signal.getCurrentRange().getEndTime()), signal.getCurrentTime());
+                    new TmfRangeSynchSignal(signal.getSource(), new TmfTimeRange(signal.getCurrentRange().getStartTime(), signal.getCurrentRange().getEndTime()));
 
             fSavedTimeSyncSignal = null;
         }
@@ -716,7 +751,6 @@ public class CallStackView extends TmfView {
         }
         final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
         final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
-        final long time = signal.getCurrentTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
         Display.getDefault().asyncExec(new Runnable() {
             @Override
             public void run() {
@@ -724,7 +758,6 @@ public class CallStackView extends TmfView {
                     return;
                 }
                 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
-                fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(time, false);
                 startZoomThread(startTime, endTime);
             }
         });
@@ -733,6 +766,7 @@ public class CallStackView extends TmfView {
     // ------------------------------------------------------------------------
     // Internal
     // ------------------------------------------------------------------------
+
     private void loadTrace() {
         synchronized (fEntryListMap) {
             fEntryList = fEntryListMap.get(fTrace);
@@ -753,23 +787,20 @@ public class CallStackView extends TmfView {
     private void buildThreadList(final ITmfTrace trace, IProgressMonitor monitor) {
         fStartTime = Long.MAX_VALUE;
         fEndTime = Long.MIN_VALUE;
-        ITmfTrace[] traces;
-        if (trace instanceof TmfExperiment) {
-            TmfExperiment experiment = (TmfExperiment) trace;
-            traces = experiment.getTraces();
-        } else {
-            traces = new ITmfTrace[] { trace };
-        }
-        ArrayList<ThreadEntry> entryList = new ArrayList<ThreadEntry>();
+        ITmfTrace[] traces = TmfTraceManager.getTraceSet(trace);
+        ArrayList<ThreadEntry> entryList = new ArrayList<>();
         for (ITmfTrace aTrace : traces) {
             if (monitor.isCanceled()) {
                 return;
             }
-            ITmfStateSystem ss = aTrace.getStateSystems().get(CallStackStateProvider.ID);
-            if (ss == null || !ss.waitUntilBuilt()) {
-                String threadName = Messages.CallStackView_StackInfoNotAvailable + ' ' + '(' + aTrace.getName() + ')';
-                ThreadEntry threadEntry = new ThreadEntry(aTrace, threadName, -1, 0, 0);
-                entryList.add(threadEntry);
+            ITmfStateSystem ss = getCallStackStateSystem(aTrace);
+            if (ss == null) {
+                addUnavailableEntry(aTrace, entryList);
+                continue;
+            }
+            ss.waitUntilBuilt();
+            if (ss.isCancelled()) {
+                addUnavailableEntry(aTrace, entryList);
                 continue;
             }
             long startTime = ss.getStartTime();
@@ -795,12 +826,12 @@ public class CallStackView extends TmfView {
                         threadEntry.addChild(callStackEntry);
                     }
                 } catch (AttributeNotFoundException e) {
-                    e.printStackTrace();
+                    Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                 }
             }
         }
         synchronized (fEntryListMap) {
-            fEntryListMap.put(trace, (ArrayList<ThreadEntry>) entryList.clone());
+            fEntryListMap.put(trace, new ArrayList<>(entryList));
         }
         if (trace == fTrace) {
             refresh();
@@ -815,8 +846,17 @@ public class CallStackView extends TmfView {
         }
     }
 
+    private void addUnavailableEntry(ITmfTrace trace, List<ThreadEntry> list) {
+        String threadName = Messages.CallStackView_StackInfoNotAvailable + ' ' + '(' + trace.getName() + ')';
+        ThreadEntry threadEntry = new ThreadEntry(trace, threadName, -1, 0, 0);
+        list.add(threadEntry);
+    }
+
     private void buildStatusEvents(ITmfTrace trace, CallStackEntry entry, IProgressMonitor monitor) {
-        ITmfStateSystem ss = entry.getTrace().getStateSystems().get(CallStackStateProvider.ID);
+        ITmfStateSystem ss = getCallStackStateSystem(entry.getTrace());
+        if (ss == null) {
+            return;
+        }
         long start = ss.getStartTime();
         long end = ss.getCurrentEndTime() + 1;
         long resolution = Math.max(1, (end - start) / fDisplayWidth);
@@ -833,7 +873,10 @@ public class CallStackView extends TmfView {
     private static List<ITimeEvent> getEventList(CallStackEntry entry,
             long startTime, long endTime, long resolution,
             IProgressMonitor monitor) {
-        ITmfStateSystem ss = entry.getTrace().getStateSystems().get(CallStackStateProvider.ID);
+        ITmfStateSystem ss = getCallStackStateSystem(entry.getTrace());
+        if (ss == null) {
+            return null;
+        }
         long start = Math.max(startTime, ss.getStartTime());
         long end = Math.min(endTime, ss.getCurrentEndTime() + 1);
         if (end <= start) {
@@ -842,7 +885,7 @@ public class CallStackView extends TmfView {
         List<ITimeEvent> eventList = null;
         try {
             List<ITmfStateInterval> stackIntervals = ss.queryHistoryRange(entry.getQuark(), start, end - 1, resolution, monitor);
-            eventList = new ArrayList<ITimeEvent>(stackIntervals.size());
+            eventList = new ArrayList<>(stackIntervals.size());
             long lastEndTime = -1;
             boolean lastIsNull = true;
             for (ITmfStateInterval statusInterval : stackIntervals) {
@@ -852,23 +895,32 @@ public class CallStackView extends TmfView {
                 long time = statusInterval.getStartTime();
                 long duration = statusInterval.getEndTime() - time + 1;
                 if (!statusInterval.getStateValue().isNull()) {
-                    final int MODULO = CallStackPresentationProvider.NUM_COLORS / 2;
-                    int value = statusInterval.getStateValue().toString().hashCode() % MODULO + MODULO;
+                    final int modulo = CallStackPresentationProvider.NUM_COLORS / 2;
+                    int value = statusInterval.getStateValue().toString().hashCode() % modulo + modulo;
                     eventList.add(new CallStackEvent(entry, time, duration, value));
                     lastIsNull = false;
                 } else {
-                    if (lastEndTime != time && lastEndTime != -1 && lastIsNull) {
-                        eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
+                    if (lastEndTime == -1) {
+                        // add null event if it intersects the start time
+                        eventList.add(new NullTimeEvent(entry, time, duration));
+                    } else {
+                        if (lastEndTime != time && lastIsNull) {
+                            // add unknown event if between two null states
+                            eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
+                        }
+                        if (time + duration >= endTime) {
+                            // add null event if it intersects the end time
+                            eventList.add(new NullTimeEvent(entry, time, duration));
+                        }
                     }
-                    eventList.add(new NullTimeEvent(entry, time, duration));
                     lastIsNull = true;
                 }
                 lastEndTime = time + duration;
             }
         } catch (AttributeNotFoundException e) {
-            e.printStackTrace();
+            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
         } catch (TimeRangeException e) {
-            e.printStackTrace();
+            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
         } catch (StateSystemDisposedException e) {
             /* Ignored */
         }
@@ -879,10 +931,13 @@ public class CallStackView extends TmfView {
         if (fEntryList == null) {
             return;
         }
-        fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(time, true);
         for (ThreadEntry threadEntry : fEntryList) {
-            ITmfStateSystem ss = threadEntry.fThreadTrace.getStateSystems().get(CallStackStateProvider.ID);
-            if (ss == null || !ss.waitUntilBuilt()) {
+            ITmfStateSystem ss = threadEntry.getStateSystem();
+            if (ss == null) {
+                continue;
+            }
+            ss.waitUntilBuilt();
+            if (ss.isCancelled()) {
                 continue;
             }
             long queryTime = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), time));
@@ -893,7 +948,8 @@ public class CallStackView extends TmfView {
                     String name = ""; //$NON-NLS-1$
                     try {
                         if (nameValue.getType() == Type.STRING) {
-                            name = nameValue.unboxStr();
+                            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) {
@@ -907,16 +963,15 @@ public class CallStackView extends TmfView {
                         callStackEntry.setEndTime(stackLevelInterval.getEndTime() + 1);
                     }
                 } catch (AttributeNotFoundException e) {
-                    e.printStackTrace();
+                    Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                 } catch (TimeRangeException e) {
-                    e.printStackTrace();
+                    Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                 } catch (StateSystemDisposedException e) {
-                    e.printStackTrace();
+                    Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                 }
             }
         }
         fTimeGraphCombo.refresh();
-        fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(time, true);
     }
 
     private void refresh() {
@@ -930,19 +985,21 @@ public class CallStackView extends TmfView {
                 synchronized (fEntryListMap) {
                     fEntryList = fEntryListMap.get(fTrace);
                     if (fEntryList == null) {
-                        fEntryList = new ArrayList<ThreadEntry>();
+                        fEntryList = new ArrayList<>();
                     }
                     entries = fEntryList.toArray(new ITimeGraphEntry[0]);
                 }
                 fTimeGraphCombo.setInput(entries);
                 fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
 
-                long timestamp = fTrace == null ? 0 : fTraceManager.getCurrentTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+                long selectionBeginTime = fTrace == null ? 0 : fTraceManager.getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+                long selectionEndTime = fTrace == null ? 0 : fTraceManager.getSelectionEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
                 long startTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
                 long endTime = fTrace == null ? 0 : fTraceManager.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
                 startTime = Math.max(startTime, fStartTime);
                 endTime = Math.min(endTime, fEndTime);
-                selectTime(timestamp);
+                fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
+                selectTime(selectionBeginTime);
                 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
                 startZoomThread(startTime, endTime);
             }
@@ -1004,17 +1061,15 @@ public class CallStackView extends TmfView {
         fPinAction.addPropertyChangeListener(new IPropertyChangeListener(){
             @Override
             public void propertyChange(PropertyChangeEvent event) {
-                if (IAction.CHECKED.equals(event.getProperty())) {
-                    if (!isPinned()) {
-                        if (fSavedRangeSyncSignal != null) {
-                            synchToRange(fSavedRangeSyncSignal);
-                            fSavedRangeSyncSignal = null;
-                        }
+                if (IAction.CHECKED.equals(event.getProperty()) && !isPinned()) {
+                    if (fSavedRangeSyncSignal != null) {
+                        synchToRange(fSavedRangeSyncSignal);
+                        fSavedRangeSyncSignal = null;
+                    }
 
-                        if (fSavedTimeSyncSignal != null) {
-                            synchToTime(fSavedTimeSyncSignal);
-                            fSavedTimeSyncSignal = null;
-                        }
+                    if (fSavedTimeSyncSignal != null) {
+                        synchToTime(fSavedTimeSyncSignal);
+                        fSavedTimeSyncSignal = null;
                     }
                 }
             }
@@ -1022,6 +1077,7 @@ public class CallStackView extends TmfView {
     }
 
     private void fillLocalToolBar(IToolBarManager manager) {
+        manager.add(getImportMappingAction());
         manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction());
         manager.add(getPreviousEventAction());
         manager.add(getNextEventAction());
@@ -1048,8 +1104,11 @@ public class CallStackView extends TmfView {
                         try {
                             CallStackEntry callStackEntry = (CallStackEntry) entry;
                             ITmfTrace trace = callStackEntry.getTrace();
-                            ITmfStateSystem ss = trace.getStateSystems().get(CallStackStateProvider.ID);
-                            long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectedTime()));
+                            ITmfStateSystem ss = getCallStackStateSystem(trace);
+                            if (ss == null) {
+                                return;
+                            }
+                            long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
                             ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
                             int quark = ss.getQuarkRelative(threadEntry.getThreadQuark(), CallStackStateProvider.CALL_STACK);
                             ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
@@ -1061,14 +1120,15 @@ public class CallStackView extends TmfView {
                             fTimeGraphCombo.setSelection(selectedEntry);
                             viewer.getTimeGraphControl().fireSelectionChanged();
                             startZoomThread(viewer.getTime0(), viewer.getTime1());
+
                         } catch (AttributeNotFoundException e) {
-                            e.printStackTrace();
+                            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                         } catch (TimeRangeException e) {
-                            e.printStackTrace();
+                            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                         } catch (StateSystemDisposedException e) {
-                            e.printStackTrace();
+                            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                         } catch (StateValueTypeException e) {
-                            e.printStackTrace();
+                            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                         }
                     }
                 }
@@ -1098,8 +1158,11 @@ public class CallStackView extends TmfView {
                         try {
                             CallStackEntry callStackEntry = (CallStackEntry) entry;
                             ITmfTrace trace = callStackEntry.getTrace();
-                            ITmfStateSystem ss = trace.getStateSystems().get(CallStackStateProvider.ID);
-                            long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectedTime()));
+                            ITmfStateSystem ss = getCallStackStateSystem(trace);
+                            if (ss == null) {
+                                return;
+                            }
+                            long time = Math.max(ss.getStartTime(), Math.min(ss.getCurrentEndTime(), viewer.getSelectionBegin()));
                             ThreadEntry threadEntry = (ThreadEntry) callStackEntry.getParent();
                             int quark = ss.getQuarkRelative(threadEntry.getThreadQuark(), CallStackStateProvider.CALL_STACK);
                             ITmfStateInterval stackInterval = ss.querySingleState(time, quark);
@@ -1112,14 +1175,15 @@ public class CallStackView extends TmfView {
                             fTimeGraphCombo.setSelection(selectedEntry);
                             viewer.getTimeGraphControl().fireSelectionChanged();
                             startZoomThread(viewer.getTime0(), viewer.getTime1());
+
                         } catch (AttributeNotFoundException e) {
-                            e.printStackTrace();
+                            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                         } catch (TimeRangeException e) {
-                            e.printStackTrace();
+                            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                         } catch (StateSystemDisposedException e) {
-                            e.printStackTrace();
+                            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                         } catch (StateValueTypeException e) {
-                            e.printStackTrace();
+                            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                         }
                     }
                 }
@@ -1133,4 +1197,106 @@ public class CallStackView extends TmfView {
         return fPrevEventAction;
     }
 
+    @Nullable
+    static ITmfStateSystem getCallStackStateSystem(ITmfTrace trace) {
+        /*
+         * Since we cannot know the exact analysis ID (in separate plugins), we
+         * will search using the analysis type.
+         */
+        Iterable<AbstractCallStackAnalysis> modules =
+                trace.getAnalysisModulesOfClass(AbstractCallStackAnalysis.class);
+        Iterator<AbstractCallStackAnalysis> it = modules.iterator();
+        if (!it.hasNext()) {
+            /* This trace does not provide a call-stack analysis */
+            return null;
+        }
+
+        /*
+         * We only look at the first module we find.
+         *
+         * TODO Handle the advanced case where one trace provides more than one
+         * call-stack analysis.
+         */
+        AbstractCallStackAnalysis module = it.next();
+        /* This analysis is not automatic, we need to schedule it on-demand */
+        module.schedule();
+        module.waitForInitialization();
+        ITmfStateSystem ss = module.getStateSystem();
+        if (ss == null) {
+            /* If we've waited for initialization, 'ss' should not be null */
+            throw new IllegalStateException();
+        }
+        return ss;
+    }
+
+    // ------------------------------------------------------------------------
+    // Methods related to function name mapping
+    // ------------------------------------------------------------------------
+
+    /**
+     * Toolbar icon to import the function address-to-name mapping file.
+     */
+    private Action getImportMappingAction() {
+        if (fImportMappingAction != null) {
+            return fImportMappingAction;
+        }
+        fImportMappingAction = new Action() {
+            @Override
+            public void run() {
+                FileDialog dialog = new FileDialog(getViewSite().getShell());
+                dialog.setText(Messages.CallStackView_ImportMappingDialogTitle);
+                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 ImportMappingJob(new File(filePath));
+                job.schedule();
+            }
+        };
+
+        fImportMappingAction.setText(Messages.CallStackView_ImportMappingButtonText);
+        fImportMappingAction.setToolTipText(Messages.CallStackView_ImportMappingButtonTooltip);
+        fImportMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_MAPPING_ICON_PATH));
+
+        return fImportMappingAction;
+    }
+
+    private class ImportMappingJob extends Job {
+        private final File fMappingFile;
+
+        public ImportMappingJob(File mappingFile) {
+            super(Messages.CallStackView_ImportMappingJobName);
+            fMappingFile = mappingFile;
+        }
+
+        @Override
+        public IStatus run(IProgressMonitor monitor) {
+            fNameMapping = FunctionNameMapper.mapFromNmTextFile(fMappingFile);
+
+            /* Refresh the time graph and the list of entries */
+            buildThreadList(fTrace, new NullProgressMonitor());
+            redraw();
+
+            return Status.OK_STATUS;
+        }
+    }
+
+    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;
+    }
+
 }
This page took 0.04906 seconds and 5 git commands to generate.