tmf: Bug 491548: Do not incrementally build full time graph event list
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.ui / src / org / eclipse / tracecompass / analysis / os / linux / ui / views / controlflow / ControlFlowView.java
index 38a0b2d1f213049b02307b83dfef61c1cfe309b8..2cde3f81d5ae3d6262d17788ea0a92fc6c3704e9 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal and others.
+ * Copyright (c) 2012, 2016 Ericsson, École Polytechnique de Montréal 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
@@ -24,13 +24,18 @@ import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.Attributes;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator;
 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions.FollowThreadAction;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowColumnComparators;
 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
 import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
@@ -41,6 +46,7 @@ import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
 import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.util.Pair;
 import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractStateSystemTimeGraphView;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
@@ -53,6 +59,8 @@ import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
 
+import com.google.common.collect.ImmutableList;
+
 /**
  * The Control Flow view main object
  *
@@ -62,7 +70,6 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
     // ------------------------------------------------------------------------
     // Constants
     // ------------------------------------------------------------------------
-
     /**
      * View ID.
      */
@@ -90,6 +97,21 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
     // Timeout between updates in the build thread in ms
     private static final long BUILD_UPDATE_TIMEOUT = 500;
 
+    private static final Comparator<ITimeGraphEntry>[] COLUMN_COMPARATORS;
+
+    private static final int INITIAL_SORT_COLUMN_INDEX = 3;
+
+    static {
+        ImmutableList.Builder<Comparator<ITimeGraphEntry>> builder = ImmutableList.builder();
+        builder.add(ControlFlowColumnComparators.PROCESS_NAME_COLUMN_COMPARATOR)
+            .add(ControlFlowColumnComparators.TID_COLUMN_COMPARATOR)
+            .add(ControlFlowColumnComparators.PTID_COLUMN_COMPARATOR)
+            .add(ControlFlowColumnComparators.BIRTH_TIME_COLUMN_COMPARATOR)
+            .add(ControlFlowColumnComparators.TRACE_COLUMN_COMPARATOR);
+        List<Comparator<ITimeGraphEntry>> l = builder.build();
+        COLUMN_COMPARATORS = l.toArray(new Comparator[l.size()]);
+    }
+
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
@@ -99,11 +121,11 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
      */
     public ControlFlowView() {
         super(ID, new ControlFlowPresentationProvider());
-        setTreeColumns(COLUMN_NAMES);
+        setTreeColumns(COLUMN_NAMES, COLUMN_COMPARATORS, INITIAL_SORT_COLUMN_INDEX);
         setTreeLabelProvider(new ControlFlowTreeLabelProvider());
         setFilterColumns(FILTER_COLUMN_NAMES);
         setFilterLabelProvider(new ControlFlowFilterLabelProvider());
-        setEntryComparator(new ControlFlowEntryComparator());
+        setEntryComparator(ControlFlowColumnComparators.BIRTH_TIME_COLUMN_COMPARATOR);
     }
 
     @Override
@@ -117,6 +139,21 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
                 new ControlFlowCheckActiveProvider(Messages.ControlFlowView_uncheckInactiveLabel, Messages.ControlFlowView_uncheckInactiveToolTip));
     }
 
+    /**
+     * @since 2.0
+     */
+    @Override
+    protected void fillTimeGraphEntryContextMenu(@NonNull IMenuManager menuManager) {
+        ISelection selection = getSite().getSelectionProvider().getSelection();
+        if (selection instanceof StructuredSelection) {
+            StructuredSelection sSel = (StructuredSelection) selection;
+            if (sSel.getFirstElement() instanceof ControlFlowEntry) {
+                ControlFlowEntry entry = (ControlFlowEntry) sSel.getFirstElement();
+                menuManager.add(new FollowThreadAction(ControlFlowView.this, entry.getName(), entry.getThreadId(), entry.getTrace()));
+            }
+        }
+    }
+
     @Override
     protected void fillLocalToolBar(IToolBarManager manager) {
         super.fillLocalToolBar(manager);
@@ -160,33 +197,6 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
         return Messages.ControlFlowView_previousProcessActionToolTipText;
     }
 
