linux.ui: Add Threads Presentation to View Menu of the CFV
authorMahdi Zolnouri <mzolnouri@yahoo.com>
Wed, 30 Mar 2016 21:09:25 +0000 (17:09 -0400)
committerPatrick Tasse <patrick.tasse@gmail.com>
Fri, 6 May 2016 14:01:49 +0000 (10:01 -0400)
This patch adds a threads presentation item to the view menu
(the triangular menu in the top right corner of the view) of
the control flow view, in order to select which presentation
mode is needed.

At the moment, the options offered are:
 * Hierarchical
 * Flat

Others may come later such as clamping by time...

These menus are the first step towards grouping threads by
affinity.

Change-Id: I65a71ad4a5eb6489f668f8b5806f12702f43edbc
Signed-off-by: Mahdi Zolnouri <mzolnouri@yahoo.com>
Signed-off-by: Samuel Gagnon <samuel.gagnon92@gmail.com>
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/68231
Reviewed-by: Hudson CI
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/Messages.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/messages.properties
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowView.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractStateSystemTimeGraphView.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/model/TimeGraphEntry.java

index f0e98d513ece9a8cd6c40e107812dd4c7d202442..282db08033860e3c3e3cd9b3db797f85af7834f0 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     Patrick Tassé - Initial API and implementation
+ *     Mahdi Zolnouri - Add new String for ControlFlowView
  *******************************************************************************/
 
 package org.eclipse.tracecompass.internal.analysis.os.linux.ui;
@@ -18,6 +19,8 @@ public class Messages extends NLS {
     private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.analysis.os.linux.ui.messages"; //$NON-NLS-1$
 
     public static String ControlFlowView_birthTimeColumn;
+    public static String ControlFlowView_threadPresentation;
+
     public static String ControlFlowView_tidColumn;
     public static String ControlFlowView_ptidColumn;
     public static String ControlFlowView_processColumn;
@@ -37,6 +40,10 @@ public class Messages extends NLS {
     public static String ControlFlowView_uncheckInactiveToolTip;
     public static String ControlFlowView_attributeSyscallName;
     public static String ControlFlowView_attributeCpuName;
+    public static String ControlFlowView_flatViewLabel;
+    public static String ControlFlowView_flatViewToolTip;
+    public static String ControlFlowView_hierarchicalViewLabel;
+    public static String ControlFlowView_hierarchicalViewToolTip;
 
     public static String ResourcesView_stateTypeName;
     public static String ResourcesView_multipleStates;
index a6a7d1ed771461899cacfdec504a53d96372feac..8098004332317fa4889b70b3043b24a3cf9b77f6 100644 (file)
@@ -11,6 +11,7 @@
 ###############################################################################
 
 ControlFlowView_birthTimeColumn=Birth time
+ControlFlowView_threadPresentation=Thread Presentation
 ControlFlowView_tidColumn=TID
 ControlFlowView_ptidColumn=PTID
 ControlFlowView_processColumn=Process
@@ -30,6 +31,10 @@ ControlFlowView_uncheckInactiveLabel=Uncheck Inactive
 ControlFlowView_uncheckInactiveToolTip=Unchecks all threads not executing within the time frame.
 ControlFlowView_attributeSyscallName=System Call
 ControlFlowView_attributeCpuName=CPU
+ControlFlowView_flatViewLabel=Flat
+ControlFlowView_flatViewToolTip= Flat Thread Layout
+ControlFlowView_hierarchicalViewLabel=Hierarchical
+ControlFlowView_hierarchicalViewToolTip=Hierarchical Thread Layout
 
 ResourcesView_stateTypeName=Resource
 ResourcesView_multipleStates=(multiple)
index 5db607983f0e34c69e5f13ef7d66eb88edb06480..9a63d869a7ca9ce7f9ef75010d80b43dfdcb3dec 100644 (file)
@@ -10,6 +10,7 @@
  *   Patrick Tasse - Initial API and implementation
  *   Geneviève Bastien - Move code to provide base classes for time graph view
  *   Christian Mansky - Add check active / uncheck inactive buttons
+ *   Mahdi Zolnouri & Samuel Gagnon - Add flat / hierarchical button
  *******************************************************************************/
 
 package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;
@@ -17,20 +18,27 @@ package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
 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.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.common.core.StreamUtils.StreamFlattener;
 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;
@@ -42,6 +50,8 @@ import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeExcept
 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
 import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
@@ -111,6 +121,12 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
         COLUMN_COMPARATORS = l.toArray(new Comparator[l.size()]);
     }
 
+    private final Set<ITmfTrace> fFlatTraces = new HashSet<>();
+
+    private IAction fFlatAction;
+
+    private IAction fHierarchicalAction;
+
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
@@ -176,6 +192,59 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
         manager.add(followArrowFwdAction);
     }
 
