analysis: Bug 489573: Internalize Control Flow view implementation
authorBernd Hufmann <Bernd.Hufmann@ericsson.com>
Tue, 22 Mar 2016 11:12:48 +0000 (07:12 -0400)
committerBernd Hufmann <bernd.hufmann@ericsson.com>
Tue, 19 Apr 2016 16:00:14 +0000 (12:00 -0400)
Change-Id: I92e81e1b158cb5dbf1910f9d25b880482fdb3355
Signed-off-by: Bernd Hufmann <Bernd.Hufmann@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/69007
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
15 files changed:
analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/controlflow/ControlFlowEntryComparatorTest.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.java [deleted file]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowEntry.java [deleted file]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowPresentationProvider.java [deleted file]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java [deleted file]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.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/ControlFlowEntry.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/ControlFlowPresentationProvider.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/ControlFlowView.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/IControlFlowEntryComparator.java
lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ImportAndReadKernelSmokeTest.java
lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelPerspectiveChecker.java
lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/PerspectiveFactory.java

index 270849843dc2d50a3f63cb6cf1a4d61e2d57deb6..6f959401899a12a9f7b79f49c81814e41f1040dc 100644 (file)
@@ -19,8 +19,8 @@ import java.util.List;
 
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.swt.SWT;
-import org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowEntry;
 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowColumnComparators;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowEntry;
 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.IControlFlowEntryComparator;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
index d7b15473897d48e724e2f1f43515d50fde9609ed..e11b9b0942b6794be4bf46658461186e8289a600 100644 (file)
@@ -23,13 +23,17 @@ Require-Bundle: org.eclipse.ui,
 Import-Package: com.google.common.base,
  com.google.common.collect,
  org.swtchart
-Export-Package: org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow,
+Export-Package: org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.cpuusage,
  org.eclipse.tracecompass.internal.analysis.os.linux.ui;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests",
  org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions;x-internal:=true,
- org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests,org.eclipse.tracecompass.analysis.os.linux.ui.tests",
+ org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;
+  x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests,
+   org.eclipse.tracecompass.analysis.os.linux.ui.tests,
+   org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests,
+   org.eclipse.tracecompass.lttng2.kernel.ui",
+ org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.cpuusage;x-internal:=true,
  org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.io.diskioactivity;x-internal:=true,
  org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage;x-internal:=true,
- org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.cpuusage;x-internal:=true,
  org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests",
  org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.statistics;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests",
  org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources;
index d650f818b7e9a74e9a04c0062f3017b4e442c494..2cbb49cc072f74d4de55847578cdbe125995b571 100644 (file)
@@ -6,7 +6,7 @@
       <view
             allowMultiple="false"
             category="org.eclipse.linuxtools.lttng2.ui.views.category"
