tmf: Rename "Next/Previous Event" action to "Next/Previous State Change"
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / callstack / CallStackView.java
index 8efa4881f0883df8d96e8202c50fe7ebbb0f5b73..f5eb13beeb1bbc75b1145daa147e0404c861f514 100644 (file)
@@ -21,6 +21,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Consumer;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.annotation.NonNull;
@@ -64,7 +65,6 @@ import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
 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;
@@ -122,6 +122,7 @@ public class CallStackView extends AbstractTimeGraphView {
     // 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$
 
@@ -173,6 +174,10 @@ public class CallStackView extends AbstractTimeGraphView {
     // 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
     // ------------------------------------------------------------------------
@@ -188,19 +193,28 @@ public class CallStackView extends AbstractTimeGraphView {
         }
     }
 
+    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 call stack quark
-        private final int fCallStackQuark;
-        // The state system from which this entry comes
-        private final ITmfStateSystem fSS;
         // 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
@@ -208,18 +222,9 @@ public class CallStackView extends AbstractTimeGraphView {
             return false;
         }
 
-        public int getCallStackQuark() {
-            return fCallStackQuark;
-        }
-
         public long getThreadId() {
             return fThreadId;
         }
-
-        @Nullable
-        public ITmfStateSystem getStateSystem() {
-            return fSS;
-        }
     }
 
     private class CallStackComparator implements Comparator<ITimeGraphEntry> {
@@ -227,6 +232,8 @@ public class CallStackView extends AbstractTimeGraphView {
         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;
         }
@@ -255,10 +262,13 @@ public class CallStackView extends AbstractTimeGraphView {
 
         @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;
         }
     }
 
@@ -281,7 +291,9 @@ public class CallStackView extends AbstractTimeGraphView {
         @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;
@@ -303,10 +315,10 @@ public class CallStackView extends AbstractTimeGraphView {
                     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);
@@ -385,7 +397,7 @@ public class CallStackView extends AbstractTimeGraphView {
                         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));
                         getTimeGraphViewer().setStartFinishTime(entryTime, exitTime);
                         startZoomThread(entryTime, exitTime);
@@ -408,7 +420,7 @@ public class CallStackView extends AbstractTimeGraphView {
                         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));
                         getTimeGraphViewer().setStartFinishTime(startTime, endTime);
                         startZoomThread(startTime, endTime);
@@ -458,37 +470,13 @@ public class CallStackView extends AbstractTimeGraphView {
                 } else {
                     getTimeGraphViewer().setSelectionRange(beginTime, endTime, true);
                 }
+                fSyncSelection = true;
                 synchingToTime(beginTime);
+                fSyncSelection = false;
                 startZoomThread(getTimeGraphViewer().getTime0(), getTimeGraphViewer().getTime1());
-                List<TimeGraphEntry> entryList = getEntryList(getTrace());
-                if (entryList == null) {
-                    return;
-                }
-                TimeGraphViewer viewer = getTimeGraphViewer();
-                for (TimeGraphEntry traceEntry : entryList) {
-                    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));
-                                getTimeGraphCombo().setSelection(selectedEntry);
-                                viewer.getTimeGraphControl().fireSelectionChanged();
-                                break;
-                            }
-                        } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
-                            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
-                        }
-                    }
-                }
             }
         });