+    @Override
+    protected void fillLocalMenu(IMenuManager manager) {
+        super.fillLocalMenu(manager);
+        final MenuManager item = new MenuManager(Messages.ControlFlowView_threadPresentation);
+        fFlatAction = createFlatAction();
+        item.add(fFlatAction);
+
+        fHierarchicalAction = createHierarchicalAction();
+        item.add(fHierarchicalAction);
+        manager.add(item);
+
+    }
+
+    private IAction createHierarchicalAction() {
+        IAction action = new Action(Messages.ControlFlowView_hierarchicalViewLabel, IAction.AS_RADIO_BUTTON) {
+            @Override
+            public void run() {
+                ITmfTrace parentTrace = getTrace();
+                synchronized (fFlatTraces) {
+                    fFlatTraces.remove(parentTrace);
+                    for (ITmfTrace trace : TmfTraceManager.getTraceSet(parentTrace)) {
+                        final ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
+                        List<ControlFlowEntry> currentRootList = getEntryList(ss).stream().filter(e -> e instanceof ControlFlowEntry).map(e -> (ControlFlowEntry) e).collect(Collectors.toList());
+                        addEntriesToHierarchicalTree(currentRootList, parentTrace, ss);
+                    }
+                }
+                refresh();
+            }
+        };
+        action.setChecked(true);
+        action.setToolTipText(Messages.ControlFlowView_hierarchicalViewToolTip);
+        return action;
+    }
+
+    private IAction createFlatAction() {
+        IAction action = new Action(Messages.ControlFlowView_flatViewLabel, IAction.AS_RADIO_BUTTON) {
+            @Override
+            public void run() {
+                ITmfTrace parentTrace = getTrace();
+                synchronized (fFlatTraces) {
+                    fFlatTraces.add(parentTrace);
+                    for (ITmfTrace trace : TmfTraceManager.getTraceSet(parentTrace)) {
+                        final ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
+                        hierarchicalToFlatTree(parentTrace, ss);
+                    }
+                }
+                refresh();
+            }
+        };
+        action.setToolTipText(Messages.ControlFlowView_flatViewToolTip);
+        return action;
+    }
+
     @Override
     protected String getNextText() {
         return Messages.ControlFlowView_nextProcessActionNameText;
@@ -240,6 +309,30 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
 
     }
 
+    @TmfSignalHandler
+    @Override
+    public void traceClosed(org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal signal) {
+        super.traceClosed(signal);
+        synchronized (fFlatTraces) {
+            fFlatTraces.remove(signal.getTrace());
+        }
+    }
+
+    @TmfSignalHandler
+    @Override
+    public void traceSelected(TmfTraceSelectedSignal signal) {
+        super.traceSelected(signal);
+        synchronized (fFlatTraces) {
+            if (fFlatTraces.contains(signal.getTrace())) {
+                fHierarchicalAction.setChecked(false);
+                fFlatAction.setChecked(true);
+            } else {
+                fFlatAction.setChecked(false);
+                fHierarchicalAction.setChecked(true);
+            }
+        }
+    }
+
     // ------------------------------------------------------------------------
     // Internal
     // ------------------------------------------------------------------------
@@ -360,7 +453,13 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
                             lastPpidStartTime = ppidInterval.getStartTime();
                         }
                     }
-                    updateTree(entryList, parentTrace, ssq);
+                    synchronized (fFlatTraces) {
+                        if (fFlatTraces.contains(parentTrace)) {
+                            addEntriesToFlatTree(entryList, parentTrace, ssq);
+                        } else {
+                            addEntriesToHierarchicalTree(entryList, parentTrace, ssq);
+                        }
+                    }
                 }
             });
 
@@ -384,8 +483,47 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
         }
     }
 
