os.linux: Add Next/Previous TID event action in CFV
authorAlexandre Montplaisir <alexmonthy@efficios.com>
Wed, 15 Jun 2016 19:41:45 +0000 (15:41 -0400)
committerAlexandre Montplaisir <alexmonthy@efficios.com>
Fri, 8 Jul 2016 07:07:15 +0000 (03:07 -0400)
Expose actions in the Control Flow View to navigate to the
previous or next trace event for a given row/thread.

Unlike the "Go to state change" action, this action will stop
on all trace events related to that thread. To do so, we need
to stop on every trace event to test if they match. Since this
operation is unbounded in terms of number of events to read,
it is deferred to a separate Job.

Change-Id: Ie0f4f7dc3f2d0c6e3f2d0111fa95f265dfcdf75f
Signed-off-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Reviewed-on: https://git.eclipse.org/r/75362
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/icons/elcl16/shift_l_edit.gif [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/icons/elcl16/shift_r_edit.gif [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowView.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/PackageMessages.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/messages.properties [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/TimeGraphControl.java

diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/icons/elcl16/shift_l_edit.gif b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/icons/elcl16/shift_l_edit.gif
new file mode 100644 (file)
index 0000000..328e97e
Binary files /dev/null and b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/icons/elcl16/shift_l_edit.gif differ
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/icons/elcl16/shift_r_edit.gif b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/icons/elcl16/shift_r_edit.gif
new file mode 100644 (file)
index 0000000..c39cf62
Binary files /dev/null and b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/icons/elcl16/shift_r_edit.gif differ
index 1aa2bc47b1ce8b5fb2f4c94c43720db78601198e..f5852f6ce62e53286d8f2a1804c60d28ccfd3191 100644 (file)
@@ -24,10 +24,15 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jface.action.Action;
@@ -42,6 +47,7 @@ import org.eclipse.jface.viewers.StructuredSelection;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelTidAspect;
 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;
@@ -54,11 +60,17 @@ 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.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
 import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
 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;
@@ -68,6 +80,7 @@ import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeLinkEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
 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;
@@ -98,6 +111,9 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
     private static final String INVISIBLE_COLUMN = Messages.ControlFlowView_invisibleColumn;
     private Action fOptimizationAction;
 
+    private static final String NEXT_EVENT_ICON_PATH = "icons/elcl16/shift_r_edit.gif"; //$NON-NLS-1$
+    private static final String PREV_EVENT_ICON_PATH = "icons/elcl16/shift_l_edit.gif"; //$NON-NLS-1$
+
     private static final String[] COLUMN_NAMES = new String[] {
             PROCESS_COLUMN,
             TID_COLUMN,
@@ -127,8 +143,23 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
         COLUMN_COMPARATORS = l.toArray(new Comparator[l.size()]);
     }
 
+    /**
+     * Mutex rule for search action jobs, making sure they execute sequentially
+     */
+    private final ISchedulingRule fSearchActionMutexRule = new ISchedulingRule() {
+        @Override
+        public boolean isConflicting(ISchedulingRule rule) {
+            return (rule == this);
+        }
+        @Override
+        public boolean contains(ISchedulingRule rule) {
+            return (rule == this);
+        }
+    };
+
     private final Set<ITmfTrace> fFlatTraces = new HashSet<>();
 
+
     private IAction fFlatAction;
 
     private IAction fHierarchicalAction;
@@ -203,6 +234,18 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
         followArrowFwdAction.setText(Messages.ControlFlowView_followCPUFwdText);
         followArrowFwdAction.setToolTipText(Messages.ControlFlowView_followCPUFwdText);
         manager.add(followArrowFwdAction);
+
+        IAction previousEventAction = new SearchEventAction(false, PackageMessages.ControlFlowView_PreviousEventJobName);
+        previousEventAction.setText(PackageMessages.ControlFlowView_PreviousEventActionName);
+        previousEventAction.setToolTipText(PackageMessages.ControlFlowView_PreviousEventActionTooltip);
+        previousEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(PREV_EVENT_ICON_PATH));
+        manager.add(previousEventAction);
+
+        IAction nextEventAction = new SearchEventAction(true, PackageMessages.ControlFlowView_NextEventJobName);
+        nextEventAction.setText(PackageMessages.ControlFlowView_NextEventActionName);
+        nextEventAction.setToolTipText(PackageMessages.ControlFlowView_NextEventActionTooltip);
+        nextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(NEXT_EVENT_ICON_PATH));
+        manager.add(nextEventAction);
     }
 
     private IAction getOptimizationAction() {
@@ -228,6 +271,84 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
 
     }
 
