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.Job;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.action.Action;
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.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;
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.ITmfTimestamp;
+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;
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;
private static final String PTID_COLUMN = Messages.ControlFlowView_ptidColumn;
private static final String BIRTH_TIME_COLUMN = Messages.ControlFlowView_birthTimeColumn;
+ private static final String NEXT_EVENT_ICON_PATH = "icons/obj16/shift_r_edit.gif"; //$NON-NLS-1$
+ private static final String PREV_EVENT_ICON_PATH = "icons/obj16/shift_l_edit.gif"; //$NON-NLS-1$
+
private static final String[] COLUMN_NAMES = new String[] {
PROCESS_COLUMN,
TID_COLUMN,
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);
}
@Override
}
+ /**
+ * 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() {
+ TimeGraphControl ctrl = getTimeGraphViewer().getTimeGraphControl();
+
+ ITimeGraphEntry traceEntry = ctrl.getSelectedTrace();
+ long ts = ctrl.getTimeDataProvider().getSelectionBegin();
+ ITmfTimestamp ts2 = TmfTraceManager.getInstance().getCurrentTraceContext().getSelectionRange().getStartTime();
+ ITimeEvent selectedState = Utils.findEvent(traceEntry, ts, 0);
+
+ if (selectedState == null) {
+ return;
+ }
+ ITimeGraphEntry entry = selectedState.getEntry();
+ if (!(entry instanceof ControlFlowEntry)) {
+ return;
+ }
+ ControlFlowEntry cfEntry = (ControlFlowEntry) entry;
+ int tid = cfEntry.getThreadId();
+
+ Job job = new Job(ifJobName) {
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ ITmfTrace trace = cfEntry.getTrace();
+ ITmfContext ctx = trace.seekEvent(ts2);
+ long rank = ctx.getRank();
+
+ Predicate<@NonNull ITmfEvent> predicate = event -> {
+ Integer eventTid = KernelTidAspect.INSTANCE.resolve(event);
+ return (eventTid != null && eventTid.intValue() == tid);
+ };
+
+ ITmfEvent event = (ifDirection ?
+ TmfTraceUtils.getNextEventMatching(cfEntry.getTrace(), rank, predicate) :
+ TmfTraceUtils.getPreviousEventMatching(cfEntry.getTrace(), rank, predicate));
+ if (event != null) {
+ TmfSignalManager.dispatchSignal(new TmfSelectionRangeUpdatedSignal(this, event.getTimestamp()));
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.schedule();
+ }
+ }
+
private IAction createHierarchicalAction() {
IAction action = new Action(Messages.ControlFlowView_hierarchicalViewLabel, IAction.AS_RADIO_BUTTON) {
@Override