-    private void updateTree(List<ControlFlowEntry> entryList, ITmfTrace parentTrace, ITmfStateSystem ss) {
-        List<TimeGraphEntry> rootListToAdd = new ArrayList<>();
+    /**
+     * Add entries to the traces's entry list in a flat fashion (no hierarchy).
+     * If one entry has children, we do a depth first search to add each child
+     * to the trace's entry list and update the parent and child relations.
+     */
+    private void hierarchicalToFlatTree(ITmfTrace parentTrace, ITmfStateSystem ss) {
+        List<@NonNull TimeGraphEntry> rootList = getEntryList(ss);
+        // We visit the children of every entry to add
+        StreamFlattener<TimeGraphEntry> sf = new StreamFlattener<>(entry -> entry.getChildren().stream());
+        Stream<TimeGraphEntry> allEntries = rootList.stream().flatMap(entry -> sf.flatten(entry));
+
+        // We add every entry that is missing from the trace's entry list
+        List<@NonNull TimeGraphEntry> rootListToAdd = allEntries
+                .filter(entry -> !rootList.contains(entry))
+                .collect(Collectors.toList());
+        rootList.forEach(entry -> {
+            entry.clearChildren();
+        });
+        rootListToAdd.forEach(entry -> {
+            entry.setParent(null);
+            entry.clearChildren();
+        });
+        addToEntryList(parentTrace, ss, rootListToAdd);
+    }
+
+    /**
+     * Add entries to the traces's entry list in a flat fashion (no hierarchy).
+     */
+    private void addEntriesToFlatTree(List<@NonNull ControlFlowEntry> entryList, ITmfTrace parentTrace, ITmfStateSystem ss) {
+        List<TimeGraphEntry> rootList = getEntryList(ss);
+        List<@NonNull TimeGraphEntry> rootListToAdd = entryList.stream()
+                .filter(entry -> !rootList.contains(entry))
+                .collect(Collectors.toList());
+        addToEntryList(parentTrace, ss, rootListToAdd);
+    }
+
+    /**
+     * Add entries to the trace's entry list in a hierarchical fashion.
+     */
+    private void addEntriesToHierarchicalTree(List<ControlFlowEntry> entryList, ITmfTrace parentTrace, ITmfStateSystem ss) {
+        List<@NonNull TimeGraphEntry> rootListToAdd = new ArrayList<>();
         List<TimeGraphEntry> rootListToRemove = new ArrayList<>();
         List<TimeGraphEntry> rootList = getEntryList(ss);
 
index e5f4776b61051fa8da276e48688b6032bab8e0b4..197c2c979c6295362b0122064cc1636b36342aee 100644 (file)
@@ -57,7 +57,7 @@ public abstract class AbstractStateSystemTimeGraphView extends AbstractTimeGraph
     // ------------------------------------------------------------------------
 
     /** The state system to entry list hash map */
-    private final Map<ITmfStateSystem, List<TimeGraphEntry>> fSSEntryListMap = new HashMap<>();
+    private final Map<ITmfStateSystem, List<@NonNull TimeGraphEntry>> fSSEntryListMap = new HashMap<>();
 
     /** The trace to state system multi map */
     private final Multimap<ITmfTrace, ITmfStateSystem> fTraceSSMap = HashMultimap.create();
@@ -232,7 +232,7 @@ public abstract class AbstractStateSystemTimeGraphView extends AbstractTimeGraph
      *
      * @return the entry list map
      */
-    protected List<TimeGraphEntry> getEntryList(ITmfStateSystem ss) {
+    protected List<@NonNull TimeGraphEntry> getEntryList(ITmfStateSystem ss) {
         synchronized (fSSEntryListMap) {
             return fSSEntryListMap.get(ss);
         }
@@ -248,7 +248,7 @@ public abstract class AbstractStateSystemTimeGraphView extends AbstractTimeGraph
      * @param list
      *            the list of time graph entries
      */
-    protected void putEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
+    protected void putEntryList(ITmfTrace trace, ITmfStateSystem ss, List<@NonNull TimeGraphEntry> list) {
         super.putEntryList(trace, list);
         synchronized (fSSEntryListMap) {
             fSSEntryListMap.put(ss, new CopyOnWriteArrayList<>(list));
@@ -266,10 +266,10 @@ public abstract class AbstractStateSystemTimeGraphView extends AbstractTimeGraph
      * @param list
      *            the list of time graph entries to add
      */
-    protected void addToEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
+    protected void addToEntryList(ITmfTrace trace, ITmfStateSystem ss, List<@NonNull TimeGraphEntry> list) {
         super.addToEntryList(trace, list);
         synchronized (fSSEntryListMap) {
-            List<TimeGraphEntry> entryList = fSSEntryListMap.get(ss);
+            List<@NonNull TimeGraphEntry> entryList = fSSEntryListMap.get(ss);
             if (entryList == null) {
                 fSSEntryListMap.put(ss, new CopyOnWriteArrayList<>(list));
             } else {
index f25342a91ee79f3db58164e3b95cd953a38996bd..da35170fc2e5bf7d5b10761a6c45957d92cecff4 100644 (file)
@@ -91,6 +91,15 @@ public class TimeGraphEntry implements ITimeGraphEntry {
         return fChildren;
     }
 
+    /**
+     * Clear the children of the entry
+     *
+     * @since 2.0
+     */
+    public void clearChildren() {
+        fChildren.clear();
+    }
+
     @Override
     public String getName() {
         return fName;
This page took 0.031355 seconds and 5 git commands to generate.