+    /**
+     * Base Action for the "Go to Next/Previous Event for thread" actions
+     */
+    private class SearchEventAction extends Action {
+
+        private final boolean ifDirection;
+        private final String ifJobName;
+
+        /**
+         * Constructor
+         *
+         * @param direction
+         *            The direction of the search, "true" for forwards and
+         *            "false" for backwards.
+         * @param jobName
+         *            The name of the job that will be spawned
+         */
+        public SearchEventAction(boolean direction, String jobName) {
+            ifDirection = direction;
+            ifJobName = jobName;
+        }
+
+        @Override
+        public void run() {
+            Job job = new Job(ifJobName) {
+                @Override
+                protected IStatus run(IProgressMonitor monitor) {
+                    TimeGraphControl ctrl = getTimeGraphViewer().getTimeGraphControl();
+                    ITimeGraphEntry traceEntry = ctrl.getSelectedTrace();
+
+                    long ts = getTimeGraphViewer().getSelectionBegin();
+                    ITimeEvent selectedState = Utils.findEvent(traceEntry, ts, 0);
+
+                    if (selectedState == null) {
+                        /* No selection currently in the view, do nothing */
+                        return Status.OK_STATUS;
+                    }
+                    ITimeGraphEntry entry = selectedState.getEntry();
+                    if (!(entry instanceof ControlFlowEntry)) {
+                        return Status.OK_STATUS;
+                    }
+                    ControlFlowEntry cfEntry = (ControlFlowEntry) entry;
+                    int tid = cfEntry.getThreadId();
+
+                    ITmfTrace trace = cfEntry.getTrace();
+                    ITmfContext ctx = trace.seekEvent(TmfTimestamp.fromNanos(ts));
+                    long rank = ctx.getRank();
+                    ctx.dispose();
+
+                    Predicate<@NonNull ITmfEvent> predicate = event -> {
+                        /*
+                         * TODO Specific to the Control Flow View and kernel
+                         * traces for now. Could be eventually generalized to
+                         * anything represented by the time graph row.
+                         */
+                        Integer eventTid = KernelTidAspect.INSTANCE.resolve(event);
+                        return (eventTid != null && eventTid.intValue() == tid);
+                    };
+
+                    ITmfEvent event = (ifDirection ?
+                            TmfTraceUtils.getNextEventMatching(cfEntry.getTrace(), rank, predicate, monitor) :
+                            TmfTraceUtils.getPreviousEventMatching(cfEntry.getTrace(), rank, predicate, monitor));
+                    if (event != null) {
+                        TmfSignalManager.dispatchSignal(new TmfSelectionRangeUpdatedSignal(this, event.getTimestamp()));
+                    }
+                    return Status.OK_STATUS;
+
+                }
+            };
+            /*
+             * Make subsequent jobs not run concurrently, but wait after one
+             * another.
+             */
+            job.setRule(fSearchActionMutexRule);
+            job.schedule();
+        }
+    }
+
     private IAction createHierarchicalAction() {
         IAction action = new Action(Messages.ControlFlowView_hierarchicalViewLabel, IAction.AS_RADIO_BUTTON) {
             @Override
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/PackageMessages.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/PackageMessages.java
new file mode 100644 (file)
index 0000000..42b2b4e
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc. 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
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Message bundle for the package
+ *
+ * @noreference Messages class
+ */
+@SuppressWarnings("javadoc")
+public class PackageMessages extends NLS {
+
+    private static final String BUNDLE_NAME = PackageMessages.class.getPackage().getName() + ".messages"; //$NON-NLS-1$
+
+    public static String ControlFlowView_NextEventActionName;
+    public static String ControlFlowView_NextEventActionTooltip;
+    public static String ControlFlowView_NextEventJobName;
+
+    public static String ControlFlowView_PreviousEventActionName;
+    public static String ControlFlowView_PreviousEventActionTooltip;
+    public static String ControlFlowView_PreviousEventJobName;
+
+
+    static {
+        NLS.initializeMessages(BUNDLE_NAME, PackageMessages.class);
+    }
+
+    private PackageMessages() {
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/messages.properties b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/messages.properties
new file mode 100644 (file)
index 0000000..9b6cddb
--- /dev/null
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2016 EfficiOS Inc. 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 accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+###############################################################################
+
+ControlFlowView_NextEventActionName = Go to next event
+ControlFlowView_NextEventActionTooltip = Go to next event of the selected thread
+ControlFlowView_NextEventJobName = Searching for next matching event
+
+ControlFlowView_PreviousEventActionName = Go to previous event
+ControlFlowView_PreviousEventActionTooltip = Go to previous event of the selected thread
+ControlFlowView_PreviousEventJobName = Searching for previous matching event
index 3727a46ad3a03d339338dca3f8a34af1053ad320..4705e72d9181feeb6405d092ab70b8fb772f7a3c 100644 (file)
@@ -244,6 +244,16 @@ public class TimeGraphControl extends TimeGraphBaseControl
         return fTimeGraphProvider;
     }
 
+    /**
+     * Gets the time data provider used by this viewer.
+     *
+     * @return The time data provider, or <code>null</code> if not set
+     * @since 2.1
+     */
+    public ITimeDataProvider getTimeDataProvider() {
+        return fTimeProvider;
+    }
+
     /**
      * Gets the color map used by this timegraph viewer.
      *
This page took 0.029439 seconds and 5 git commands to generate.