+
     }
 
     /**
@@ -534,10 +522,24 @@ public class CallStackView extends AbstractTimeGraphView {
     }
 
     @Override
-    protected void buildEventList(final ITmfTrace trace, final ITmfTrace parentTrace, final IProgressMonitor monitor) {
+    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);
@@ -550,8 +552,8 @@ public class CallStackView extends AbstractTimeGraphView {
         }
 
         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();
 
@@ -569,16 +571,6 @@ public class CallStackView extends AbstractTimeGraphView {
                 continue;
             }
 
-            ISymbolProvider provider = fSymbolProviders.get(trace);
-            if (provider == null) {
-                provider = SymbolProviderManager.getInstance().getSymbolProvider(trace);
-                provider.loadConfiguration(monitor);
-                fSymbolProviders.put(trace, provider);
-            }
-
-            getConfigureSymbolsAction().setEnabled(true);
-
-            List<Integer> threadQuarks = ss.getQuarks(threadPaths);
             TraceEntry traceEntry = traceEntryMap.get(trace);
             if (traceEntry == null) {
                 traceEntry = new TraceEntry(trace.getName(), start, end + 1);
@@ -588,48 +580,114 @@ public class CallStackView extends AbstractTimeGraphView {
             } 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 == getTrace()) {
                 synchronized (this) {
                     setStartTime(getStartTime() == SWT.DEFAULT ? start : Math.min(getStartTime(), start));
@@ -638,14 +696,22 @@ public class CallStackView extends AbstractTimeGraphView {
                 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);
                 }
-            }
+            };
+            traceEntry.getChildren().forEach(consumer);
+
             start = end;
         }
     }
@@ -664,9 +730,7 @@ public class CallStackView extends AbstractTimeGraphView {
         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 == getTrace()) {
             redraw();
@@ -674,7 +738,7 @@ public class CallStackView extends AbstractTimeGraphView {
     }
 
     /**
-     * @since 2.0
+     * @since 1.2
      */
     @Override
     protected final List<ITimeEvent> getEventList(TimeGraphEntry tgentry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
@@ -688,12 +752,13 @@ public class CallStackView extends AbstractTimeGraphView {
         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;
@@ -706,7 +771,7 @@ public class CallStackView extends AbstractTimeGraphView {
                     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 {
@@ -714,7 +779,7 @@ public class CallStackView extends AbstractTimeGraphView {
                             // 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));
                         }
@@ -734,52 +799,74 @@ public class CallStackView extends AbstractTimeGraphView {
     }
 
     /**
-     * @since 2.0
+     * @since 1.2
      */
     @Override
-    protected void synchingToTime(long time) {
-        List<TimeGraphEntry> entryList = getEntryList(getTrace());
-        if (entryList == null) {
+    protected void synchingToTime(final long time) {
+        List<TimeGraphEntry> traceEntries = getEntryList(getTrace());
+        Map<ITmfStateSystem, List<ITmfStateInterval>> fullStateMap = new HashMap<>();
+        if (traceEntries == null) {
             return;
         }
-        for (TimeGraphEntry traceEntry : entryList) {
-            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 = getFunctionName(trace, nameValue);
+
+                        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);
             }
-        }
+
+            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);
+                }
+                return fullState;
+            }
+        };
+        traceEntries.forEach(consumer);
         if (Display.getCurrent() != null) {
             getTimeGraphCombo().refresh();
         }
     }
 
-    String getFunctionName(ITmfTrace trace, ITmfStateValue nameValue) {
+    String getFunctionName(ITmfTrace trace, int processId, long timestamp, ITmfStateValue nameValue) {
         long address = Long.MAX_VALUE;
         String name = ""; //$NON-NLS-1$
         try {
@@ -791,10 +878,10 @@ public class CallStackView extends AbstractTimeGraphView {
                     // ignore
                 }
             } else if (nameValue.getType() == Type.INTEGER) {
-                name = "0x" + Integer.toHexString(nameValue.unboxInt()); //$NON-NLS-1$
+                name = "0x" + Integer.toUnsignedString(nameValue.unboxInt(), 16); //$NON-NLS-1$
                 address = nameValue.unboxInt();
             } else if (nameValue.getType() == Type.LONG) {
-                name = "0x" + Long.toHexString(nameValue.unboxLong()); //$NON-NLS-1$
+                name = "0x" + Long.toUnsignedString(nameValue.unboxLong(), 16); //$NON-NLS-1$
                 address = nameValue.unboxLong();
             }
         } catch (StateValueTypeException e) {
@@ -802,7 +889,7 @@ public class CallStackView extends AbstractTimeGraphView {
         if (address != Long.MAX_VALUE) {
             ISymbolProvider provider = fSymbolProviders.get(trace);
             if (provider != null) {
-                String symbol = provider.getSymbolText(address);
+                String symbol = provider.getSymbolText(processId, timestamp, address);
                 if (symbol != null) {
                     name = symbol;
                 }
@@ -842,7 +929,7 @@ public class CallStackView extends AbstractTimeGraphView {
     }
 
     /**
-     * @since 2.0
+     * @since 1.2
      */
     @Override
     protected void fillLocalToolBar(IToolBarManager manager) {
@@ -909,16 +996,16 @@ public class CallStackView extends AbstractTimeGraphView {
                             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;
@@ -954,16 +1041,16 @@ public class CallStackView extends AbstractTimeGraphView {
                             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;
@@ -1140,6 +1227,12 @@ public class CallStackView extends AbstractTimeGraphView {
 
         fConfigureSymbolsAction.setToolTipText(Messages.CallStackView_ConfigureSymbolProvidersTooltip);
         fConfigureSymbolsAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_BINARY_ICON_PATH));
+
+        /*
+         * 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);
 
         return fConfigureSymbolsAction;
This page took 0.033183 seconds and 5 git commands to generate.