-    private static class ControlFlowEntryComparator implements Comparator<ITimeGraphEntry> {
-
-        @Override
-        public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
-
-            int result = 0;
-
-            if ((o1 instanceof ControlFlowEntry) && (o2 instanceof ControlFlowEntry)) {
-                ControlFlowEntry entry1 = (ControlFlowEntry) o1;
-                ControlFlowEntry entry2 = (ControlFlowEntry) o2;
-                result = entry1.getTrace().getStartTime().compareTo(entry2.getTrace().getStartTime());
-                if (result == 0) {
-                    result = entry1.getTrace().getName().compareTo(entry2.getTrace().getName());
-                }
-                if (result == 0) {
-                    result = entry1.getThreadId() < entry2.getThreadId() ? -1 : entry1.getThreadId() > entry2.getThreadId() ? 1 : 0;
-                }
-            }
-
-            if (result == 0) {
-                result = o1.getStartTime() < o2.getStartTime() ? -1 : o1.getStartTime() > o2.getStartTime() ? 1 : 0;
-            }
-
-            return result;
-        }
-    }
-
     /**
      * @author gbastien
      *
@@ -236,14 +246,15 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
     // ------------------------------------------------------------------------
 
     @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) {
         final ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
         if (ssq == null) {
             return;
         }
 
         final List<ControlFlowEntry> entryList = new ArrayList<>();
-        final Map<Integer, ControlFlowEntry> entryMap = new HashMap<>();
+        /** Map of view entries, key is a pair [threadId, cpuId] */
+        final Map<Pair<Integer, Integer>, ControlFlowEntry> entryMap = new HashMap<>();
 
         long start = ssq.getStartTime();
         setStartTime(Math.min(getStartTime(), start));
@@ -264,20 +275,16 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
             final long resolution = Math.max(1, (end - ssq.getStartTime()) / getDisplayWidth());
             setEndTime(Math.max(getEndTime(), end + 1));
             final List<Integer> threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$
-            final long qStart = start;
-            final long qEnd = end;
-            queryFullStates(ssq, qStart, qEnd, resolution, monitor, new IQueryHandler() {
+            queryFullStates(ssq, start, end, resolution, monitor, new IQueryHandler() {
                 @Override
                 public void handle(List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState) {
                     for (int threadQuark : threadQuarks) {
-                        String threadName = ssq.getAttributeName(threadQuark);
-                        int threadId = -1;
-                        try {
-                            threadId = Integer.parseInt(threadName);
-                        } catch (NumberFormatException e1) {
-                            continue;
-                        }
-                        if (threadId <= 0) { // ignore the 'unknown' (-1) and swapper (0) threads
+                        String threadAttributeName = ssq.getAttributeName(threadQuark);
+
+                        Pair<Integer, Integer> entryKey = Attributes.parseThreadAttributeName(threadAttributeName);
+                        int threadId = entryKey.getFirst();
+
+                        if (threadId < 0) { // ignore the 'unknown' (-1) thread
                             continue;
                         }
 
@@ -330,11 +337,11 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
                                     execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
                                 String execName = execNameInterval.getStateValue().unboxStr();
                                 int ppid = ppidInterval.getStateValue().unboxInt();
-                                ControlFlowEntry entry = entryMap.get(threadId);
+                                ControlFlowEntry entry = entryMap.get(entryKey);
                                 if (entry == null) {
                                     entry = new ControlFlowEntry(threadQuark, trace, execName, threadId, ppid, startTime, endTime);
                                     entryList.add(entry);
-                                    entryMap.put(threadId, entry);
+                                    entryMap.put(entryKey, entry);
                                 } else {
                                     /*
                                      * Update the name of the entry to the
@@ -347,7 +354,7 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
                                 }
                             }
                             if (isNull) {
-                                entryMap.remove(threadId);
+                                entryMap.remove(entryKey);
                             }
                             lastExecNameStartTime = startTime;
                             lastExecNameEndTime = endTime;
@@ -355,12 +362,17 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
                         }
                     }
                     updateTree(entryList, parentTrace, ssq);
+                }
+            });
 
+            queryFullStates(ssq, ssq.getStartTime(), end, resolution, monitor, new IQueryHandler() {
+                @Override
+                public void handle(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState) {
                     for (final TimeGraphEntry entry : getEntryList(ssq)) {
                         if (monitor.isCanceled()) {
                             return;
                         }
-                        buildStatusEvents(trace, parentTrace, ssq, fullStates, prevFullState, (ControlFlowEntry) entry, monitor, qStart, qEnd);
+                        buildStatusEvents(trace, parentTrace, ssq, fullStates, prevFullState, (ControlFlowEntry) entry, monitor, ssq.getStartTime(), end);
                     }
                 }
             });
@@ -418,8 +430,13 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
             if (eventList == null) {
                 return;
             }
-            for (ITimeEvent event : eventList) {
-                entry.addEvent(event);
+            /* Start a new event list on first iteration, then append to it */
+            if (prevFullState == null) {
+                entry.setEventList(eventList);
+            } else {
+                for (ITimeEvent event : eventList) {
+                    entry.addEvent(event);
+                }
             }
             if (parentTrace.equals(getTrace())) {
                 redraw();
This page took 0.028181 seconds and 5 git commands to generate.