-            class="org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowView"
+            class="org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowView"
             icon="icons/eview16/control_flow_view.gif"
             id="org.eclipse.tracecompass.analysis.os.linux.views.controlflow"
             name="%controlflow.view.name"
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.java
deleted file mode 100644 (file)
index 042e73c..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Keba AG
- *
- * 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
- *
- * Contributors:
- *   Christian Mansky - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow;
-
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
-import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
-import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
-import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
-import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
-import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
-import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
-import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.ITimeGraphEntryActiveProvider;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
-
-/**
- * Provides Functionality for check Active / uncheck inactive
- *
- * @noinstantiate This class is not intended to be instantiated by clients.
- * @noextend This class is not intended to be subclassed by clients.
- * @since 1.0
- */
-public class ControlFlowCheckActiveProvider implements ITimeGraphEntryActiveProvider {
-
-    String fLabel;
-    String fTooltip;
-
-    /**
-     * @param label
-     *            Button label
-     * @param tooltip
-     *            Button tooltip
-     */
-    public ControlFlowCheckActiveProvider(String label, String tooltip) {
-        fLabel = label;
-        fTooltip = tooltip;
-    }
-
-    @Override
-    public String getLabel() {
-        return fLabel;
-    }
-
-    @Override
-    public String getTooltip() {
-        return fTooltip;
-    }
-
-    @Override
-    public boolean isActive(ITimeGraphEntry element) {
-        if (element instanceof ControlFlowEntry) {
-            ControlFlowEntry cfe = (ControlFlowEntry) element;
-
-            TmfTraceManager traceManager = TmfTraceManager.getInstance();
-            TmfTraceContext traceContext = traceManager.getCurrentTraceContext();
-            TmfTimeRange winRange = traceContext.getWindowRange();
-            TmfTimeRange selRange = traceContext.getSelectionRange();
-
-            /* Take precedence of selection over window range. */
-            long beginTS = selRange.getStartTime().getValue();
-            long endTS = selRange.getEndTime().getValue();
-
-            /* No selection, take window range */
-            if (beginTS == endTS) {
-                beginTS = winRange.getStartTime().getValue();
-                endTS = winRange.getEndTime().getValue();
-            }
-
-            ITmfTrace trace = cfe.getTrace();
-            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
-            if (ssq != null) {
-                beginTS = Math.max(beginTS, ssq.getStartTime());
-                endTS = Math.min(endTS, ssq.getCurrentEndTime());
-                if (beginTS > endTS) {
-                    return false;
-                }
-                try {
-                    int statusQuark = ssq.getQuarkRelative(cfe.getThreadQuark(), Attributes.STATUS);
-
-                    /* Get the initial state at beginTS */
-                    ITmfStateInterval currentInterval = ssq.querySingleState(beginTS, statusQuark);
-                    if (isIntervalInStateActive(currentInterval)) {
-                        return true;
-                    }
-
-                    /* Get the following state changes */
-                    long ts = currentInterval.getEndTime();
-                    while (ts != -1 && ts < endTS) {
-                        ts++; /* To "jump over" to the next state in the history */
-                        currentInterval = ssq.querySingleState(ts, statusQuark);
-                        if (isIntervalInStateActive(currentInterval)) {
-                            return true;
-                        }
-                        ts = currentInterval.getEndTime();
-                    }
-                } catch (AttributeNotFoundException | StateSystemDisposedException e) {
-                    /* Ignore ... */
-                }
-            }
-        }
-
-        return false;
-    }
-
-    private static boolean isIntervalInStateActive (ITmfStateInterval ival) {
-        int value = ival.getStateValue().unboxInt();
-        /* An entry is only active when running */
-        if (value == StateValues.PROCESS_STATUS_RUN_USERMODE || value == StateValues.PROCESS_STATUS_RUN_SYSCALL ||
-                value == StateValues.PROCESS_STATUS_INTERRUPTED) {
-            return true;
-        }
-
-        return false;
-    }
-
-}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowEntry.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowEntry.java
deleted file mode 100644 (file)
index 1b7a09b..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012, 2016 Ericsson, École Polytechnique de Montréal
- *
- * 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
- *
- * Contributors:
- *   Patrick Tasse - Initial API and implementation
- *   Geneviève Bastien - Move code to provide base classes for time graph view
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow;
-
-import java.util.regex.Pattern;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
-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;
-
-/**
- * An entry in the Control Flow view
- */
-public class ControlFlowEntry extends TimeGraphEntry {
-
-    private final @NonNull ITmfTrace fTrace;
-    private final int fThreadId;
-    private int fParentThreadId;
-    private final int fThreadQuark;
-
-    /**
-     * Constructor
-     *
-     * @param quark
-     *            The attribute quark matching the thread
-     * @param trace
-     *            The trace on which we are working
-     * @param execName
-     *            The exec_name of this entry
-     * @param threadId
-     *            The TID of the thread
-     * @param parentThreadId
-     *            the Parent_TID of this thread
-     * @param startTime
-     *            The start time of this process's lifetime
-     * @param endTime
-     *            The end time of this process
-     */
-    public ControlFlowEntry(int quark, @NonNull ITmfTrace trace, String execName, int threadId, int parentThreadId, long startTime, long endTime) {
-        super(execName, startTime, endTime);
-        fTrace = trace;
-        fThreadId = threadId;
-        fParentThreadId = parentThreadId;
-        fThreadQuark = quark;
-    }
-
-    /**
-     * Get this entry's thread ID
-     *
-     * @return The TID
-     */
-    public int getThreadId() {
-        return fThreadId;
-    }
-
-    /**
-     * Get the entry's trace
-     *
-     * @return the entry's trace
-     */
-    public @NonNull ITmfTrace getTrace() {
-        return fTrace;
-    }
-
-    /**
-     * Get this thread's parent TID
-     *
-     * @return The "PTID"
-     */
-    public int getParentThreadId() {
-        return fParentThreadId;
-    }
-
-    /**
-     * Set this thread's parent TID
-     *
-     * @param ptid
-     *            The "PTID"
-     * @since 1.1
-     */
-    public void setParentThreadId(int ptid) {
-        fParentThreadId = ptid;
-    }
-
-    /**
-     * Get the quark of the attribute matching this thread's TID
-     *
-     * @return The quark
-     */
-    public int getThreadQuark() {
-        return fThreadQuark;
-    }
-
-    @Override
-    public boolean matches(@NonNull Pattern pattern) {
-        if (pattern.matcher(getName()).find()) {
-            return true;
-        }
-        if (pattern.matcher(Integer.toString(fThreadId)).find()) {
-            return true;
-        }
-        if (pattern.matcher(Integer.toString(fParentThreadId)).find()) {
-            return true;
-        }
-        if (pattern.matcher(Integer.toString(fThreadQuark)).find()) {
-            return true;
-        }
-        if (pattern.matcher(Utils.formatTime(getStartTime(), TimeFormat.CALENDAR, Resolution.NANOSEC)).find()) {
-            return true;
-        }
-        return pattern.matcher(fTrace.getName()).find();
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + '(' + getName() + '[' + fThreadId + "])"; //$NON-NLS-1$
-    }
-}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowPresentationProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowPresentationProvider.java
deleted file mode 100644 (file)
index 49e5826..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal
- *
- * 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
- *
- * Contributors:
- *   Patrick Tasse - Initial API and implementation
- *   Geneviève Bastien - Move code to provide base classes for time graph view
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow;
-
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.RGB;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
-import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
-import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
-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.statesystem.core.ITmfStateSystem;
-import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
-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.statesystem.TmfStateSystemAnalysisModule;
-import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
-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.widgets.Utils;
-
-/**
- * Presentation provider for the control flow view
- */
-public class ControlFlowPresentationProvider extends TimeGraphPresentationProvider {
-
-    private enum State {
-        UNKNOWN        (new RGB(100, 100, 100)),
-        WAIT_UNKNOWN   (new RGB(200, 200, 200)),
-        WAIT_BLOCKED   (new RGB(200, 200, 0)),
-        WAIT_FOR_CPU   (new RGB(200, 100, 0)),
-        USERMODE       (new RGB(0,   200, 0)),
-        SYSCALL        (new RGB(0,     0, 200)),
-        INTERRUPTED    (new RGB(200,   0, 100));
-
-        public final RGB rgb;
-
-        private State(RGB rgb) {
-            this.rgb = rgb;
-        }
-
-    }
-
-    /**
-     * Average width of the characters used for state labels. Is computed in the
-     * first call to postDrawEvent(). Is null before that.
-     */
-    private Integer fAverageCharacterWidth = null;
-
-    /**
-     * Default constructor
-     */
-    public ControlFlowPresentationProvider() {
-        super(Messages.ControlFlowView_stateTypeName);
-    }
-
-    private static State[] getStateValues() {
-        return State.values();
-    }
-
-    @Override
-    public StateItem[] getStateTable() {
-        State[] states = getStateValues();
-        StateItem[] stateTable = new StateItem[states.length];
-        for (int i = 0; i < stateTable.length; i++) {
-            State state = states[i];
-            stateTable[i] = new StateItem(state.rgb, state.toString());
-        }
-        return stateTable;
-    }
-
-    @Override
-    public int getStateTableIndex(ITimeEvent event) {
-        if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) {
-            int status = ((TimeEvent) event).getValue();
-            return getMatchingState(status).ordinal();
-        }
-        if (event instanceof NullTimeEvent) {
-            return INVISIBLE;
-        }
-        return TRANSPARENT;
-    }
-
-    @Override
-    public String getEventName(ITimeEvent event) {
-        if (event instanceof TimeEvent) {
-            TimeEvent ev = (TimeEvent) event;
-            if (ev.hasValue()) {
-                return getMatchingState(ev.getValue()).toString();
-            }
-        }
-        return Messages.ControlFlowView_multipleStates;
-    }
-
-    private static State getMatchingState(int status) {
-        switch (status) {
-        case StateValues.PROCESS_STATUS_WAIT_UNKNOWN:
-            return State.WAIT_UNKNOWN;
-        case StateValues.PROCESS_STATUS_WAIT_BLOCKED:
-            return State.WAIT_BLOCKED;
-        case StateValues.PROCESS_STATUS_WAIT_FOR_CPU:
-            return State.WAIT_FOR_CPU;
-        case StateValues.PROCESS_STATUS_RUN_USERMODE:
-            return State.USERMODE;
-        case StateValues.PROCESS_STATUS_RUN_SYSCALL:
-            return State.SYSCALL;
-        case StateValues.PROCESS_STATUS_INTERRUPTED:
-            return State.INTERRUPTED;
-        default:
-            return State.UNKNOWN;
-        }
-    }
-
-    @Override
-    public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event) {
-        Map<String, String> retMap = new LinkedHashMap<>();
-        if (!(event instanceof TimeEvent) || !((TimeEvent) event).hasValue() ||
-                !(event.getEntry() instanceof ControlFlowEntry)) {
-            return retMap;
-        }
-        ControlFlowEntry entry = (ControlFlowEntry) event.getEntry();
-        ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
-        if (ssq == null) {
-            return retMap;
-        }
-        int tid = entry.getThreadId();
-
-        try {
-            // Find every CPU first, then get the current thread
-            int cpusQuark = ssq.getQuarkAbsolute(Attributes.CPUS);
-            List<Integer> cpuQuarks = ssq.getSubAttributes(cpusQuark, false);
-            for (Integer cpuQuark : cpuQuarks) {
-                int currentThreadQuark = ssq.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
-                ITmfStateInterval interval = ssq.querySingleState(event.getTime(), currentThreadQuark);
-                if (!interval.getStateValue().isNull()) {
-                    ITmfStateValue state = interval.getStateValue();
-                    int currentThreadId = state.unboxInt();
-                    if (tid == currentThreadId) {
-                        retMap.put(Messages.ControlFlowView_attributeCpuName, ssq.getAttributeName(cpuQuark));
-                        break;
-                    }
-                }
-            }
-
-        } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
-            Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
-        } catch (StateSystemDisposedException e) {
-            /* Ignored */
-        }
-        int status = ((TimeEvent) event).getValue();
-        if (status == StateValues.PROCESS_STATUS_RUN_SYSCALL) {
-            try {
-                int syscallQuark = ssq.getQuarkRelative(entry.getThreadQuark(), Attributes.SYSTEM_CALL);
-                ITmfStateInterval value = ssq.querySingleState(event.getTime(), syscallQuark);
-                if (!value.getStateValue().isNull()) {
-                    ITmfStateValue state = value.getStateValue();
-                    retMap.put(Messages.ControlFlowView_attributeSyscallName, state.toString());
-                }
-
-            } catch (AttributeNotFoundException | TimeRangeException e) {
-                Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
-            } catch (StateSystemDisposedException e) {
-                /* Ignored */
-            }
-        }
-
-        return retMap;
-    }
-
-    @Override
-    public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) {
-        if (fAverageCharacterWidth == null) {
-            fAverageCharacterWidth = gc.getFontMetrics().getAverageCharWidth();
-        }
-        if (bounds.width <= fAverageCharacterWidth) {
-            return;
-        }
-        if (!(event instanceof TimeEvent)) {
-            return;
-        }
-        ControlFlowEntry entry = (ControlFlowEntry) event.getEntry();
-        ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
-        if (ss == null) {
-            return;
-        }
-        int status = ((TimeEvent) event).getValue();
-
-        if (status != StateValues.PROCESS_STATUS_RUN_SYSCALL) {
-            return;
-        }
-        try {
-            int syscallQuark = ss.getQuarkRelative(entry.getThreadQuark(), Attributes.SYSTEM_CALL);
-            ITmfStateInterval value = ss.querySingleState(event.getTime(), syscallQuark);
-            if (!value.getStateValue().isNull()) {
-                ITmfStateValue state = value.getStateValue();
-                gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
-
-                /*
-                 * Remove the "sys_" or "syscall_entry_" or similar from what we
-                 * draw in the rectangle. This depends on the trace's event layout.
-                 */
-                int beginIndex = 0;
-                ITmfTrace trace = entry.getTrace();
-                if (trace instanceof IKernelTrace) {
-                    IKernelAnalysisEventLayout layout = ((IKernelTrace) trace).getKernelEventLayout();
-                    beginIndex = layout.eventSyscallEntryPrefix().length();
-                }
-
-                Utils.drawText(gc, state.toString().substring(beginIndex), bounds.x, bounds.y, bounds.width, bounds.height, true, true);
-            }
-        } catch (AttributeNotFoundException | TimeRangeException e) {
-            Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
-        } catch (StateSystemDisposedException e) {
-            /* Ignored */
-        }
-    }
-}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java
deleted file mode 100644 (file)
index 2cde3f8..0000000
+++ /dev/null
@@ -1,661 +0,0 @@
-/*******************************************************************************
- * 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
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *   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
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-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.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;
-import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
-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.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;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
-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.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
- *
- */
-public class ControlFlowView extends AbstractStateSystemTimeGraphView {
-
-    // ------------------------------------------------------------------------
-    // Constants
-    // ------------------------------------------------------------------------
-    /**
-     * View ID.
-     */
-    public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.controlflow"; //$NON-NLS-1$
-
-    private static final String PROCESS_COLUMN = Messages.ControlFlowView_processColumn;
-    private static final String TID_COLUMN = Messages.ControlFlowView_tidColumn;
-    private static final String PTID_COLUMN = Messages.ControlFlowView_ptidColumn;
-    private static final String BIRTH_TIME_COLUMN = Messages.ControlFlowView_birthTimeColumn;
-    private static final String TRACE_COLUMN = Messages.ControlFlowView_traceColumn;
-
-    private static final String[] COLUMN_NAMES = new String[] {
-            PROCESS_COLUMN,
-            TID_COLUMN,
-            PTID_COLUMN,
-            BIRTH_TIME_COLUMN,
-            TRACE_COLUMN
-    };
-
-    private static final String[] FILTER_COLUMN_NAMES = new String[] {
-            PROCESS_COLUMN,
-            TID_COLUMN
-    };
-
-    // 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
-    // ------------------------------------------------------------------------
-
-    /**
-     * Constructor
-     */
-    public ControlFlowView() {
-        super(ID, new ControlFlowPresentationProvider());
-        setTreeColumns(COLUMN_NAMES, COLUMN_COMPARATORS, INITIAL_SORT_COLUMN_INDEX);
-        setTreeLabelProvider(new ControlFlowTreeLabelProvider());
-        setFilterColumns(FILTER_COLUMN_NAMES);
-        setFilterLabelProvider(new ControlFlowFilterLabelProvider());
-        setEntryComparator(ControlFlowColumnComparators.BIRTH_TIME_COLUMN_COMPARATOR);
-    }
-
-    @Override
-    public void createPartControl(Composite parent) {
-        super.createPartControl(parent);
-        // add "Check active" Button to TimeGraphFilterDialog
-        super.getTimeGraphCombo().addTimeGraphFilterCheckActiveButton(
-                new ControlFlowCheckActiveProvider(Messages.ControlFlowView_checkActiveLabel, Messages.ControlFlowView_checkActiveToolTip));
-        // add "Uncheck inactive" Button to TimeGraphFilterDialog
-        super.getTimeGraphCombo().addTimeGraphFilterUncheckInactiveButton(
-                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);
-        IDialogSettings settings = Activator.getDefault().getDialogSettings();
-        IDialogSettings section = settings.getSection(getClass().getName());
-        if (section == null) {
-            section = settings.addNewSection(getClass().getName());
-        }
-
-        IAction hideArrowsAction = getTimeGraphCombo().getTimeGraphViewer().getHideArrowsAction(section);
-        manager.add(hideArrowsAction);
-
-        IAction followArrowBwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowBwdAction();
-        followArrowBwdAction.setText(Messages.ControlFlowView_followCPUBwdText);
-        followArrowBwdAction.setToolTipText(Messages.ControlFlowView_followCPUBwdText);
-        manager.add(followArrowBwdAction);
-
-        IAction followArrowFwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowFwdAction();
-        followArrowFwdAction.setText(Messages.ControlFlowView_followCPUFwdText);
-        followArrowFwdAction.setToolTipText(Messages.ControlFlowView_followCPUFwdText);
-        manager.add(followArrowFwdAction);
-    }
-
-    @Override
-    protected String getNextText() {
-        return Messages.ControlFlowView_nextProcessActionNameText;
-    }
-
-    @Override
-    protected String getNextTooltip() {
-        return Messages.ControlFlowView_nextProcessActionToolTipText;
-    }
-
-    @Override
-    protected String getPrevText() {
-        return Messages.ControlFlowView_previousProcessActionNameText;
-    }
-
-    @Override
-    protected String getPrevTooltip() {
-        return Messages.ControlFlowView_previousProcessActionToolTipText;
-    }
-
-    /**
-     * @author gbastien
-     *
-     */
-    protected static class ControlFlowTreeLabelProvider extends TreeLabelProvider {
-
-        @Override
-        public String getColumnText(Object element, int columnIndex) {
-            ControlFlowEntry entry = (ControlFlowEntry) element;
-
-            if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_processColumn)) {
-                return entry.getName();
-            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_tidColumn)) {
-                return Integer.toString(entry.getThreadId());
-            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_ptidColumn)) {
-                if (entry.getParentThreadId() > 0) {
-                    return Integer.toString(entry.getParentThreadId());
-                }
-            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_birthTimeColumn)) {
-                return Utils.formatTime(entry.getStartTime(), TimeFormat.CALENDAR, Resolution.NANOSEC);
-            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_traceColumn)) {
-                return entry.getTrace().getName();
-            }
-            return ""; //$NON-NLS-1$
-        }
-
-    }
-
-    private static class ControlFlowFilterLabelProvider extends TreeLabelProvider {
-
-        @Override
-        public String getColumnText(Object element, int columnIndex) {
-            ControlFlowEntry entry = (ControlFlowEntry) element;
-
-            if (columnIndex == 0) {
-                return entry.getName();
-            } else if (columnIndex == 1) {
-                return Integer.toString(entry.getThreadId());
-            }
-            return ""; //$NON-NLS-1$
-        }
-
-    }
-
-    // ------------------------------------------------------------------------
-    // Internal
-    // ------------------------------------------------------------------------
-
-    @Override
-    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<>();
-        /** 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));
-
-        boolean complete = false;
-        while (!complete) {
-            if (monitor.isCanceled()) {
-                return;
-            }
-            complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
-            if (ssq.isCancelled()) {
-                return;
-            }
-            long end = ssq.getCurrentEndTime();
-            if (start == end && !complete) { // when complete execute one last time regardless of end time
-                continue;
-            }
-            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$
-            queryFullStates(ssq, start, end, resolution, monitor, new IQueryHandler() {
-                @Override
-                public void handle(List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState) {
-                    for (int threadQuark : threadQuarks) {
-                        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;
-                        }
-
-                        int execNameQuark;
-                        int ppidQuark;
-                        try {
-                            execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME);
-                            ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID);
-                        } catch (AttributeNotFoundException e) {
-                            /* No information on this thread (yet?), skip it for now */
-                            continue;
-                        }
-                        ITmfStateInterval lastExecNameInterval = prevFullState == null || execNameQuark >= prevFullState.size() ? null : prevFullState.get(execNameQuark);
-                        long lastExecNameStartTime = lastExecNameInterval == null ? -1 : lastExecNameInterval.getStartTime();
-                        long lastExecNameEndTime = lastExecNameInterval == null ? -1 : lastExecNameInterval.getEndTime() + 1;
-                        long lastPpidStartTime = prevFullState == null || ppidQuark >= prevFullState.size() ? -1 : prevFullState.get(ppidQuark).getStartTime();
-                        for (List<ITmfStateInterval> fullState : fullStates) {
-                            if (monitor.isCanceled()) {
-                                return;
-                            }
-                            if (execNameQuark >= fullState.size() || ppidQuark >= fullState.size()) {
-                                /* No information on this thread (yet?), skip it for now */
-                                continue;
-                            }
-                            ITmfStateInterval execNameInterval = fullState.get(execNameQuark);
-                            ITmfStateInterval ppidInterval = fullState.get(ppidQuark);
-                            long startTime = execNameInterval.getStartTime();
-                            long endTime = execNameInterval.getEndTime() + 1;
-                            if (startTime == lastExecNameStartTime && ppidInterval.getStartTime() == lastPpidStartTime) {
-                                continue;
-                            }
-                            boolean isNull = execNameInterval.getStateValue().isNull();
-                            if (isNull && lastExecNameEndTime < startTime && lastExecNameEndTime != -1) {
-                                /*
-                                 * There was a non-null interval in between the
-                                 * full states, try to use it.
-                                 */
-                                try {
-                                    execNameInterval = ssq.querySingleState(startTime - 1, execNameQuark);
-                                    ppidInterval = ssq.querySingleState(startTime - 1, ppidQuark);
-                                    startTime = execNameInterval.getStartTime();
-                                    endTime = execNameInterval.getEndTime() + 1;
-                                } catch (AttributeNotFoundException e) {
-                                    Activator.getDefault().logError(e.getMessage());
-                                } catch (StateSystemDisposedException e) {
-                                    /* ignored */
-                                }
-                            }
-                            if (!execNameInterval.getStateValue().isNull() &&
-                                    execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
-                                String execName = execNameInterval.getStateValue().unboxStr();
-                                int ppid = ppidInterval.getStateValue().unboxInt();
-                                ControlFlowEntry entry = entryMap.get(entryKey);
-                                if (entry == null) {
-                                    entry = new ControlFlowEntry(threadQuark, trace, execName, threadId, ppid, startTime, endTime);
-                                    entryList.add(entry);
-                                    entryMap.put(entryKey, entry);
-                                } else {
-                                    /*
-                                     * Update the name of the entry to the
-                                     * latest execName and the parent thread id
-                                     * to the latest ppid.
-                                     */
-                                    entry.setName(execName);
-                                    entry.setParentThreadId(ppid);
-                                    entry.updateEndTime(endTime);
-                                }
-                            }
-                            if (isNull) {
-                                entryMap.remove(entryKey);
-                            }
-                            lastExecNameStartTime = startTime;
-                            lastExecNameEndTime = endTime;
-                            lastPpidStartTime = ppidInterval.getStartTime();
-                        }
-                    }
-                    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, ssq.getStartTime(), end);
-                    }
-                }
-            });
-
-            if (parentTrace.equals(getTrace())) {
-                refresh();
-            }
-
-            start = end;
-        }
-    }
-
-    private void updateTree(List<ControlFlowEntry> entryList, ITmfTrace parentTrace, ITmfStateSystem ss) {
-        List<TimeGraphEntry> rootListToAdd = new ArrayList<>();
-        List<TimeGraphEntry> rootListToRemove = new ArrayList<>();
-        List<TimeGraphEntry> rootList = getEntryList(ss);
-
-        for (ControlFlowEntry entry : entryList) {
-            boolean root = (entry.getParent() == null);
-            if (root && entry.getParentThreadId() > 0) {
-                for (ControlFlowEntry parent : entryList) {
-                    /*
-                     * Associate the parent entry only if their time overlap. A
-                     * child entry may start before its parent, for example at
-                     * the beginning of the trace if a parent has not yet
-                     * appeared in the state system. We just want to make sure
-                     * that the entry didn't start after the parent ended or
-                     * ended before the parent started.
-                     */
-                    if (parent.getThreadId() == entry.getParentThreadId() &&
-                            !(entry.getStartTime() > parent.getEndTime() ||
-                            entry.getEndTime() < parent.getStartTime())) {
-                        parent.addChild(entry);
-                        root = false;
-                        if (rootList != null && rootList.contains(entry)) {
-                            rootListToRemove.add(entry);
-                        }
-                        break;
-                    }
-                }
-            }
-            if (root && (rootList == null || !rootList.contains(entry))) {
-                rootListToAdd.add(entry);
-            }
-        }
-
-        addToEntryList(parentTrace, ss, rootListToAdd);
-        removeFromEntryList(parentTrace, ss, rootListToRemove);
-    }
-
-    private void buildStatusEvents(ITmfTrace trace, ITmfTrace parentTrace, ITmfStateSystem ss, @NonNull List<List<ITmfStateInterval>> fullStates,
-            @Nullable List<ITmfStateInterval> prevFullState, ControlFlowEntry entry, @NonNull IProgressMonitor monitor, long start, long end) {
-        if (start < entry.getEndTime() && end > entry.getStartTime()) {
-            List<ITimeEvent> eventList = getEventList(entry, ss, fullStates, prevFullState, monitor);
-            if (eventList == null) {
-                return;
-            }
-            /* 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();
-            }
-        }
-        for (ITimeGraphEntry child : entry.getChildren()) {
-            if (monitor.isCanceled()) {
-                return;
-            }
-            buildStatusEvents(trace, parentTrace, ss, fullStates, prevFullState, (ControlFlowEntry) child, monitor, start, end);
-        }
-    }
-
-    @Override
-    protected @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry tgentry, ITmfStateSystem ss,
-            @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
-        List<ITimeEvent> eventList = null;
-        if (!(tgentry instanceof ControlFlowEntry)) {
-            return eventList;
-        }
-        ControlFlowEntry entry = (ControlFlowEntry) tgentry;
-        try {
-            int threadQuark = entry.getThreadQuark();
-            int statusQuark = ss.getQuarkRelative(threadQuark, Attributes.STATUS);
-            eventList = new ArrayList<>(fullStates.size());
-            ITmfStateInterval lastInterval = prevFullState == null || statusQuark >= prevFullState.size() ? null : prevFullState.get(statusQuark);
-            long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime();
-            long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1;
-            for (List<ITmfStateInterval> fullState : fullStates) {
-                if (monitor.isCanceled()) {
-                    return null;
-                }
-                if (statusQuark >= fullState.size()) {
-                    /* No information on this thread (yet?), skip it for now */
-                    continue;
-                }
-                ITmfStateInterval statusInterval = fullState.get(statusQuark);
-                long time = statusInterval.getStartTime();
-                if (time == lastStartTime) {
-                    continue;
-                }
-                long duration = statusInterval.getEndTime() - time + 1;
-                int status = -1;
-                try {
-                    status = statusInterval.getStateValue().unboxInt();
-                } catch (StateValueTypeException e) {
-                    Activator.getDefault().logError(e.getMessage());
-                }
-                if (lastEndTime != time && lastEndTime != -1) {
-                    eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
-                }
-                if (!statusInterval.getStateValue().isNull()) {
-                    eventList.add(new TimeEvent(entry, time, duration, status));
-                } else {
-                    eventList.add(new NullTimeEvent(entry, time, duration));
-                }
-                lastStartTime = time;
-                lastEndTime = time + duration;
-            }
-        } catch (AttributeNotFoundException | TimeRangeException e) {
-            Activator.getDefault().logError(e.getMessage());
-        }
-        return eventList;
-    }
-
-    /**
-     * Returns a value corresponding to the selected entry.
-     *
-     * Used in conjunction with synchingToTime to change the selected entry. If
-     * one of these methods is overridden in child class, then both should be.
-     *
-     * @param time
-     *            The currently selected time
-     * @return a value identifying the entry
-     */
-    private int getSelectionValue(long time) {
-        int thread = -1;
-        for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) {
-            if (thread > 0) {
-                break;
-            }
-            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
-            if (ssq == null) {
-                continue;
-            }
-            if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) {
-                List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
-                for (int currentThreadQuark : currentThreadQuarks) {
-                    try {
-                        ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark);
-                        int currentThread = currentThreadInterval.getStateValue().unboxInt();
-                        if (currentThread > 0) {
-                            int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS);
-                            ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark);
-                            if (statusInterval.getStartTime() == time) {
-                                thread = currentThread;
-                                break;
-                            }
-                        }
-                    } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
-                        Activator.getDefault().logError(e.getMessage());
-                    } catch (StateSystemDisposedException e) {
-                        /* Ignored */
-                    }
-                }
-            }
-        }
-        return thread;
-    }
-
-    @Override
-    protected void synchingToTime(long time) {
-        int selected = getSelectionValue(time);
-        if (selected > 0) {
-            for (Object element : getTimeGraphViewer().getExpandedElements()) {
-                if (element instanceof ControlFlowEntry) {
-                    ControlFlowEntry entry = (ControlFlowEntry) element;
-                    if (entry.getThreadId() == selected) {
-                        getTimeGraphCombo().setSelection(entry);
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    protected @NonNull List<ILinkEvent> getLinkList(ITmfStateSystem ss,
-            @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
-        List<ILinkEvent> list = new ArrayList<>();
-        List<TimeGraphEntry> entryList = getEntryList(ss);
-        if (entryList == null) {
-            return list;
-        }
-        for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) {
-            List<Integer> currentThreadQuarks = ss.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
-            for (int currentThreadQuark : currentThreadQuarks) {
-                if (currentThreadQuark >= fullStates.get(0).size()) {
-                    /* No information on this cpu (yet?), skip it for now */
-                    continue;
-                }
-                List<ITmfStateInterval> currentThreadIntervals = new ArrayList<>(fullStates.size() + 2);
-                try {
-                    /*
-                     * Add the previous interval if it is the first query
-                     * iteration and the first interval has currentThread=0. Add
-                     * the following interval if the last interval has
-                     * currentThread=0. These are diagonal arrows crossing the
-                     * query iteration range.
-                     */
-                    if (prevFullState == null) {
-                        ITmfStateInterval currentThreadInterval = fullStates.get(0).get(currentThreadQuark);
-                        if (currentThreadInterval.getStateValue().unboxInt() == 0) {
-                            long start = Math.max(currentThreadInterval.getStartTime() - 1, ss.getStartTime());
-                            currentThreadIntervals.add(ss.querySingleState(start, currentThreadQuark));
-                        }
-                    }
-                    for (List<ITmfStateInterval> fullState : fullStates) {
-                        currentThreadIntervals.add(fullState.get(currentThreadQuark));
-                    }
-                    ITmfStateInterval currentThreadInterval = fullStates.get(fullStates.size() - 1).get(currentThreadQuark);
-                    if (currentThreadInterval.getStateValue().unboxInt() == 0) {
-                        long end = Math.min(currentThreadInterval.getEndTime() + 1, ss.getCurrentEndTime());
-                        currentThreadIntervals.add(ss.querySingleState(end, currentThreadQuark));
-                    }
-                } catch (AttributeNotFoundException e) {
-                    Activator.getDefault().logError(e.getMessage());
-                    return list;
-                } catch (StateSystemDisposedException e) {
-                    /* Ignored */
-                    return list;
-                }
-                int prevThread = 0;
-                long prevEnd = 0;
-                long lastEnd = 0;
-                for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) {
-                    if (monitor.isCanceled()) {
-                        return list;
-                    }
-                    if (currentThreadInterval.getEndTime() + 1 == lastEnd) {
-                        continue;
-                    }
-                    long time = currentThreadInterval.getStartTime();
-                    if (time != lastEnd) {
-                        // don't create links where there are gaps in intervals due to the resolution
-                        prevThread = 0;
-                        prevEnd = 0;
-                    }
-                    int thread = currentThreadInterval.getStateValue().unboxInt();
-                    if (thread > 0 && prevThread > 0) {
-                        ITimeGraphEntry prevEntry = findEntry(entryList, trace, prevThread);
-                        ITimeGraphEntry nextEntry = findEntry(entryList, trace, thread);
-                        list.add(new TimeLinkEvent(prevEntry, nextEntry, prevEnd, time - prevEnd, 0));
-                    }
-                    lastEnd = currentThreadInterval.getEndTime() + 1;
-                    if (thread != 0) {
-                        prevThread = thread;
-                        prevEnd = lastEnd;
-                    }
-                }
-            }
-        }
-        return list;
-    }
-
-    private ControlFlowEntry findEntry(List<? extends ITimeGraphEntry> entryList, ITmfTrace trace, int threadId) {
-        for (ITimeGraphEntry entry : entryList) {
-            if (entry instanceof ControlFlowEntry) {
-                ControlFlowEntry controlFlowEntry = (ControlFlowEntry) entry;
-                if (controlFlowEntry.getThreadId() == threadId && controlFlowEntry.getTrace() == trace) {
-                    return controlFlowEntry;
-                } else if (entry.hasChildren()) {
-                    controlFlowEntry = findEntry(entry.getChildren(), trace, threadId);
-                    if (controlFlowEntry != null) {
-                        return controlFlowEntry;
-                    }
-                }
-            }
-        }
-        return null;
-    }
-}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.java
new file mode 100644 (file)
index 0000000..d12fe25
--- /dev/null
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Keba AG
+ *
+ * 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
+ *
+ * Contributors:
+ *   Christian Mansky - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;
+
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.ITimeGraphEntryActiveProvider;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+
+/**
+ * Provides Functionality for check Active / uncheck inactive
+ *
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ * @noextend This class is not intended to be subclassed by clients.
+ * @since 1.0
+ */
+public class ControlFlowCheckActiveProvider implements ITimeGraphEntryActiveProvider {
+
+    String fLabel;
+    String fTooltip;
+
+    /**
+     * @param label
+     *            Button label
+     * @param tooltip
+     *            Button tooltip
+     */
+    public ControlFlowCheckActiveProvider(String label, String tooltip) {
+        fLabel = label;
+        fTooltip = tooltip;
+    }
+
+    @Override
+    public String getLabel() {
+        return fLabel;
+    }
+
+    @Override
+    public String getTooltip() {
+        return fTooltip;
+    }
+
+    @Override
+    public boolean isActive(ITimeGraphEntry element) {
+        if (element instanceof ControlFlowEntry) {
+            ControlFlowEntry cfe = (ControlFlowEntry) element;
+
+            TmfTraceManager traceManager = TmfTraceManager.getInstance();
+            TmfTraceContext traceContext = traceManager.getCurrentTraceContext();
+            TmfTimeRange winRange = traceContext.getWindowRange();
+            TmfTimeRange selRange = traceContext.getSelectionRange();
+
+            /* Take precedence of selection over window range. */
+            long beginTS = selRange.getStartTime().getValue();
+            long endTS = selRange.getEndTime().getValue();
+
+            /* No selection, take window range */
+            if (beginTS == endTS) {
+                beginTS = winRange.getStartTime().getValue();
+                endTS = winRange.getEndTime().getValue();
+            }
+
+            ITmfTrace trace = cfe.getTrace();
+            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
+            if (ssq != null) {
+                beginTS = Math.max(beginTS, ssq.getStartTime());
+                endTS = Math.min(endTS, ssq.getCurrentEndTime());
+                if (beginTS > endTS) {
+                    return false;
+                }
+                try {
+                    int statusQuark = ssq.getQuarkRelative(cfe.getThreadQuark(), Attributes.STATUS);
+
+                    /* Get the initial state at beginTS */
+                    ITmfStateInterval currentInterval = ssq.querySingleState(beginTS, statusQuark);
+                    if (isIntervalInStateActive(currentInterval)) {
+                        return true;
+                    }
+
+                    /* Get the following state changes */
+                    long ts = currentInterval.getEndTime();
+                    while (ts != -1 && ts < endTS) {
+                        ts++; /* To "jump over" to the next state in the history */
+                        currentInterval = ssq.querySingleState(ts, statusQuark);
+                        if (isIntervalInStateActive(currentInterval)) {
+                            return true;
+                        }
+                        ts = currentInterval.getEndTime();
+                    }
+                } catch (AttributeNotFoundException | StateSystemDisposedException e) {
+                    /* Ignore ... */
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private static boolean isIntervalInStateActive (ITmfStateInterval ival) {
+        int value = ival.getStateValue().unboxInt();
+        /* An entry is only active when running */
+        if (value == StateValues.PROCESS_STATUS_RUN_USERMODE || value == StateValues.PROCESS_STATUS_RUN_SYSCALL ||
+                value == StateValues.PROCESS_STATUS_INTERRUPTED) {
+            return true;
+        }
+
+        return false;
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowEntry.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowEntry.java
new file mode 100644 (file)
index 0000000..cfdfcf3
--- /dev/null
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2016 Ericsson, École Polytechnique de Montréal
+ *
+ * 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
+ *
+ * Contributors:
+ *   Patrick Tasse - Initial API and implementation
+ *   Geneviève Bastien - Move code to provide base classes for time graph view
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;
+
+import java.util.regex.Pattern;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
+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;
+
+/**
+ * An entry in the Control Flow view
+ */
+public class ControlFlowEntry extends TimeGraphEntry {
+
+    private final @NonNull ITmfTrace fTrace;
+    private final int fThreadId;
+    private int fParentThreadId;
+    private final int fThreadQuark;
+
+    /**
+     * Constructor
+     *
+     * @param quark
+     *            The attribute quark matching the thread
+     * @param trace
+     *            The trace on which we are working
+     * @param execName
+     *            The exec_name of this entry
+     * @param threadId
+     *            The TID of the thread
+     * @param parentThreadId
+     *            the Parent_TID of this thread
+     * @param startTime
+     *            The start time of this process's lifetime
+     * @param endTime
+     *            The end time of this process
+     */
+    public ControlFlowEntry(int quark, @NonNull ITmfTrace trace, String execName, int threadId, int parentThreadId, long startTime, long endTime) {
+        super(execName, startTime, endTime);
+        fTrace = trace;
+        fThreadId = threadId;
+        fParentThreadId = parentThreadId;
+        fThreadQuark = quark;
+    }
+
+    /**
+     * Get this entry's thread ID
+     *
+     * @return The TID
+     */
+    public int getThreadId() {
+        return fThreadId;
+    }
+
+    /**
+     * Get the entry's trace
+     *
+     * @return the entry's trace
+     */
+    public @NonNull ITmfTrace getTrace() {
+        return fTrace;
+    }
+
+    /**
+     * Get this thread's parent TID
+     *
+     * @return The "PTID"
+     */
+    public int getParentThreadId() {
+        return fParentThreadId;
+    }
+
+    /**
+     * Set this thread's parent TID
+     *
+     * @param ptid
+     *            The "PTID"
+     * @since 1.1
+     */
+    public void setParentThreadId(int ptid) {
+        fParentThreadId = ptid;
+    }
+
+    /**
+     * Get the quark of the attribute matching this thread's TID
+     *
+     * @return The quark
+     */
+    public int getThreadQuark() {
+        return fThreadQuark;
+    }
+
+    @Override
+    public boolean matches(@NonNull Pattern pattern) {
+        if (pattern.matcher(getName()).find()) {
+            return true;
+        }
+        if (pattern.matcher(Integer.toString(fThreadId)).find()) {
+            return true;
+        }
+        if (pattern.matcher(Integer.toString(fParentThreadId)).find()) {
+            return true;
+        }
+        if (pattern.matcher(Integer.toString(fThreadQuark)).find()) {
+            return true;
+        }
+        if (pattern.matcher(Utils.formatTime(getStartTime(), TimeFormat.CALENDAR, Resolution.NANOSEC)).find()) {
+            return true;
+        }
+        return pattern.matcher(fTrace.getName()).find();
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + '(' + getName() + '[' + fThreadId + "])"; //$NON-NLS-1$
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowPresentationProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowPresentationProvider.java
new file mode 100644 (file)
index 0000000..f36d274
--- /dev/null
@@ -0,0 +1,242 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal
+ *
+ * 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
+ *
+ * Contributors:
+ *   Patrick Tasse - Initial API and implementation
+ *   Geneviève Bastien - Move code to provide base classes for time graph view
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
+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.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
+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.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
+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.widgets.Utils;
+
+/**
+ * Presentation provider for the control flow view
+ */
+public class ControlFlowPresentationProvider extends TimeGraphPresentationProvider {
+
+    private enum State {
+        UNKNOWN        (new RGB(100, 100, 100)),
+        WAIT_UNKNOWN   (new RGB(200, 200, 200)),
+        WAIT_BLOCKED   (new RGB(200, 200, 0)),
+        WAIT_FOR_CPU   (new RGB(200, 100, 0)),
+        USERMODE       (new RGB(0,   200, 0)),
+        SYSCALL        (new RGB(0,     0, 200)),
+        INTERRUPTED    (new RGB(200,   0, 100));
+
+        public final RGB rgb;
+
+        private State(RGB rgb) {
+            this.rgb = rgb;
+        }
+
+    }
+
+    /**
+     * Average width of the characters used for state labels. Is computed in the
+     * first call to postDrawEvent(). Is null before that.
+     */
+    private Integer fAverageCharacterWidth = null;
+
+    /**
+     * Default constructor
+     */
+    public ControlFlowPresentationProvider() {
+        super(Messages.ControlFlowView_stateTypeName);
+    }
+
+    private static State[] getStateValues() {
+        return State.values();
+    }
+
+    @Override
+    public StateItem[] getStateTable() {
+        State[] states = getStateValues();
+        StateItem[] stateTable = new StateItem[states.length];
+        for (int i = 0; i < stateTable.length; i++) {
+            State state = states[i];
+            stateTable[i] = new StateItem(state.rgb, state.toString());
+        }
+        return stateTable;
+    }
+
+    @Override
+    public int getStateTableIndex(ITimeEvent event) {
+        if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) {
+            int status = ((TimeEvent) event).getValue();
+            return getMatchingState(status).ordinal();
+        }
+        if (event instanceof NullTimeEvent) {
+            return INVISIBLE;
+        }
+        return TRANSPARENT;
+    }
+
+    @Override
+    public String getEventName(ITimeEvent event) {
+        if (event instanceof TimeEvent) {
+            TimeEvent ev = (TimeEvent) event;
+            if (ev.hasValue()) {
+                return getMatchingState(ev.getValue()).toString();
+            }
+        }
+        return Messages.ControlFlowView_multipleStates;
+    }
+
+    private static State getMatchingState(int status) {
+        switch (status) {
+        case StateValues.PROCESS_STATUS_WAIT_UNKNOWN:
+            return State.WAIT_UNKNOWN;
+        case StateValues.PROCESS_STATUS_WAIT_BLOCKED:
+            return State.WAIT_BLOCKED;
+        case StateValues.PROCESS_STATUS_WAIT_FOR_CPU:
+            return State.WAIT_FOR_CPU;
+        case StateValues.PROCESS_STATUS_RUN_USERMODE:
+            return State.USERMODE;
+        case StateValues.PROCESS_STATUS_RUN_SYSCALL:
+            return State.SYSCALL;
+        case StateValues.PROCESS_STATUS_INTERRUPTED:
+            return State.INTERRUPTED;
+        default:
+            return State.UNKNOWN;
+        }
+    }
+
+    @Override
+    public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event) {
+        Map<String, String> retMap = new LinkedHashMap<>();
+        if (!(event instanceof TimeEvent) || !((TimeEvent) event).hasValue() ||
+                !(event.getEntry() instanceof ControlFlowEntry)) {
+            return retMap;
+        }
+        ControlFlowEntry entry = (ControlFlowEntry) event.getEntry();
+        ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
+        if (ssq == null) {
+            return retMap;
+        }
+        int tid = entry.getThreadId();
+
+        try {
+            // Find every CPU first, then get the current thread
+            int cpusQuark = ssq.getQuarkAbsolute(Attributes.CPUS);
+            List<Integer> cpuQuarks = ssq.getSubAttributes(cpusQuark, false);
+            for (Integer cpuQuark : cpuQuarks) {
+                int currentThreadQuark = ssq.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
+                ITmfStateInterval interval = ssq.querySingleState(event.getTime(), currentThreadQuark);
+                if (!interval.getStateValue().isNull()) {
+                    ITmfStateValue state = interval.getStateValue();
+                    int currentThreadId = state.unboxInt();
+                    if (tid == currentThreadId) {
+                        retMap.put(Messages.ControlFlowView_attributeCpuName, ssq.getAttributeName(cpuQuark));
+                        break;
+                    }
+                }
+            }
+
+        } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
+            Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
+        } catch (StateSystemDisposedException e) {
+            /* Ignored */
+        }
+        int status = ((TimeEvent) event).getValue();
+        if (status == StateValues.PROCESS_STATUS_RUN_SYSCALL) {
+            try {
+                int syscallQuark = ssq.getQuarkRelative(entry.getThreadQuark(), Attributes.SYSTEM_CALL);
+                ITmfStateInterval value = ssq.querySingleState(event.getTime(), syscallQuark);
+                if (!value.getStateValue().isNull()) {
+                    ITmfStateValue state = value.getStateValue();
+                    retMap.put(Messages.ControlFlowView_attributeSyscallName, state.toString());
+                }
+
+            } catch (AttributeNotFoundException | TimeRangeException e) {
+                Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
+            } catch (StateSystemDisposedException e) {
+                /* Ignored */
+            }
+        }
+
+        return retMap;
+    }
+
+    @Override
+    public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) {
+        if (fAverageCharacterWidth == null) {
+            fAverageCharacterWidth = gc.getFontMetrics().getAverageCharWidth();
+        }
+        if (bounds.width <= fAverageCharacterWidth) {
+            return;
+        }
+        if (!(event instanceof TimeEvent)) {
+            return;
+        }
+        ControlFlowEntry entry = (ControlFlowEntry) event.getEntry();
+        ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
+        if (ss == null) {
+            return;
+        }
+        int status = ((TimeEvent) event).getValue();
+
+        if (status != StateValues.PROCESS_STATUS_RUN_SYSCALL) {
+            return;
+        }
+        try {
+            int syscallQuark = ss.getQuarkRelative(entry.getThreadQuark(), Attributes.SYSTEM_CALL);
+            ITmfStateInterval value = ss.querySingleState(event.getTime(), syscallQuark);
+            if (!value.getStateValue().isNull()) {
+                ITmfStateValue state = value.getStateValue();
+                gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
+
+                /*
+                 * Remove the "sys_" or "syscall_entry_" or similar from what we
+                 * draw in the rectangle. This depends on the trace's event layout.
+                 */
+                int beginIndex = 0;
+                ITmfTrace trace = entry.getTrace();
+                if (trace instanceof IKernelTrace) {
+                    IKernelAnalysisEventLayout layout = ((IKernelTrace) trace).getKernelEventLayout();
+                    beginIndex = layout.eventSyscallEntryPrefix().length();
+                }
+
+                Utils.drawText(gc, state.toString().substring(beginIndex), bounds.x, bounds.y, bounds.width, bounds.height, true, true);
+            }
+        } catch (AttributeNotFoundException | TimeRangeException e) {
+            Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
+        } catch (StateSystemDisposedException e) {
+            /* Ignored */
+        }
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowView.java
new file mode 100644 (file)
index 0000000..5db6079
--- /dev/null
@@ -0,0 +1,660 @@
+/*******************************************************************************
+ * 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
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   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
+ *******************************************************************************/
+
+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.List;
+import java.util.Map;
+
+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.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.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
+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.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;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+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.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
+ *
+ */
+public class ControlFlowView extends AbstractStateSystemTimeGraphView {
+
+    // ------------------------------------------------------------------------
+    // Constants
+    // ------------------------------------------------------------------------
+    /**
+     * View ID.
+     */
+    public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.controlflow"; //$NON-NLS-1$
+
+    private static final String PROCESS_COLUMN = Messages.ControlFlowView_processColumn;
+    private static final String TID_COLUMN = Messages.ControlFlowView_tidColumn;
+    private static final String PTID_COLUMN = Messages.ControlFlowView_ptidColumn;
+    private static final String BIRTH_TIME_COLUMN = Messages.ControlFlowView_birthTimeColumn;
+    private static final String TRACE_COLUMN = Messages.ControlFlowView_traceColumn;
+
+    private static final String[] COLUMN_NAMES = new String[] {
+            PROCESS_COLUMN,
+            TID_COLUMN,
+            PTID_COLUMN,
+            BIRTH_TIME_COLUMN,
+            TRACE_COLUMN
+    };
+
+    private static final String[] FILTER_COLUMN_NAMES = new String[] {
+            PROCESS_COLUMN,
+            TID_COLUMN
+    };
+
+    // 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
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructor
+     */
+    public ControlFlowView() {
+        super(ID, new ControlFlowPresentationProvider());
+        setTreeColumns(COLUMN_NAMES, COLUMN_COMPARATORS, INITIAL_SORT_COLUMN_INDEX);
+        setTreeLabelProvider(new ControlFlowTreeLabelProvider());
+        setFilterColumns(FILTER_COLUMN_NAMES);
+        setFilterLabelProvider(new ControlFlowFilterLabelProvider());
+        setEntryComparator(ControlFlowColumnComparators.BIRTH_TIME_COLUMN_COMPARATOR);
+    }
+
+    @Override
+    public void createPartControl(Composite parent) {
+        super.createPartControl(parent);
+        // add "Check active" Button to TimeGraphFilterDialog
+        super.getTimeGraphCombo().addTimeGraphFilterCheckActiveButton(
+                new ControlFlowCheckActiveProvider(Messages.ControlFlowView_checkActiveLabel, Messages.ControlFlowView_checkActiveToolTip));
+        // add "Uncheck inactive" Button to TimeGraphFilterDialog
+        super.getTimeGraphCombo().addTimeGraphFilterUncheckInactiveButton(
+                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);
+        IDialogSettings settings = Activator.getDefault().getDialogSettings();
+        IDialogSettings section = settings.getSection(getClass().getName());
+        if (section == null) {
+            section = settings.addNewSection(getClass().getName());
+        }
+
+        IAction hideArrowsAction = getTimeGraphCombo().getTimeGraphViewer().getHideArrowsAction(section);
+        manager.add(hideArrowsAction);
+
+        IAction followArrowBwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowBwdAction();
+        followArrowBwdAction.setText(Messages.ControlFlowView_followCPUBwdText);
+        followArrowBwdAction.setToolTipText(Messages.ControlFlowView_followCPUBwdText);
+        manager.add(followArrowBwdAction);
+
+        IAction followArrowFwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowFwdAction();
+        followArrowFwdAction.setText(Messages.ControlFlowView_followCPUFwdText);
+        followArrowFwdAction.setToolTipText(Messages.ControlFlowView_followCPUFwdText);
+        manager.add(followArrowFwdAction);
+    }
+
+    @Override
+    protected String getNextText() {
+        return Messages.ControlFlowView_nextProcessActionNameText;
+    }
+
+    @Override
+    protected String getNextTooltip() {
+        return Messages.ControlFlowView_nextProcessActionToolTipText;
+    }
+
+    @Override
+    protected String getPrevText() {
+        return Messages.ControlFlowView_previousProcessActionNameText;
+    }
+
+    @Override
+    protected String getPrevTooltip() {
+        return Messages.ControlFlowView_previousProcessActionToolTipText;
+    }
+
+    /**
+     * @author gbastien
+     *
+     */
+    protected static class ControlFlowTreeLabelProvider extends TreeLabelProvider {
+
+        @Override
+        public String getColumnText(Object element, int columnIndex) {
+            ControlFlowEntry entry = (ControlFlowEntry) element;
+
+            if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_processColumn)) {
+                return entry.getName();
+            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_tidColumn)) {
+                return Integer.toString(entry.getThreadId());
+            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_ptidColumn)) {
+                if (entry.getParentThreadId() > 0) {
+                    return Integer.toString(entry.getParentThreadId());
+                }
+            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_birthTimeColumn)) {
+                return Utils.formatTime(entry.getStartTime(), TimeFormat.CALENDAR, Resolution.NANOSEC);
+            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_traceColumn)) {
+                return entry.getTrace().getName();
+            }
+            return ""; //$NON-NLS-1$
+        }
+
+    }
+
+    private static class ControlFlowFilterLabelProvider extends TreeLabelProvider {
+
+        @Override
+        public String getColumnText(Object element, int columnIndex) {
+            ControlFlowEntry entry = (ControlFlowEntry) element;
+
+            if (columnIndex == 0) {
+                return entry.getName();
+            } else if (columnIndex == 1) {
+                return Integer.toString(entry.getThreadId());
+            }
+            return ""; //$NON-NLS-1$
+        }
+
+    }
+
+    // ------------------------------------------------------------------------
+    // Internal
+    // ------------------------------------------------------------------------
+
+    @Override
+    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<>();
+        /** 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));
+
+        boolean complete = false;
+        while (!complete) {
+            if (monitor.isCanceled()) {
+                return;
+            }
+            complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
+            if (ssq.isCancelled()) {
+                return;
+            }
+            long end = ssq.getCurrentEndTime();
+            if (start == end && !complete) { // when complete execute one last time regardless of end time
+                continue;
+            }
+            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$
+            queryFullStates(ssq, start, end, resolution, monitor, new IQueryHandler() {
+                @Override
+                public void handle(List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState) {
+                    for (int threadQuark : threadQuarks) {
+                        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;
+                        }
+
+                        int execNameQuark;
+                        int ppidQuark;
+                        try {
+                            execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME);
+                            ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID);
+                        } catch (AttributeNotFoundException e) {
+                            /* No information on this thread (yet?), skip it for now */
+                            continue;
+                        }
+                        ITmfStateInterval lastExecNameInterval = prevFullState == null || execNameQuark >= prevFullState.size() ? null : prevFullState.get(execNameQuark);
+                        long lastExecNameStartTime = lastExecNameInterval == null ? -1 : lastExecNameInterval.getStartTime();
+                        long lastExecNameEndTime = lastExecNameInterval == null ? -1 : lastExecNameInterval.getEndTime() + 1;
+                        long lastPpidStartTime = prevFullState == null || ppidQuark >= prevFullState.size() ? -1 : prevFullState.get(ppidQuark).getStartTime();
+                        for (List<ITmfStateInterval> fullState : fullStates) {
+                            if (monitor.isCanceled()) {
+                                return;
+                            }
+                            if (execNameQuark >= fullState.size() || ppidQuark >= fullState.size()) {
+                                /* No information on this thread (yet?), skip it for now */
+                                continue;
+                            }
+                            ITmfStateInterval execNameInterval = fullState.get(execNameQuark);
+                            ITmfStateInterval ppidInterval = fullState.get(ppidQuark);
+                            long startTime = execNameInterval.getStartTime();
+                            long endTime = execNameInterval.getEndTime() + 1;
+                            if (startTime == lastExecNameStartTime && ppidInterval.getStartTime() == lastPpidStartTime) {
+                                continue;
+                            }
+                            boolean isNull = execNameInterval.getStateValue().isNull();
+                            if (isNull && lastExecNameEndTime < startTime && lastExecNameEndTime != -1) {
+                                /*
+                                 * There was a non-null interval in between the
+                                 * full states, try to use it.
+                                 */
+                                try {
+                                    execNameInterval = ssq.querySingleState(startTime - 1, execNameQuark);
+                                    ppidInterval = ssq.querySingleState(startTime - 1, ppidQuark);
+                                    startTime = execNameInterval.getStartTime();
+                                    endTime = execNameInterval.getEndTime() + 1;
+                                } catch (AttributeNotFoundException e) {
+                                    Activator.getDefault().logError(e.getMessage());
+                                } catch (StateSystemDisposedException e) {
+                                    /* ignored */
+                                }
+                            }
+                            if (!execNameInterval.getStateValue().isNull() &&
+                                    execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
+                                String execName = execNameInterval.getStateValue().unboxStr();
+                                int ppid = ppidInterval.getStateValue().unboxInt();
+                                ControlFlowEntry entry = entryMap.get(entryKey);
+                                if (entry == null) {
+                                    entry = new ControlFlowEntry(threadQuark, trace, execName, threadId, ppid, startTime, endTime);
+                                    entryList.add(entry);
+                                    entryMap.put(entryKey, entry);
+                                } else {
+                                    /*
+                                     * Update the name of the entry to the
+                                     * latest execName and the parent thread id
+                                     * to the latest ppid.
+                                     */
+                                    entry.setName(execName);
+                                    entry.setParentThreadId(ppid);
+                                    entry.updateEndTime(endTime);
+                                }
+                            }
+                            if (isNull) {
+                                entryMap.remove(entryKey);
+                            }
+                            lastExecNameStartTime = startTime;
+                            lastExecNameEndTime = endTime;
+                            lastPpidStartTime = ppidInterval.getStartTime();
+                        }
+                    }
+                    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, ssq.getStartTime(), end);
+                    }
+                }
+            });
+
+            if (parentTrace.equals(getTrace())) {
+                refresh();
+            }
+
+            start = end;
+        }
+    }
+
+    private void updateTree(List<ControlFlowEntry> entryList, ITmfTrace parentTrace, ITmfStateSystem ss) {
+        List<TimeGraphEntry> rootListToAdd = new ArrayList<>();
+        List<TimeGraphEntry> rootListToRemove = new ArrayList<>();
+        List<TimeGraphEntry> rootList = getEntryList(ss);
+
+        for (ControlFlowEntry entry : entryList) {
+            boolean root = (entry.getParent() == null);
+            if (root && entry.getParentThreadId() > 0) {
+                for (ControlFlowEntry parent : entryList) {
+                    /*
+                     * Associate the parent entry only if their time overlap. A
+                     * child entry may start before its parent, for example at
+                     * the beginning of the trace if a parent has not yet
+                     * appeared in the state system. We just want to make sure
+                     * that the entry didn't start after the parent ended or
+                     * ended before the parent started.
+                     */
+                    if (parent.getThreadId() == entry.getParentThreadId() &&
+                            !(entry.getStartTime() > parent.getEndTime() ||
+                            entry.getEndTime() < parent.getStartTime())) {
+                        parent.addChild(entry);
+                        root = false;
+                        if (rootList != null && rootList.contains(entry)) {
+                            rootListToRemove.add(entry);
+                        }
+                        break;
+                    }
+                }
+            }
+            if (root && (rootList == null || !rootList.contains(entry))) {
+                rootListToAdd.add(entry);
+            }
+        }
+
+        addToEntryList(parentTrace, ss, rootListToAdd);
+        removeFromEntryList(parentTrace, ss, rootListToRemove);
+    }
+
+    private void buildStatusEvents(ITmfTrace trace, ITmfTrace parentTrace, ITmfStateSystem ss, @NonNull List<List<ITmfStateInterval>> fullStates,
+            @Nullable List<ITmfStateInterval> prevFullState, ControlFlowEntry entry, @NonNull IProgressMonitor monitor, long start, long end) {
+        if (start < entry.getEndTime() && end > entry.getStartTime()) {
+            List<ITimeEvent> eventList = getEventList(entry, ss, fullStates, prevFullState, monitor);
+            if (eventList == null) {
+                return;
+            }
+            /* 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();
+            }
+        }
+        for (ITimeGraphEntry child : entry.getChildren()) {
+            if (monitor.isCanceled()) {
+                return;
+            }
+            buildStatusEvents(trace, parentTrace, ss, fullStates, prevFullState, (ControlFlowEntry) child, monitor, start, end);
+        }
+    }
+
+    @Override
+    protected @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry tgentry, ITmfStateSystem ss,
+            @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
+        List<ITimeEvent> eventList = null;
+        if (!(tgentry instanceof ControlFlowEntry)) {
+            return eventList;
+        }
+        ControlFlowEntry entry = (ControlFlowEntry) tgentry;
+        try {
+            int threadQuark = entry.getThreadQuark();
+            int statusQuark = ss.getQuarkRelative(threadQuark, Attributes.STATUS);
+            eventList = new ArrayList<>(fullStates.size());
+            ITmfStateInterval lastInterval = prevFullState == null || statusQuark >= prevFullState.size() ? null : prevFullState.get(statusQuark);
+            long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime();
+            long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1;
+            for (List<ITmfStateInterval> fullState : fullStates) {
+                if (monitor.isCanceled()) {
+                    return null;
+                }
+                if (statusQuark >= fullState.size()) {
+                    /* No information on this thread (yet?), skip it for now */
+                    continue;
+                }
+                ITmfStateInterval statusInterval = fullState.get(statusQuark);
+                long time = statusInterval.getStartTime();
+                if (time == lastStartTime) {
+                    continue;
+                }
+                long duration = statusInterval.getEndTime() - time + 1;
+                int status = -1;
+                try {
+                    status = statusInterval.getStateValue().unboxInt();
+                } catch (StateValueTypeException e) {
+                    Activator.getDefault().logError(e.getMessage());
+                }
+                if (lastEndTime != time && lastEndTime != -1) {
+                    eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
+                }
+                if (!statusInterval.getStateValue().isNull()) {
+                    eventList.add(new TimeEvent(entry, time, duration, status));
+                } else {
+                    eventList.add(new NullTimeEvent(entry, time, duration));
+                }
+                lastStartTime = time;
+                lastEndTime = time + duration;
+            }
+        } catch (AttributeNotFoundException | TimeRangeException e) {
+            Activator.getDefault().logError(e.getMessage());
+        }
+        return eventList;
+    }
+
+    /**
+     * Returns a value corresponding to the selected entry.
+     *
+     * Used in conjunction with synchingToTime to change the selected entry. If
+     * one of these methods is overridden in child class, then both should be.
+     *
+     * @param time
+     *            The currently selected time
+     * @return a value identifying the entry
+     */
+    private int getSelectionValue(long time) {
+        int thread = -1;
+        for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) {
+            if (thread > 0) {
+                break;
+            }
+            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
+            if (ssq == null) {
+                continue;
+            }
+            if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) {
+                List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
+                for (int currentThreadQuark : currentThreadQuarks) {
+                    try {
+                        ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark);
+                        int currentThread = currentThreadInterval.getStateValue().unboxInt();
+                        if (currentThread > 0) {
+                            int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS);
+                            ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark);
+                            if (statusInterval.getStartTime() == time) {
+                                thread = currentThread;
+                                break;
+                            }
+                        }
+                    } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
+                        Activator.getDefault().logError(e.getMessage());
+                    } catch (StateSystemDisposedException e) {
+                        /* Ignored */
+                    }
+                }
+            }
+        }
+        return thread;
+    }
+
+    @Override
+    protected void synchingToTime(long time) {
+        int selected = getSelectionValue(time);
+        if (selected > 0) {
+            for (Object element : getTimeGraphViewer().getExpandedElements()) {
+                if (element instanceof ControlFlowEntry) {
+                    ControlFlowEntry entry = (ControlFlowEntry) element;
+                    if (entry.getThreadId() == selected) {
+                        getTimeGraphCombo().setSelection(entry);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    protected @NonNull List<ILinkEvent> getLinkList(ITmfStateSystem ss,
+            @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
+        List<ILinkEvent> list = new ArrayList<>();
+        List<TimeGraphEntry> entryList = getEntryList(ss);
+        if (entryList == null) {
+            return list;
+        }
+        for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) {
+            List<Integer> currentThreadQuarks = ss.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
+            for (int currentThreadQuark : currentThreadQuarks) {
+                if (currentThreadQuark >= fullStates.get(0).size()) {
+                    /* No information on this cpu (yet?), skip it for now */
+                    continue;
+                }
+                List<ITmfStateInterval> currentThreadIntervals = new ArrayList<>(fullStates.size() + 2);
+                try {
+                    /*
+                     * Add the previous interval if it is the first query
+                     * iteration and the first interval has currentThread=0. Add
+                     * the following interval if the last interval has
+                     * currentThread=0. These are diagonal arrows crossing the
+                     * query iteration range.
+                     */
+                    if (prevFullState == null) {
+                        ITmfStateInterval currentThreadInterval = fullStates.get(0).get(currentThreadQuark);
+                        if (currentThreadInterval.getStateValue().unboxInt() == 0) {
+                            long start = Math.max(currentThreadInterval.getStartTime() - 1, ss.getStartTime());
+                            currentThreadIntervals.add(ss.querySingleState(start, currentThreadQuark));
+                        }
+                    }
+                    for (List<ITmfStateInterval> fullState : fullStates) {
+                        currentThreadIntervals.add(fullState.get(currentThreadQuark));
+                    }
+                    ITmfStateInterval currentThreadInterval = fullStates.get(fullStates.size() - 1).get(currentThreadQuark);
+                    if (currentThreadInterval.getStateValue().unboxInt() == 0) {
+                        long end = Math.min(currentThreadInterval.getEndTime() + 1, ss.getCurrentEndTime());
+                        currentThreadIntervals.add(ss.querySingleState(end, currentThreadQuark));
+                    }
+                } catch (AttributeNotFoundException e) {
+                    Activator.getDefault().logError(e.getMessage());
+                    return list;
+                } catch (StateSystemDisposedException e) {
+                    /* Ignored */
+                    return list;
+                }
+                int prevThread = 0;
+                long prevEnd = 0;
+                long lastEnd = 0;
+                for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) {
+                    if (monitor.isCanceled()) {
+                        return list;
+                    }
+                    if (currentThreadInterval.getEndTime() + 1 == lastEnd) {
+                        continue;
+                    }
+                    long time = currentThreadInterval.getStartTime();
+                    if (time != lastEnd) {
+                        // don't create links where there are gaps in intervals due to the resolution
+                        prevThread = 0;
+                        prevEnd = 0;
+                    }
+                    int thread = currentThreadInterval.getStateValue().unboxInt();
+                    if (thread > 0 && prevThread > 0) {
+                        ITimeGraphEntry prevEntry = findEntry(entryList, trace, prevThread);
+                        ITimeGraphEntry nextEntry = findEntry(entryList, trace, thread);
+                        list.add(new TimeLinkEvent(prevEntry, nextEntry, prevEnd, time - prevEnd, 0));
+                    }
+                    lastEnd = currentThreadInterval.getEndTime() + 1;
+                    if (thread != 0) {
+                        prevThread = thread;
+                        prevEnd = lastEnd;
+                    }
+                }
+            }
+        }
+        return list;
+    }
+
+    private ControlFlowEntry findEntry(List<? extends ITimeGraphEntry> entryList, ITmfTrace trace, int threadId) {
+        for (ITimeGraphEntry entry : entryList) {
+            if (entry instanceof ControlFlowEntry) {
+                ControlFlowEntry controlFlowEntry = (ControlFlowEntry) entry;
+                if (controlFlowEntry.getThreadId() == threadId && controlFlowEntry.getTrace() == trace) {
+                    return controlFlowEntry;
+                } else if (entry.hasChildren()) {
+                    controlFlowEntry = findEntry(entry.getChildren(), trace, threadId);
+                    if (controlFlowEntry != null) {
+                        return controlFlowEntry;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+}
index 68424f33ad8df2cf355fb67e5a819f8a09dbb211..eaf69492360e0f092f5cd1d985599ff01230c305 100644 (file)
@@ -11,7 +11,6 @@ package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow
 import java.util.Comparator;
 
 import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowEntry;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
 
index b9858daca62b23284529e92c4c7f883cc87cd82f..48b606c8241fc9a2891b75775963fe02e4a026a7 100644 (file)
@@ -27,7 +27,7 @@ import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
 import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
 import org.eclipse.swtbot.swt.finder.results.VoidResult;
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton;
-import org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowView;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowView;
 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesView;
 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
index 82fba6fb19b75d4cafe3e5dbbb2cd5d33312b351..16e3b233455922c5c49198b8360b237d04a7d0e4 100644 (file)
@@ -15,7 +15,7 @@ package org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests;
 import java.util.ArrayList;
 import java.util.Arrays;
 
-import org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowView;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowView;
 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesView;
 import org.eclipse.tracecompass.internal.lttng2.control.ui.views.ControlView;
 import org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.PerspectiveFactory;
index 934920cc5bb569ff830c5c11a16fa4acb2dea1ff..e24a228e2309381be3aba62dc88619dcd95d25c8 100644 (file)
@@ -12,8 +12,8 @@
 
 package org.eclipse.tracecompass.internal.lttng2.kernel.ui.views;
 
-import org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowView;
 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesView;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowView;
 import org.eclipse.tracecompass.internal.lttng2.control.ui.views.ControlView;
 import org.eclipse.tracecompass.tmf.ui.project.wizards.NewTmfProjectWizard;
 import org.eclipse.tracecompass.tmf.ui.views.histogram.HistogramView;
This page took 0.050558 seconds and 5 git commands to generate.