From: Bernd Hufmann Date: Tue, 22 Mar 2016 11:12:48 +0000 (-0400) Subject: analysis: Bug 489573: Internalize Control Flow view implementation X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=ace7140d2d619ad4629a20a3ee74c4b8aefa192a;p=deliverable%2Ftracecompass.git analysis: Bug 489573: Internalize Control Flow view implementation Change-Id: I92e81e1b158cb5dbf1910f9d25b880482fdb3355 Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/69007 Reviewed-by: Hudson CI Reviewed-by: Matthew Khouzam Tested-by: Matthew Khouzam --- diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/controlflow/ControlFlowEntryComparatorTest.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/controlflow/ControlFlowEntryComparatorTest.java index 270849843d..6f95940189 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/controlflow/ControlFlowEntryComparatorTest.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/controlflow/ControlFlowEntryComparatorTest.java @@ -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; diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF index d7b1547389..e11b9b0942 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF @@ -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; diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml index d650f818b7..2cbb49cc07 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml @@ -6,7 +6,7 @@ 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 index 1b7a09b170..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowEntry.java +++ /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 index 49e58263e4..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowPresentationProvider.java +++ /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 getEventHoverToolTipInfo(ITimeEvent event) { - Map 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 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 index 2cde3f81d5..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java +++ /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[] COLUMN_COMPARATORS; - - private static final int INITIAL_SORT_COLUMN_INDEX = 3; - - static { - ImmutableList.Builder> 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> 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 entryList = new ArrayList<>(); - /** Map of view entries, key is a pair [threadId, cpuId] */ - final Map, 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 threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$ - queryFullStates(ssq, start, end, resolution, monitor, new IQueryHandler() { - @Override - public void handle(List> fullStates, List prevFullState) { - for (int threadQuark : threadQuarks) { - String threadAttributeName = ssq.getAttributeName(threadQuark); - - Pair 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 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> fullStates, @Nullable List 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 entryList, ITmfTrace parentTrace, ITmfStateSystem ss) { - List rootListToAdd = new ArrayList<>(); - List rootListToRemove = new ArrayList<>(); - List 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> fullStates, - @Nullable List prevFullState, ControlFlowEntry entry, @NonNull IProgressMonitor monitor, long start, long end) { - if (start < entry.getEndTime() && end > entry.getStartTime()) { - List 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 getEventList(@NonNull TimeGraphEntry tgentry, ITmfStateSystem ss, - @NonNull List> fullStates, @Nullable List prevFullState, @NonNull IProgressMonitor monitor) { - List 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 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 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 getLinkList(ITmfStateSystem ss, - @NonNull List> fullStates, @Nullable List prevFullState, @NonNull IProgressMonitor monitor) { - List list = new ArrayList<>(); - List entryList = getEntryList(ss); - if (entryList == null) { - return list; - } - for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) { - List 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 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 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 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 index 0000000000..d12fe25448 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.java @@ -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 index 0000000000..cfdfcf3316 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowEntry.java @@ -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 index 0000000000..f36d274c79 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowPresentationProvider.java @@ -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 getEventHoverToolTipInfo(ITimeEvent event) { + Map 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 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 index 0000000000..5db607983f --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowView.java @@ -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[] COLUMN_COMPARATORS; + + private static final int INITIAL_SORT_COLUMN_INDEX = 3; + + static { + ImmutableList.Builder> 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> 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 entryList = new ArrayList<>(); + /** Map of view entries, key is a pair [threadId, cpuId] */ + final Map, 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 threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$ + queryFullStates(ssq, start, end, resolution, monitor, new IQueryHandler() { + @Override + public void handle(List> fullStates, List prevFullState) { + for (int threadQuark : threadQuarks) { + String threadAttributeName = ssq.getAttributeName(threadQuark); + + Pair 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 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> fullStates, @Nullable List 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 entryList, ITmfTrace parentTrace, ITmfStateSystem ss) { + List rootListToAdd = new ArrayList<>(); + List rootListToRemove = new ArrayList<>(); + List 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> fullStates, + @Nullable List prevFullState, ControlFlowEntry entry, @NonNull IProgressMonitor monitor, long start, long end) { + if (start < entry.getEndTime() && end > entry.getStartTime()) { + List 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 getEventList(@NonNull TimeGraphEntry tgentry, ITmfStateSystem ss, + @NonNull List> fullStates, @Nullable List prevFullState, @NonNull IProgressMonitor monitor) { + List 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 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 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 getLinkList(ITmfStateSystem ss, + @NonNull List> fullStates, @Nullable List prevFullState, @NonNull IProgressMonitor monitor) { + List list = new ArrayList<>(); + List entryList = getEntryList(ss); + if (entryList == null) { + return list; + } + for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) { + List 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 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 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 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/IControlFlowEntryComparator.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/IControlFlowEntryComparator.java index 68424f33ad..eaf6949236 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/IControlFlowEntryComparator.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/IControlFlowEntryComparator.java @@ -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; diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ImportAndReadKernelSmokeTest.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ImportAndReadKernelSmokeTest.java index b9858daca6..48b606c824 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ImportAndReadKernelSmokeTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ImportAndReadKernelSmokeTest.java @@ -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; diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelPerspectiveChecker.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelPerspectiveChecker.java index 82fba6fb19..16e3b23345 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelPerspectiveChecker.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelPerspectiveChecker.java @@ -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; diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/PerspectiveFactory.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/PerspectiveFactory.java index 934920cc5b..e24a228e23 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/PerspectiveFactory.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/PerspectiveFactory.java @@ -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;