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;
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;
<view
allowMultiple="false"
category="org.eclipse.linuxtools.lttng2.ui.views.category"
- class="org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowView"
+ class="org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowView"
icon="icons/eview16/control_flow_view.gif"
id="org.eclipse.tracecompass.analysis.os.linux.views.controlflow"
name="%controlflow.view.name"
+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2015 Keba AG
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Christian Mansky - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow;
-
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
-import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
-import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
-import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
-import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
-import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
-import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
-import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.ITimeGraphEntryActiveProvider;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
-
-/**
- * Provides Functionality for check Active / uncheck inactive
- *
- * @noinstantiate This class is not intended to be instantiated by clients.
- * @noextend This class is not intended to be subclassed by clients.
- * @since 1.0
- */
-public class ControlFlowCheckActiveProvider implements ITimeGraphEntryActiveProvider {
-
- String fLabel;
- String fTooltip;
-
- /**
- * @param label
- * Button label
- * @param tooltip
- * Button tooltip
- */
- public ControlFlowCheckActiveProvider(String label, String tooltip) {
- fLabel = label;
- fTooltip = tooltip;
- }
-
- @Override
- public String getLabel() {
- return fLabel;
- }
-
- @Override
- public String getTooltip() {
- return fTooltip;
- }
-
- @Override
- public boolean isActive(ITimeGraphEntry element) {
- if (element instanceof ControlFlowEntry) {
- ControlFlowEntry cfe = (ControlFlowEntry) element;
-
- TmfTraceManager traceManager = TmfTraceManager.getInstance();
- TmfTraceContext traceContext = traceManager.getCurrentTraceContext();
- TmfTimeRange winRange = traceContext.getWindowRange();
- TmfTimeRange selRange = traceContext.getSelectionRange();
-
- /* Take precedence of selection over window range. */
- long beginTS = selRange.getStartTime().getValue();
- long endTS = selRange.getEndTime().getValue();
-
- /* No selection, take window range */
- if (beginTS == endTS) {
- beginTS = winRange.getStartTime().getValue();
- endTS = winRange.getEndTime().getValue();
- }
-
- ITmfTrace trace = cfe.getTrace();
- ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
- if (ssq != null) {
- beginTS = Math.max(beginTS, ssq.getStartTime());
- endTS = Math.min(endTS, ssq.getCurrentEndTime());
- if (beginTS > endTS) {
- return false;
- }
- try {
- int statusQuark = ssq.getQuarkRelative(cfe.getThreadQuark(), Attributes.STATUS);
-
- /* Get the initial state at beginTS */
- ITmfStateInterval currentInterval = ssq.querySingleState(beginTS, statusQuark);
- if (isIntervalInStateActive(currentInterval)) {
- return true;
- }
-
- /* Get the following state changes */
- long ts = currentInterval.getEndTime();
- while (ts != -1 && ts < endTS) {
- ts++; /* To "jump over" to the next state in the history */
- currentInterval = ssq.querySingleState(ts, statusQuark);
- if (isIntervalInStateActive(currentInterval)) {
- return true;
- }
- ts = currentInterval.getEndTime();
- }
- } catch (AttributeNotFoundException | StateSystemDisposedException e) {
- /* Ignore ... */
- }
- }
- }
-
- return false;
- }
-
- private static boolean isIntervalInStateActive (ITmfStateInterval ival) {
- int value = ival.getStateValue().unboxInt();
- /* An entry is only active when running */
- if (value == StateValues.PROCESS_STATUS_RUN_USERMODE || value == StateValues.PROCESS_STATUS_RUN_SYSCALL ||
- value == StateValues.PROCESS_STATUS_INTERRUPTED) {
- return true;
- }
-
- return false;
- }
-
-}
+++ /dev/null
-/*******************************************************************************
- * 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$
- }
-}
+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Patrick Tasse - Initial API and implementation
- * Geneviève Bastien - Move code to provide base classes for time graph view
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow;
-
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.RGB;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
-import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
-import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
-import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
-import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator;
-import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
-import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
-import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
-import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
-import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
-import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
-import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
-
-/**
- * Presentation provider for the control flow view
- */
-public class ControlFlowPresentationProvider extends TimeGraphPresentationProvider {
-
- private enum State {
- UNKNOWN (new RGB(100, 100, 100)),
- WAIT_UNKNOWN (new RGB(200, 200, 200)),
- WAIT_BLOCKED (new RGB(200, 200, 0)),
- WAIT_FOR_CPU (new RGB(200, 100, 0)),
- USERMODE (new RGB(0, 200, 0)),
- SYSCALL (new RGB(0, 0, 200)),
- INTERRUPTED (new RGB(200, 0, 100));
-
- public final RGB rgb;
-
- private State(RGB rgb) {
- this.rgb = rgb;
- }
-
- }
-
- /**
- * Average width of the characters used for state labels. Is computed in the
- * first call to postDrawEvent(). Is null before that.
- */
- private Integer fAverageCharacterWidth = null;
-
- /**
- * Default constructor
- */
- public ControlFlowPresentationProvider() {
- super(Messages.ControlFlowView_stateTypeName);
- }
-
- private static State[] getStateValues() {
- return State.values();
- }
-
- @Override
- public StateItem[] getStateTable() {
- State[] states = getStateValues();
- StateItem[] stateTable = new StateItem[states.length];
- for (int i = 0; i < stateTable.length; i++) {
- State state = states[i];
- stateTable[i] = new StateItem(state.rgb, state.toString());
- }
- return stateTable;
- }
-
- @Override
- public int getStateTableIndex(ITimeEvent event) {
- if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) {
- int status = ((TimeEvent) event).getValue();
- return getMatchingState(status).ordinal();
- }
- if (event instanceof NullTimeEvent) {
- return INVISIBLE;
- }
- return TRANSPARENT;
- }
-
- @Override
- public String getEventName(ITimeEvent event) {
- if (event instanceof TimeEvent) {
- TimeEvent ev = (TimeEvent) event;
- if (ev.hasValue()) {
- return getMatchingState(ev.getValue()).toString();
- }
- }
- return Messages.ControlFlowView_multipleStates;
- }
-
- private static State getMatchingState(int status) {
- switch (status) {
- case StateValues.PROCESS_STATUS_WAIT_UNKNOWN:
- return State.WAIT_UNKNOWN;
- case StateValues.PROCESS_STATUS_WAIT_BLOCKED:
- return State.WAIT_BLOCKED;
- case StateValues.PROCESS_STATUS_WAIT_FOR_CPU:
- return State.WAIT_FOR_CPU;
- case StateValues.PROCESS_STATUS_RUN_USERMODE:
- return State.USERMODE;
- case StateValues.PROCESS_STATUS_RUN_SYSCALL:
- return State.SYSCALL;
- case StateValues.PROCESS_STATUS_INTERRUPTED:
- return State.INTERRUPTED;
- default:
- return State.UNKNOWN;
- }
- }
-
- @Override
- public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event) {
- Map<String, String> retMap = new LinkedHashMap<>();
- if (!(event instanceof TimeEvent) || !((TimeEvent) event).hasValue() ||
- !(event.getEntry() instanceof ControlFlowEntry)) {
- return retMap;
- }
- ControlFlowEntry entry = (ControlFlowEntry) event.getEntry();
- ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
- if (ssq == null) {
- return retMap;
- }
- int tid = entry.getThreadId();
-
- try {
- // Find every CPU first, then get the current thread
- int cpusQuark = ssq.getQuarkAbsolute(Attributes.CPUS);
- List<Integer> cpuQuarks = ssq.getSubAttributes(cpusQuark, false);
- for (Integer cpuQuark : cpuQuarks) {
- int currentThreadQuark = ssq.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
- ITmfStateInterval interval = ssq.querySingleState(event.getTime(), currentThreadQuark);
- if (!interval.getStateValue().isNull()) {
- ITmfStateValue state = interval.getStateValue();
- int currentThreadId = state.unboxInt();
- if (tid == currentThreadId) {
- retMap.put(Messages.ControlFlowView_attributeCpuName, ssq.getAttributeName(cpuQuark));
- break;
- }
- }
- }
-
- } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
- Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
- } catch (StateSystemDisposedException e) {
- /* Ignored */
- }
- int status = ((TimeEvent) event).getValue();
- if (status == StateValues.PROCESS_STATUS_RUN_SYSCALL) {
- try {
- int syscallQuark = ssq.getQuarkRelative(entry.getThreadQuark(), Attributes.SYSTEM_CALL);
- ITmfStateInterval value = ssq.querySingleState(event.getTime(), syscallQuark);
- if (!value.getStateValue().isNull()) {
- ITmfStateValue state = value.getStateValue();
- retMap.put(Messages.ControlFlowView_attributeSyscallName, state.toString());
- }
-
- } catch (AttributeNotFoundException | TimeRangeException e) {
- Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
- } catch (StateSystemDisposedException e) {
- /* Ignored */
- }
- }
-
- return retMap;
- }
-
- @Override
- public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) {
- if (fAverageCharacterWidth == null) {
- fAverageCharacterWidth = gc.getFontMetrics().getAverageCharWidth();
- }
- if (bounds.width <= fAverageCharacterWidth) {
- return;
- }
- if (!(event instanceof TimeEvent)) {
- return;
- }
- ControlFlowEntry entry = (ControlFlowEntry) event.getEntry();
- ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
- if (ss == null) {
- return;
- }
- int status = ((TimeEvent) event).getValue();
-
- if (status != StateValues.PROCESS_STATUS_RUN_SYSCALL) {
- return;
- }
- try {
- int syscallQuark = ss.getQuarkRelative(entry.getThreadQuark(), Attributes.SYSTEM_CALL);
- ITmfStateInterval value = ss.querySingleState(event.getTime(), syscallQuark);
- if (!value.getStateValue().isNull()) {
- ITmfStateValue state = value.getStateValue();
- gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
-
- /*
- * Remove the "sys_" or "syscall_entry_" or similar from what we
- * draw in the rectangle. This depends on the trace's event layout.
- */
- int beginIndex = 0;
- ITmfTrace trace = entry.getTrace();
- if (trace instanceof IKernelTrace) {
- IKernelAnalysisEventLayout layout = ((IKernelTrace) trace).getKernelEventLayout();
- beginIndex = layout.eventSyscallEntryPrefix().length();
- }
-
- Utils.drawText(gc, state.toString().substring(beginIndex), bounds.x, bounds.y, bounds.width, bounds.height, true, true);
- }
- } catch (AttributeNotFoundException | TimeRangeException e) {
- Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
- } catch (StateSystemDisposedException e) {
- /* Ignored */
- }
- }
-}
+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2012, 2016 Ericsson, École Polytechnique de Montréal and others.
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Patrick Tasse - Initial API and implementation
- * Geneviève Bastien - Move code to provide base classes for time graph view
- * Christian Mansky - Add check active / uncheck inactive buttons
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.action.IMenuManager;
-import org.eclipse.jface.action.IToolBarManager;
-import org.eclipse.jface.dialogs.IDialogSettings;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
-import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
-import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator;
-import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
-import org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions.FollowThreadAction;
-import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowColumnComparators;
-import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
-import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
-import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
-import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
-import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
-import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
-import org.eclipse.tracecompass.tmf.core.util.Pair;
-import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractStateSystemTimeGraphView;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeLinkEvent;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * The Control Flow view main object
- *
- */
-public class ControlFlowView extends AbstractStateSystemTimeGraphView {
-
- // ------------------------------------------------------------------------
- // Constants
- // ------------------------------------------------------------------------
- /**
- * View ID.
- */
- public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.controlflow"; //$NON-NLS-1$
-
- private static final String PROCESS_COLUMN = Messages.ControlFlowView_processColumn;
- private static final String TID_COLUMN = Messages.ControlFlowView_tidColumn;
- private static final String PTID_COLUMN = Messages.ControlFlowView_ptidColumn;
- private static final String BIRTH_TIME_COLUMN = Messages.ControlFlowView_birthTimeColumn;
- private static final String TRACE_COLUMN = Messages.ControlFlowView_traceColumn;
-
- private static final String[] COLUMN_NAMES = new String[] {
- PROCESS_COLUMN,
- TID_COLUMN,
- PTID_COLUMN,
- BIRTH_TIME_COLUMN,
- TRACE_COLUMN
- };
-
- private static final String[] FILTER_COLUMN_NAMES = new String[] {
- PROCESS_COLUMN,
- TID_COLUMN
- };
-
- // Timeout between updates in the build thread in ms
- private static final long BUILD_UPDATE_TIMEOUT = 500;
-
- private static final Comparator<ITimeGraphEntry>[] COLUMN_COMPARATORS;
-
- private static final int INITIAL_SORT_COLUMN_INDEX = 3;
-
- static {
- ImmutableList.Builder<Comparator<ITimeGraphEntry>> builder = ImmutableList.builder();
- builder.add(ControlFlowColumnComparators.PROCESS_NAME_COLUMN_COMPARATOR)
- .add(ControlFlowColumnComparators.TID_COLUMN_COMPARATOR)
- .add(ControlFlowColumnComparators.PTID_COLUMN_COMPARATOR)
- .add(ControlFlowColumnComparators.BIRTH_TIME_COLUMN_COMPARATOR)
- .add(ControlFlowColumnComparators.TRACE_COLUMN_COMPARATOR);
- List<Comparator<ITimeGraphEntry>> l = builder.build();
- COLUMN_COMPARATORS = l.toArray(new Comparator[l.size()]);
- }
-
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
-
- /**
- * Constructor
- */
- public ControlFlowView() {
- super(ID, new ControlFlowPresentationProvider());
- setTreeColumns(COLUMN_NAMES, COLUMN_COMPARATORS, INITIAL_SORT_COLUMN_INDEX);
- setTreeLabelProvider(new ControlFlowTreeLabelProvider());
- setFilterColumns(FILTER_COLUMN_NAMES);
- setFilterLabelProvider(new ControlFlowFilterLabelProvider());
- setEntryComparator(ControlFlowColumnComparators.BIRTH_TIME_COLUMN_COMPARATOR);
- }
-
- @Override
- public void createPartControl(Composite parent) {
- super.createPartControl(parent);
- // add "Check active" Button to TimeGraphFilterDialog
- super.getTimeGraphCombo().addTimeGraphFilterCheckActiveButton(
- new ControlFlowCheckActiveProvider(Messages.ControlFlowView_checkActiveLabel, Messages.ControlFlowView_checkActiveToolTip));
- // add "Uncheck inactive" Button to TimeGraphFilterDialog
- super.getTimeGraphCombo().addTimeGraphFilterUncheckInactiveButton(
- new ControlFlowCheckActiveProvider(Messages.ControlFlowView_uncheckInactiveLabel, Messages.ControlFlowView_uncheckInactiveToolTip));
- }
-
- /**
- * @since 2.0
- */
- @Override
- protected void fillTimeGraphEntryContextMenu(@NonNull IMenuManager menuManager) {
- ISelection selection = getSite().getSelectionProvider().getSelection();
- if (selection instanceof StructuredSelection) {
- StructuredSelection sSel = (StructuredSelection) selection;
- if (sSel.getFirstElement() instanceof ControlFlowEntry) {
- ControlFlowEntry entry = (ControlFlowEntry) sSel.getFirstElement();
- menuManager.add(new FollowThreadAction(ControlFlowView.this, entry.getName(), entry.getThreadId(), entry.getTrace()));
- }
- }
- }
-
- @Override
- protected void fillLocalToolBar(IToolBarManager manager) {
- super.fillLocalToolBar(manager);
- IDialogSettings settings = Activator.getDefault().getDialogSettings();
- IDialogSettings section = settings.getSection(getClass().getName());
- if (section == null) {
- section = settings.addNewSection(getClass().getName());
- }
-
- IAction hideArrowsAction = getTimeGraphCombo().getTimeGraphViewer().getHideArrowsAction(section);
- manager.add(hideArrowsAction);
-
- IAction followArrowBwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowBwdAction();
- followArrowBwdAction.setText(Messages.ControlFlowView_followCPUBwdText);
- followArrowBwdAction.setToolTipText(Messages.ControlFlowView_followCPUBwdText);
- manager.add(followArrowBwdAction);
-
- IAction followArrowFwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowFwdAction();
- followArrowFwdAction.setText(Messages.ControlFlowView_followCPUFwdText);
- followArrowFwdAction.setToolTipText(Messages.ControlFlowView_followCPUFwdText);
- manager.add(followArrowFwdAction);
- }
-
- @Override
- protected String getNextText() {
- return Messages.ControlFlowView_nextProcessActionNameText;
- }
-
- @Override
- protected String getNextTooltip() {
- return Messages.ControlFlowView_nextProcessActionToolTipText;
- }
-
- @Override
- protected String getPrevText() {
- return Messages.ControlFlowView_previousProcessActionNameText;
- }
-
- @Override
- protected String getPrevTooltip() {
- return Messages.ControlFlowView_previousProcessActionToolTipText;
- }
-
- /**
- * @author gbastien
- *
- */
- protected static class ControlFlowTreeLabelProvider extends TreeLabelProvider {
-
- @Override
- public String getColumnText(Object element, int columnIndex) {
- ControlFlowEntry entry = (ControlFlowEntry) element;
-
- if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_processColumn)) {
- return entry.getName();
- } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_tidColumn)) {
- return Integer.toString(entry.getThreadId());
- } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_ptidColumn)) {
- if (entry.getParentThreadId() > 0) {
- return Integer.toString(entry.getParentThreadId());
- }
- } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_birthTimeColumn)) {
- return Utils.formatTime(entry.getStartTime(), TimeFormat.CALENDAR, Resolution.NANOSEC);
- } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_traceColumn)) {
- return entry.getTrace().getName();
- }
- return ""; //$NON-NLS-1$
- }
-
- }
-
- private static class ControlFlowFilterLabelProvider extends TreeLabelProvider {
-
- @Override
- public String getColumnText(Object element, int columnIndex) {
- ControlFlowEntry entry = (ControlFlowEntry) element;
-
- if (columnIndex == 0) {
- return entry.getName();
- } else if (columnIndex == 1) {
- return Integer.toString(entry.getThreadId());
- }
- return ""; //$NON-NLS-1$
- }
-
- }
-
- // ------------------------------------------------------------------------
- // Internal
- // ------------------------------------------------------------------------
-
- @Override
- protected void buildEntryList(final ITmfTrace trace, final ITmfTrace parentTrace, final IProgressMonitor monitor) {
- final ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
- if (ssq == null) {
- return;
- }
-
- final List<ControlFlowEntry> entryList = new ArrayList<>();
- /** Map of view entries, key is a pair [threadId, cpuId] */
- final Map<Pair<Integer, Integer>, ControlFlowEntry> entryMap = new HashMap<>();
-
- long start = ssq.getStartTime();
- setStartTime(Math.min(getStartTime(), start));
-
- boolean complete = false;
- while (!complete) {
- if (monitor.isCanceled()) {
- return;
- }
- complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
- if (ssq.isCancelled()) {
- return;
- }
- long end = ssq.getCurrentEndTime();
- if (start == end && !complete) { // when complete execute one last time regardless of end time
- continue;
- }
- final long resolution = Math.max(1, (end - ssq.getStartTime()) / getDisplayWidth());
- setEndTime(Math.max(getEndTime(), end + 1));
- final List<Integer> threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$
- queryFullStates(ssq, start, end, resolution, monitor, new IQueryHandler() {
- @Override
- public void handle(List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState) {
- for (int threadQuark : threadQuarks) {
- String threadAttributeName = ssq.getAttributeName(threadQuark);
-
- Pair<Integer, Integer> entryKey = Attributes.parseThreadAttributeName(threadAttributeName);
- int threadId = entryKey.getFirst();
-
- if (threadId < 0) { // ignore the 'unknown' (-1) thread
- continue;
- }
-
- int execNameQuark;
- int ppidQuark;
- try {
- execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME);
- ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID);
- } catch (AttributeNotFoundException e) {
- /* No information on this thread (yet?), skip it for now */
- continue;
- }
- ITmfStateInterval lastExecNameInterval = prevFullState == null || execNameQuark >= prevFullState.size() ? null : prevFullState.get(execNameQuark);
- long lastExecNameStartTime = lastExecNameInterval == null ? -1 : lastExecNameInterval.getStartTime();
- long lastExecNameEndTime = lastExecNameInterval == null ? -1 : lastExecNameInterval.getEndTime() + 1;
- long lastPpidStartTime = prevFullState == null || ppidQuark >= prevFullState.size() ? -1 : prevFullState.get(ppidQuark).getStartTime();
- for (List<ITmfStateInterval> fullState : fullStates) {
- if (monitor.isCanceled()) {
- return;
- }
- if (execNameQuark >= fullState.size() || ppidQuark >= fullState.size()) {
- /* No information on this thread (yet?), skip it for now */
- continue;
- }
- ITmfStateInterval execNameInterval = fullState.get(execNameQuark);
- ITmfStateInterval ppidInterval = fullState.get(ppidQuark);
- long startTime = execNameInterval.getStartTime();
- long endTime = execNameInterval.getEndTime() + 1;
- if (startTime == lastExecNameStartTime && ppidInterval.getStartTime() == lastPpidStartTime) {
- continue;
- }
- boolean isNull = execNameInterval.getStateValue().isNull();
- if (isNull && lastExecNameEndTime < startTime && lastExecNameEndTime != -1) {
- /*
- * There was a non-null interval in between the
- * full states, try to use it.
- */
- try {
- execNameInterval = ssq.querySingleState(startTime - 1, execNameQuark);
- ppidInterval = ssq.querySingleState(startTime - 1, ppidQuark);
- startTime = execNameInterval.getStartTime();
- endTime = execNameInterval.getEndTime() + 1;
- } catch (AttributeNotFoundException e) {
- Activator.getDefault().logError(e.getMessage());
- } catch (StateSystemDisposedException e) {
- /* ignored */
- }
- }
- if (!execNameInterval.getStateValue().isNull() &&
- execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
- String execName = execNameInterval.getStateValue().unboxStr();
- int ppid = ppidInterval.getStateValue().unboxInt();
- ControlFlowEntry entry = entryMap.get(entryKey);
- if (entry == null) {
- entry = new ControlFlowEntry(threadQuark, trace, execName, threadId, ppid, startTime, endTime);
- entryList.add(entry);
- entryMap.put(entryKey, entry);
- } else {
- /*
- * Update the name of the entry to the
- * latest execName and the parent thread id
- * to the latest ppid.
- */
- entry.setName(execName);
- entry.setParentThreadId(ppid);
- entry.updateEndTime(endTime);
- }
- }
- if (isNull) {
- entryMap.remove(entryKey);
- }
- lastExecNameStartTime = startTime;
- lastExecNameEndTime = endTime;
- lastPpidStartTime = ppidInterval.getStartTime();
- }
- }
- updateTree(entryList, parentTrace, ssq);
- }
- });
-
- queryFullStates(ssq, ssq.getStartTime(), end, resolution, monitor, new IQueryHandler() {
- @Override
- public void handle(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState) {
- for (final TimeGraphEntry entry : getEntryList(ssq)) {
- if (monitor.isCanceled()) {
- return;
- }
- buildStatusEvents(trace, parentTrace, ssq, fullStates, prevFullState, (ControlFlowEntry) entry, monitor, ssq.getStartTime(), end);
- }
- }
- });
-
- if (parentTrace.equals(getTrace())) {
- refresh();
- }
-
- start = end;
- }
- }
-
- private void updateTree(List<ControlFlowEntry> entryList, ITmfTrace parentTrace, ITmfStateSystem ss) {
- List<TimeGraphEntry> rootListToAdd = new ArrayList<>();
- List<TimeGraphEntry> rootListToRemove = new ArrayList<>();
- List<TimeGraphEntry> rootList = getEntryList(ss);
-
- for (ControlFlowEntry entry : entryList) {
- boolean root = (entry.getParent() == null);
- if (root && entry.getParentThreadId() > 0) {
- for (ControlFlowEntry parent : entryList) {
- /*
- * Associate the parent entry only if their time overlap. A
- * child entry may start before its parent, for example at
- * the beginning of the trace if a parent has not yet
- * appeared in the state system. We just want to make sure
- * that the entry didn't start after the parent ended or
- * ended before the parent started.
- */
- if (parent.getThreadId() == entry.getParentThreadId() &&
- !(entry.getStartTime() > parent.getEndTime() ||
- entry.getEndTime() < parent.getStartTime())) {
- parent.addChild(entry);
- root = false;
- if (rootList != null && rootList.contains(entry)) {
- rootListToRemove.add(entry);
- }
- break;
- }
- }
- }
- if (root && (rootList == null || !rootList.contains(entry))) {
- rootListToAdd.add(entry);
- }
- }
-
- addToEntryList(parentTrace, ss, rootListToAdd);
- removeFromEntryList(parentTrace, ss, rootListToRemove);
- }
-
- private void buildStatusEvents(ITmfTrace trace, ITmfTrace parentTrace, ITmfStateSystem ss, @NonNull List<List<ITmfStateInterval>> fullStates,
- @Nullable List<ITmfStateInterval> prevFullState, ControlFlowEntry entry, @NonNull IProgressMonitor monitor, long start, long end) {
- if (start < entry.getEndTime() && end > entry.getStartTime()) {
- List<ITimeEvent> eventList = getEventList(entry, ss, fullStates, prevFullState, monitor);
- if (eventList == null) {
- return;
- }
- /* Start a new event list on first iteration, then append to it */
- if (prevFullState == null) {
- entry.setEventList(eventList);
- } else {
- for (ITimeEvent event : eventList) {
- entry.addEvent(event);
- }
- }
- if (parentTrace.equals(getTrace())) {
- redraw();
- }
- }
- for (ITimeGraphEntry child : entry.getChildren()) {
- if (monitor.isCanceled()) {
- return;
- }
- buildStatusEvents(trace, parentTrace, ss, fullStates, prevFullState, (ControlFlowEntry) child, monitor, start, end);
- }
- }
-
- @Override
- protected @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry tgentry, ITmfStateSystem ss,
- @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
- List<ITimeEvent> eventList = null;
- if (!(tgentry instanceof ControlFlowEntry)) {
- return eventList;
- }
- ControlFlowEntry entry = (ControlFlowEntry) tgentry;
- try {
- int threadQuark = entry.getThreadQuark();
- int statusQuark = ss.getQuarkRelative(threadQuark, Attributes.STATUS);
- eventList = new ArrayList<>(fullStates.size());
- ITmfStateInterval lastInterval = prevFullState == null || statusQuark >= prevFullState.size() ? null : prevFullState.get(statusQuark);
- long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime();
- long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1;
- for (List<ITmfStateInterval> fullState : fullStates) {
- if (monitor.isCanceled()) {
- return null;
- }
- if (statusQuark >= fullState.size()) {
- /* No information on this thread (yet?), skip it for now */
- continue;
- }
- ITmfStateInterval statusInterval = fullState.get(statusQuark);
- long time = statusInterval.getStartTime();
- if (time == lastStartTime) {
- continue;
- }
- long duration = statusInterval.getEndTime() - time + 1;
- int status = -1;
- try {
- status = statusInterval.getStateValue().unboxInt();
- } catch (StateValueTypeException e) {
- Activator.getDefault().logError(e.getMessage());
- }
- if (lastEndTime != time && lastEndTime != -1) {
- eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
- }
- if (!statusInterval.getStateValue().isNull()) {
- eventList.add(new TimeEvent(entry, time, duration, status));
- } else {
- eventList.add(new NullTimeEvent(entry, time, duration));
- }
- lastStartTime = time;
- lastEndTime = time + duration;
- }
- } catch (AttributeNotFoundException | TimeRangeException e) {
- Activator.getDefault().logError(e.getMessage());
- }
- return eventList;
- }
-
- /**
- * Returns a value corresponding to the selected entry.
- *
- * Used in conjunction with synchingToTime to change the selected entry. If
- * one of these methods is overridden in child class, then both should be.
- *
- * @param time
- * The currently selected time
- * @return a value identifying the entry
- */
- private int getSelectionValue(long time) {
- int thread = -1;
- for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) {
- if (thread > 0) {
- break;
- }
- ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
- if (ssq == null) {
- continue;
- }
- if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) {
- List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
- for (int currentThreadQuark : currentThreadQuarks) {
- try {
- ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark);
- int currentThread = currentThreadInterval.getStateValue().unboxInt();
- if (currentThread > 0) {
- int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS);
- ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark);
- if (statusInterval.getStartTime() == time) {
- thread = currentThread;
- break;
- }
- }
- } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
- Activator.getDefault().logError(e.getMessage());
- } catch (StateSystemDisposedException e) {
- /* Ignored */
- }
- }
- }
- }
- return thread;
- }
-
- @Override
- protected void synchingToTime(long time) {
- int selected = getSelectionValue(time);
- if (selected > 0) {
- for (Object element : getTimeGraphViewer().getExpandedElements()) {
- if (element instanceof ControlFlowEntry) {
- ControlFlowEntry entry = (ControlFlowEntry) element;
- if (entry.getThreadId() == selected) {
- getTimeGraphCombo().setSelection(entry);
- break;
- }
- }
- }
- }
- }
-
- @Override
- protected @NonNull List<ILinkEvent> getLinkList(ITmfStateSystem ss,
- @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
- List<ILinkEvent> list = new ArrayList<>();
- List<TimeGraphEntry> entryList = getEntryList(ss);
- if (entryList == null) {
- return list;
- }
- for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) {
- List<Integer> currentThreadQuarks = ss.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
- for (int currentThreadQuark : currentThreadQuarks) {
- if (currentThreadQuark >= fullStates.get(0).size()) {
- /* No information on this cpu (yet?), skip it for now */
- continue;
- }
- List<ITmfStateInterval> currentThreadIntervals = new ArrayList<>(fullStates.size() + 2);
- try {
- /*
- * Add the previous interval if it is the first query
- * iteration and the first interval has currentThread=0. Add
- * the following interval if the last interval has
- * currentThread=0. These are diagonal arrows crossing the
- * query iteration range.
- */
- if (prevFullState == null) {
- ITmfStateInterval currentThreadInterval = fullStates.get(0).get(currentThreadQuark);
- if (currentThreadInterval.getStateValue().unboxInt() == 0) {
- long start = Math.max(currentThreadInterval.getStartTime() - 1, ss.getStartTime());
- currentThreadIntervals.add(ss.querySingleState(start, currentThreadQuark));
- }
- }
- for (List<ITmfStateInterval> fullState : fullStates) {
- currentThreadIntervals.add(fullState.get(currentThreadQuark));
- }
- ITmfStateInterval currentThreadInterval = fullStates.get(fullStates.size() - 1).get(currentThreadQuark);
- if (currentThreadInterval.getStateValue().unboxInt() == 0) {
- long end = Math.min(currentThreadInterval.getEndTime() + 1, ss.getCurrentEndTime());
- currentThreadIntervals.add(ss.querySingleState(end, currentThreadQuark));
- }
- } catch (AttributeNotFoundException e) {
- Activator.getDefault().logError(e.getMessage());
- return list;
- } catch (StateSystemDisposedException e) {
- /* Ignored */
- return list;
- }
- int prevThread = 0;
- long prevEnd = 0;
- long lastEnd = 0;
- for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) {
- if (monitor.isCanceled()) {
- return list;
- }
- if (currentThreadInterval.getEndTime() + 1 == lastEnd) {
- continue;
- }
- long time = currentThreadInterval.getStartTime();
- if (time != lastEnd) {
- // don't create links where there are gaps in intervals due to the resolution
- prevThread = 0;
- prevEnd = 0;
- }
- int thread = currentThreadInterval.getStateValue().unboxInt();
- if (thread > 0 && prevThread > 0) {
- ITimeGraphEntry prevEntry = findEntry(entryList, trace, prevThread);
- ITimeGraphEntry nextEntry = findEntry(entryList, trace, thread);
- list.add(new TimeLinkEvent(prevEntry, nextEntry, prevEnd, time - prevEnd, 0));
- }
- lastEnd = currentThreadInterval.getEndTime() + 1;
- if (thread != 0) {
- prevThread = thread;
- prevEnd = lastEnd;
- }
- }
- }
- }
- return list;
- }
-
- private ControlFlowEntry findEntry(List<? extends ITimeGraphEntry> entryList, ITmfTrace trace, int threadId) {
- for (ITimeGraphEntry entry : entryList) {
- if (entry instanceof ControlFlowEntry) {
- ControlFlowEntry controlFlowEntry = (ControlFlowEntry) entry;
- if (controlFlowEntry.getThreadId() == threadId && controlFlowEntry.getTrace() == trace) {
- return controlFlowEntry;
- } else if (entry.hasChildren()) {
- controlFlowEntry = findEntry(entry.getChildren(), trace, threadId);
- if (controlFlowEntry != null) {
- return controlFlowEntry;
- }
- }
- }
- }
- return null;
- }
-}
--- /dev/null
+/*******************************************************************************
+ * 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;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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$
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Patrick Tasse - Initial API and implementation
+ * Geneviève Bastien - Move code to provide base classes for time graph view
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
+import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
+
+/**
+ * Presentation provider for the control flow view
+ */
+public class ControlFlowPresentationProvider extends TimeGraphPresentationProvider {
+
+ private enum State {
+ UNKNOWN (new RGB(100, 100, 100)),
+ WAIT_UNKNOWN (new RGB(200, 200, 200)),
+ WAIT_BLOCKED (new RGB(200, 200, 0)),
+ WAIT_FOR_CPU (new RGB(200, 100, 0)),
+ USERMODE (new RGB(0, 200, 0)),
+ SYSCALL (new RGB(0, 0, 200)),
+ INTERRUPTED (new RGB(200, 0, 100));
+
+ public final RGB rgb;
+
+ private State(RGB rgb) {
+ this.rgb = rgb;
+ }
+
+ }
+
+ /**
+ * Average width of the characters used for state labels. Is computed in the
+ * first call to postDrawEvent(). Is null before that.
+ */
+ private Integer fAverageCharacterWidth = null;
+
+ /**
+ * Default constructor
+ */
+ public ControlFlowPresentationProvider() {
+ super(Messages.ControlFlowView_stateTypeName);
+ }
+
+ private static State[] getStateValues() {
+ return State.values();
+ }
+
+ @Override
+ public StateItem[] getStateTable() {
+ State[] states = getStateValues();
+ StateItem[] stateTable = new StateItem[states.length];
+ for (int i = 0; i < stateTable.length; i++) {
+ State state = states[i];
+ stateTable[i] = new StateItem(state.rgb, state.toString());
+ }
+ return stateTable;
+ }
+
+ @Override
+ public int getStateTableIndex(ITimeEvent event) {
+ if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) {
+ int status = ((TimeEvent) event).getValue();
+ return getMatchingState(status).ordinal();
+ }
+ if (event instanceof NullTimeEvent) {
+ return INVISIBLE;
+ }
+ return TRANSPARENT;
+ }
+
+ @Override
+ public String getEventName(ITimeEvent event) {
+ if (event instanceof TimeEvent) {
+ TimeEvent ev = (TimeEvent) event;
+ if (ev.hasValue()) {
+ return getMatchingState(ev.getValue()).toString();
+ }
+ }
+ return Messages.ControlFlowView_multipleStates;
+ }
+
+ private static State getMatchingState(int status) {
+ switch (status) {
+ case StateValues.PROCESS_STATUS_WAIT_UNKNOWN:
+ return State.WAIT_UNKNOWN;
+ case StateValues.PROCESS_STATUS_WAIT_BLOCKED:
+ return State.WAIT_BLOCKED;
+ case StateValues.PROCESS_STATUS_WAIT_FOR_CPU:
+ return State.WAIT_FOR_CPU;
+ case StateValues.PROCESS_STATUS_RUN_USERMODE:
+ return State.USERMODE;
+ case StateValues.PROCESS_STATUS_RUN_SYSCALL:
+ return State.SYSCALL;
+ case StateValues.PROCESS_STATUS_INTERRUPTED:
+ return State.INTERRUPTED;
+ default:
+ return State.UNKNOWN;
+ }
+ }
+
+ @Override
+ public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event) {
+ Map<String, String> retMap = new LinkedHashMap<>();
+ if (!(event instanceof TimeEvent) || !((TimeEvent) event).hasValue() ||
+ !(event.getEntry() instanceof ControlFlowEntry)) {
+ return retMap;
+ }
+ ControlFlowEntry entry = (ControlFlowEntry) event.getEntry();
+ ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
+ if (ssq == null) {
+ return retMap;
+ }
+ int tid = entry.getThreadId();
+
+ try {
+ // Find every CPU first, then get the current thread
+ int cpusQuark = ssq.getQuarkAbsolute(Attributes.CPUS);
+ List<Integer> cpuQuarks = ssq.getSubAttributes(cpusQuark, false);
+ for (Integer cpuQuark : cpuQuarks) {
+ int currentThreadQuark = ssq.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);
+ ITmfStateInterval interval = ssq.querySingleState(event.getTime(), currentThreadQuark);
+ if (!interval.getStateValue().isNull()) {
+ ITmfStateValue state = interval.getStateValue();
+ int currentThreadId = state.unboxInt();
+ if (tid == currentThreadId) {
+ retMap.put(Messages.ControlFlowView_attributeCpuName, ssq.getAttributeName(cpuQuark));
+ break;
+ }
+ }
+ }
+
+ } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
+ Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
+ } catch (StateSystemDisposedException e) {
+ /* Ignored */
+ }
+ int status = ((TimeEvent) event).getValue();
+ if (status == StateValues.PROCESS_STATUS_RUN_SYSCALL) {
+ try {
+ int syscallQuark = ssq.getQuarkRelative(entry.getThreadQuark(), Attributes.SYSTEM_CALL);
+ ITmfStateInterval value = ssq.querySingleState(event.getTime(), syscallQuark);
+ if (!value.getStateValue().isNull()) {
+ ITmfStateValue state = value.getStateValue();
+ retMap.put(Messages.ControlFlowView_attributeSyscallName, state.toString());
+ }
+
+ } catch (AttributeNotFoundException | TimeRangeException e) {
+ Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
+ } catch (StateSystemDisposedException e) {
+ /* Ignored */
+ }
+ }
+
+ return retMap;
+ }
+
+ @Override
+ public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) {
+ if (fAverageCharacterWidth == null) {
+ fAverageCharacterWidth = gc.getFontMetrics().getAverageCharWidth();
+ }
+ if (bounds.width <= fAverageCharacterWidth) {
+ return;
+ }
+ if (!(event instanceof TimeEvent)) {
+ return;
+ }
+ ControlFlowEntry entry = (ControlFlowEntry) event.getEntry();
+ ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID);
+ if (ss == null) {
+ return;
+ }
+ int status = ((TimeEvent) event).getValue();
+
+ if (status != StateValues.PROCESS_STATUS_RUN_SYSCALL) {
+ return;
+ }
+ try {
+ int syscallQuark = ss.getQuarkRelative(entry.getThreadQuark(), Attributes.SYSTEM_CALL);
+ ITmfStateInterval value = ss.querySingleState(event.getTime(), syscallQuark);
+ if (!value.getStateValue().isNull()) {
+ ITmfStateValue state = value.getStateValue();
+ gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
+
+ /*
+ * Remove the "sys_" or "syscall_entry_" or similar from what we
+ * draw in the rectangle. This depends on the trace's event layout.
+ */
+ int beginIndex = 0;
+ ITmfTrace trace = entry.getTrace();
+ if (trace instanceof IKernelTrace) {
+ IKernelAnalysisEventLayout layout = ((IKernelTrace) trace).getKernelEventLayout();
+ beginIndex = layout.eventSyscallEntryPrefix().length();
+ }
+
+ Utils.drawText(gc, state.toString().substring(beginIndex), bounds.x, bounds.y, bounds.width, bounds.height, true, true);
+ }
+ } catch (AttributeNotFoundException | TimeRangeException e) {
+ Activator.getDefault().logError("Error in ControlFlowPresentationProvider", e); //$NON-NLS-1$
+ } catch (StateSystemDisposedException e) {
+ /* Ignored */
+ }
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2012, 2016 Ericsson, École Polytechnique de Montréal and others.
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Patrick Tasse - Initial API and implementation
+ * Geneviève Bastien - Move code to provide base classes for time graph view
+ * Christian Mansky - Add check active / uncheck inactive buttons
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions.FollowThreadAction;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
+import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.util.Pair;
+import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractStateSystemTimeGraphView;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeLinkEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * The Control Flow view main object
+ *
+ */
+public class ControlFlowView extends AbstractStateSystemTimeGraphView {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+ /**
+ * View ID.
+ */
+ public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.controlflow"; //$NON-NLS-1$
+
+ private static final String PROCESS_COLUMN = Messages.ControlFlowView_processColumn;
+ private static final String TID_COLUMN = Messages.ControlFlowView_tidColumn;
+ private static final String PTID_COLUMN = Messages.ControlFlowView_ptidColumn;
+ private static final String BIRTH_TIME_COLUMN = Messages.ControlFlowView_birthTimeColumn;
+ private static final String TRACE_COLUMN = Messages.ControlFlowView_traceColumn;
+
+ private static final String[] COLUMN_NAMES = new String[] {
+ PROCESS_COLUMN,
+ TID_COLUMN,
+ PTID_COLUMN,
+ BIRTH_TIME_COLUMN,
+ TRACE_COLUMN
+ };
+
+ private static final String[] FILTER_COLUMN_NAMES = new String[] {
+ PROCESS_COLUMN,
+ TID_COLUMN
+ };
+
+ // Timeout between updates in the build thread in ms
+ private static final long BUILD_UPDATE_TIMEOUT = 500;
+
+ private static final Comparator<ITimeGraphEntry>[] COLUMN_COMPARATORS;
+
+ private static final int INITIAL_SORT_COLUMN_INDEX = 3;
+
+ static {
+ ImmutableList.Builder<Comparator<ITimeGraphEntry>> builder = ImmutableList.builder();
+ builder.add(ControlFlowColumnComparators.PROCESS_NAME_COLUMN_COMPARATOR)
+ .add(ControlFlowColumnComparators.TID_COLUMN_COMPARATOR)
+ .add(ControlFlowColumnComparators.PTID_COLUMN_COMPARATOR)
+ .add(ControlFlowColumnComparators.BIRTH_TIME_COLUMN_COMPARATOR)
+ .add(ControlFlowColumnComparators.TRACE_COLUMN_COMPARATOR);
+ List<Comparator<ITimeGraphEntry>> l = builder.build();
+ COLUMN_COMPARATORS = l.toArray(new Comparator[l.size()]);
+ }
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor
+ */
+ public ControlFlowView() {
+ super(ID, new ControlFlowPresentationProvider());
+ setTreeColumns(COLUMN_NAMES, COLUMN_COMPARATORS, INITIAL_SORT_COLUMN_INDEX);
+ setTreeLabelProvider(new ControlFlowTreeLabelProvider());
+ setFilterColumns(FILTER_COLUMN_NAMES);
+ setFilterLabelProvider(new ControlFlowFilterLabelProvider());
+ setEntryComparator(ControlFlowColumnComparators.BIRTH_TIME_COLUMN_COMPARATOR);
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ super.createPartControl(parent);
+ // add "Check active" Button to TimeGraphFilterDialog
+ super.getTimeGraphCombo().addTimeGraphFilterCheckActiveButton(
+ new ControlFlowCheckActiveProvider(Messages.ControlFlowView_checkActiveLabel, Messages.ControlFlowView_checkActiveToolTip));
+ // add "Uncheck inactive" Button to TimeGraphFilterDialog
+ super.getTimeGraphCombo().addTimeGraphFilterUncheckInactiveButton(
+ new ControlFlowCheckActiveProvider(Messages.ControlFlowView_uncheckInactiveLabel, Messages.ControlFlowView_uncheckInactiveToolTip));
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ protected void fillTimeGraphEntryContextMenu(@NonNull IMenuManager menuManager) {
+ ISelection selection = getSite().getSelectionProvider().getSelection();
+ if (selection instanceof StructuredSelection) {
+ StructuredSelection sSel = (StructuredSelection) selection;
+ if (sSel.getFirstElement() instanceof ControlFlowEntry) {
+ ControlFlowEntry entry = (ControlFlowEntry) sSel.getFirstElement();
+ menuManager.add(new FollowThreadAction(ControlFlowView.this, entry.getName(), entry.getThreadId(), entry.getTrace()));
+ }
+ }
+ }
+
+ @Override
+ protected void fillLocalToolBar(IToolBarManager manager) {
+ super.fillLocalToolBar(manager);
+ IDialogSettings settings = Activator.getDefault().getDialogSettings();
+ IDialogSettings section = settings.getSection(getClass().getName());
+ if (section == null) {
+ section = settings.addNewSection(getClass().getName());
+ }
+
+ IAction hideArrowsAction = getTimeGraphCombo().getTimeGraphViewer().getHideArrowsAction(section);
+ manager.add(hideArrowsAction);
+
+ IAction followArrowBwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowBwdAction();
+ followArrowBwdAction.setText(Messages.ControlFlowView_followCPUBwdText);
+ followArrowBwdAction.setToolTipText(Messages.ControlFlowView_followCPUBwdText);
+ manager.add(followArrowBwdAction);
+
+ IAction followArrowFwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowFwdAction();
+ followArrowFwdAction.setText(Messages.ControlFlowView_followCPUFwdText);
+ followArrowFwdAction.setToolTipText(Messages.ControlFlowView_followCPUFwdText);
+ manager.add(followArrowFwdAction);
+ }
+
+ @Override
+ protected String getNextText() {
+ return Messages.ControlFlowView_nextProcessActionNameText;
+ }
+
+ @Override
+ protected String getNextTooltip() {
+ return Messages.ControlFlowView_nextProcessActionToolTipText;
+ }
+
+ @Override
+ protected String getPrevText() {
+ return Messages.ControlFlowView_previousProcessActionNameText;
+ }
+
+ @Override
+ protected String getPrevTooltip() {
+ return Messages.ControlFlowView_previousProcessActionToolTipText;
+ }
+
+ /**
+ * @author gbastien
+ *
+ */
+ protected static class ControlFlowTreeLabelProvider extends TreeLabelProvider {
+
+ @Override
+ public String getColumnText(Object element, int columnIndex) {
+ ControlFlowEntry entry = (ControlFlowEntry) element;
+
+ if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_processColumn)) {
+ return entry.getName();
+ } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_tidColumn)) {
+ return Integer.toString(entry.getThreadId());
+ } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_ptidColumn)) {
+ if (entry.getParentThreadId() > 0) {
+ return Integer.toString(entry.getParentThreadId());
+ }
+ } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_birthTimeColumn)) {
+ return Utils.formatTime(entry.getStartTime(), TimeFormat.CALENDAR, Resolution.NANOSEC);
+ } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_traceColumn)) {
+ return entry.getTrace().getName();
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ }
+
+ private static class ControlFlowFilterLabelProvider extends TreeLabelProvider {
+
+ @Override
+ public String getColumnText(Object element, int columnIndex) {
+ ControlFlowEntry entry = (ControlFlowEntry) element;
+
+ if (columnIndex == 0) {
+ return entry.getName();
+ } else if (columnIndex == 1) {
+ return Integer.toString(entry.getThreadId());
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ }
+
+ // ------------------------------------------------------------------------
+ // Internal
+ // ------------------------------------------------------------------------
+
+ @Override
+ protected void buildEntryList(final ITmfTrace trace, final ITmfTrace parentTrace, final IProgressMonitor monitor) {
+ final ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
+ if (ssq == null) {
+ return;
+ }
+
+ final List<ControlFlowEntry> entryList = new ArrayList<>();
+ /** Map of view entries, key is a pair [threadId, cpuId] */
+ final Map<Pair<Integer, Integer>, ControlFlowEntry> entryMap = new HashMap<>();
+
+ long start = ssq.getStartTime();
+ setStartTime(Math.min(getStartTime(), start));
+
+ boolean complete = false;
+ while (!complete) {
+ if (monitor.isCanceled()) {
+ return;
+ }
+ complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
+ if (ssq.isCancelled()) {
+ return;
+ }
+ long end = ssq.getCurrentEndTime();
+ if (start == end && !complete) { // when complete execute one last time regardless of end time
+ continue;
+ }
+ final long resolution = Math.max(1, (end - ssq.getStartTime()) / getDisplayWidth());
+ setEndTime(Math.max(getEndTime(), end + 1));
+ final List<Integer> threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$
+ queryFullStates(ssq, start, end, resolution, monitor, new IQueryHandler() {
+ @Override
+ public void handle(List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState) {
+ for (int threadQuark : threadQuarks) {
+ String threadAttributeName = ssq.getAttributeName(threadQuark);
+
+ Pair<Integer, Integer> entryKey = Attributes.parseThreadAttributeName(threadAttributeName);
+ int threadId = entryKey.getFirst();
+
+ if (threadId < 0) { // ignore the 'unknown' (-1) thread
+ continue;
+ }
+
+ int execNameQuark;
+ int ppidQuark;
+ try {
+ execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME);
+ ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID);
+ } catch (AttributeNotFoundException e) {
+ /* No information on this thread (yet?), skip it for now */
+ continue;
+ }
+ ITmfStateInterval lastExecNameInterval = prevFullState == null || execNameQuark >= prevFullState.size() ? null : prevFullState.get(execNameQuark);
+ long lastExecNameStartTime = lastExecNameInterval == null ? -1 : lastExecNameInterval.getStartTime();
+ long lastExecNameEndTime = lastExecNameInterval == null ? -1 : lastExecNameInterval.getEndTime() + 1;
+ long lastPpidStartTime = prevFullState == null || ppidQuark >= prevFullState.size() ? -1 : prevFullState.get(ppidQuark).getStartTime();
+ for (List<ITmfStateInterval> fullState : fullStates) {
+ if (monitor.isCanceled()) {
+ return;
+ }
+ if (execNameQuark >= fullState.size() || ppidQuark >= fullState.size()) {
+ /* No information on this thread (yet?), skip it for now */
+ continue;
+ }
+ ITmfStateInterval execNameInterval = fullState.get(execNameQuark);
+ ITmfStateInterval ppidInterval = fullState.get(ppidQuark);
+ long startTime = execNameInterval.getStartTime();
+ long endTime = execNameInterval.getEndTime() + 1;
+ if (startTime == lastExecNameStartTime && ppidInterval.getStartTime() == lastPpidStartTime) {
+ continue;
+ }
+ boolean isNull = execNameInterval.getStateValue().isNull();
+ if (isNull && lastExecNameEndTime < startTime && lastExecNameEndTime != -1) {
+ /*
+ * There was a non-null interval in between the
+ * full states, try to use it.
+ */
+ try {
+ execNameInterval = ssq.querySingleState(startTime - 1, execNameQuark);
+ ppidInterval = ssq.querySingleState(startTime - 1, ppidQuark);
+ startTime = execNameInterval.getStartTime();
+ endTime = execNameInterval.getEndTime() + 1;
+ } catch (AttributeNotFoundException e) {
+ Activator.getDefault().logError(e.getMessage());
+ } catch (StateSystemDisposedException e) {
+ /* ignored */
+ }
+ }
+ if (!execNameInterval.getStateValue().isNull() &&
+ execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
+ String execName = execNameInterval.getStateValue().unboxStr();
+ int ppid = ppidInterval.getStateValue().unboxInt();
+ ControlFlowEntry entry = entryMap.get(entryKey);
+ if (entry == null) {
+ entry = new ControlFlowEntry(threadQuark, trace, execName, threadId, ppid, startTime, endTime);
+ entryList.add(entry);
+ entryMap.put(entryKey, entry);
+ } else {
+ /*
+ * Update the name of the entry to the
+ * latest execName and the parent thread id
+ * to the latest ppid.
+ */
+ entry.setName(execName);
+ entry.setParentThreadId(ppid);
+ entry.updateEndTime(endTime);
+ }
+ }
+ if (isNull) {
+ entryMap.remove(entryKey);
+ }
+ lastExecNameStartTime = startTime;
+ lastExecNameEndTime = endTime;
+ lastPpidStartTime = ppidInterval.getStartTime();
+ }
+ }
+ updateTree(entryList, parentTrace, ssq);
+ }
+ });
+
+ queryFullStates(ssq, ssq.getStartTime(), end, resolution, monitor, new IQueryHandler() {
+ @Override
+ public void handle(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState) {
+ for (final TimeGraphEntry entry : getEntryList(ssq)) {
+ if (monitor.isCanceled()) {
+ return;
+ }
+ buildStatusEvents(trace, parentTrace, ssq, fullStates, prevFullState, (ControlFlowEntry) entry, monitor, ssq.getStartTime(), end);
+ }
+ }
+ });
+
+ if (parentTrace.equals(getTrace())) {
+ refresh();
+ }
+
+ start = end;
+ }
+ }
+
+ private void updateTree(List<ControlFlowEntry> entryList, ITmfTrace parentTrace, ITmfStateSystem ss) {
+ List<TimeGraphEntry> rootListToAdd = new ArrayList<>();
+ List<TimeGraphEntry> rootListToRemove = new ArrayList<>();
+ List<TimeGraphEntry> rootList = getEntryList(ss);
+
+ for (ControlFlowEntry entry : entryList) {
+ boolean root = (entry.getParent() == null);
+ if (root && entry.getParentThreadId() > 0) {
+ for (ControlFlowEntry parent : entryList) {
+ /*
+ * Associate the parent entry only if their time overlap. A
+ * child entry may start before its parent, for example at
+ * the beginning of the trace if a parent has not yet
+ * appeared in the state system. We just want to make sure
+ * that the entry didn't start after the parent ended or
+ * ended before the parent started.
+ */
+ if (parent.getThreadId() == entry.getParentThreadId() &&
+ !(entry.getStartTime() > parent.getEndTime() ||
+ entry.getEndTime() < parent.getStartTime())) {
+ parent.addChild(entry);
+ root = false;
+ if (rootList != null && rootList.contains(entry)) {
+ rootListToRemove.add(entry);
+ }
+ break;
+ }
+ }
+ }
+ if (root && (rootList == null || !rootList.contains(entry))) {
+ rootListToAdd.add(entry);
+ }
+ }
+
+ addToEntryList(parentTrace, ss, rootListToAdd);
+ removeFromEntryList(parentTrace, ss, rootListToRemove);
+ }
+
+ private void buildStatusEvents(ITmfTrace trace, ITmfTrace parentTrace, ITmfStateSystem ss, @NonNull List<List<ITmfStateInterval>> fullStates,
+ @Nullable List<ITmfStateInterval> prevFullState, ControlFlowEntry entry, @NonNull IProgressMonitor monitor, long start, long end) {
+ if (start < entry.getEndTime() && end > entry.getStartTime()) {
+ List<ITimeEvent> eventList = getEventList(entry, ss, fullStates, prevFullState, monitor);
+ if (eventList == null) {
+ return;
+ }
+ /* Start a new event list on first iteration, then append to it */
+ if (prevFullState == null) {
+ entry.setEventList(eventList);
+ } else {
+ for (ITimeEvent event : eventList) {
+ entry.addEvent(event);
+ }
+ }
+ if (parentTrace.equals(getTrace())) {
+ redraw();
+ }
+ }
+ for (ITimeGraphEntry child : entry.getChildren()) {
+ if (monitor.isCanceled()) {
+ return;
+ }
+ buildStatusEvents(trace, parentTrace, ss, fullStates, prevFullState, (ControlFlowEntry) child, monitor, start, end);
+ }
+ }
+
+ @Override
+ protected @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry tgentry, ITmfStateSystem ss,
+ @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
+ List<ITimeEvent> eventList = null;
+ if (!(tgentry instanceof ControlFlowEntry)) {
+ return eventList;
+ }
+ ControlFlowEntry entry = (ControlFlowEntry) tgentry;
+ try {
+ int threadQuark = entry.getThreadQuark();
+ int statusQuark = ss.getQuarkRelative(threadQuark, Attributes.STATUS);
+ eventList = new ArrayList<>(fullStates.size());
+ ITmfStateInterval lastInterval = prevFullState == null || statusQuark >= prevFullState.size() ? null : prevFullState.get(statusQuark);
+ long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime();
+ long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1;
+ for (List<ITmfStateInterval> fullState : fullStates) {
+ if (monitor.isCanceled()) {
+ return null;
+ }
+ if (statusQuark >= fullState.size()) {
+ /* No information on this thread (yet?), skip it for now */
+ continue;
+ }
+ ITmfStateInterval statusInterval = fullState.get(statusQuark);
+ long time = statusInterval.getStartTime();
+ if (time == lastStartTime) {
+ continue;
+ }
+ long duration = statusInterval.getEndTime() - time + 1;
+ int status = -1;
+ try {
+ status = statusInterval.getStateValue().unboxInt();
+ } catch (StateValueTypeException e) {
+ Activator.getDefault().logError(e.getMessage());
+ }
+ if (lastEndTime != time && lastEndTime != -1) {
+ eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
+ }
+ if (!statusInterval.getStateValue().isNull()) {
+ eventList.add(new TimeEvent(entry, time, duration, status));
+ } else {
+ eventList.add(new NullTimeEvent(entry, time, duration));
+ }
+ lastStartTime = time;
+ lastEndTime = time + duration;
+ }
+ } catch (AttributeNotFoundException | TimeRangeException e) {
+ Activator.getDefault().logError(e.getMessage());
+ }
+ return eventList;
+ }
+
+ /**
+ * Returns a value corresponding to the selected entry.
+ *
+ * Used in conjunction with synchingToTime to change the selected entry. If
+ * one of these methods is overridden in child class, then both should be.
+ *
+ * @param time
+ * The currently selected time
+ * @return a value identifying the entry
+ */
+ private int getSelectionValue(long time) {
+ int thread = -1;
+ for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) {
+ if (thread > 0) {
+ break;
+ }
+ ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID);
+ if (ssq == null) {
+ continue;
+ }
+ if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) {
+ List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
+ for (int currentThreadQuark : currentThreadQuarks) {
+ try {
+ ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark);
+ int currentThread = currentThreadInterval.getStateValue().unboxInt();
+ if (currentThread > 0) {
+ int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS);
+ ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark);
+ if (statusInterval.getStartTime() == time) {
+ thread = currentThread;
+ break;
+ }
+ }
+ } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
+ Activator.getDefault().logError(e.getMessage());
+ } catch (StateSystemDisposedException e) {
+ /* Ignored */
+ }
+ }
+ }
+ }
+ return thread;
+ }
+
+ @Override
+ protected void synchingToTime(long time) {
+ int selected = getSelectionValue(time);
+ if (selected > 0) {
+ for (Object element : getTimeGraphViewer().getExpandedElements()) {
+ if (element instanceof ControlFlowEntry) {
+ ControlFlowEntry entry = (ControlFlowEntry) element;
+ if (entry.getThreadId() == selected) {
+ getTimeGraphCombo().setSelection(entry);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected @NonNull List<ILinkEvent> getLinkList(ITmfStateSystem ss,
+ @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
+ List<ILinkEvent> list = new ArrayList<>();
+ List<TimeGraphEntry> entryList = getEntryList(ss);
+ if (entryList == null) {
+ return list;
+ }
+ for (ITmfTrace trace : TmfTraceManager.getTraceSet(getTrace())) {
+ List<Integer> currentThreadQuarks = ss.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
+ for (int currentThreadQuark : currentThreadQuarks) {
+ if (currentThreadQuark >= fullStates.get(0).size()) {
+ /* No information on this cpu (yet?), skip it for now */
+ continue;
+ }
+ List<ITmfStateInterval> currentThreadIntervals = new ArrayList<>(fullStates.size() + 2);
+ try {
+ /*
+ * Add the previous interval if it is the first query
+ * iteration and the first interval has currentThread=0. Add
+ * the following interval if the last interval has
+ * currentThread=0. These are diagonal arrows crossing the
+ * query iteration range.
+ */
+ if (prevFullState == null) {
+ ITmfStateInterval currentThreadInterval = fullStates.get(0).get(currentThreadQuark);
+ if (currentThreadInterval.getStateValue().unboxInt() == 0) {
+ long start = Math.max(currentThreadInterval.getStartTime() - 1, ss.getStartTime());
+ currentThreadIntervals.add(ss.querySingleState(start, currentThreadQuark));
+ }
+ }
+ for (List<ITmfStateInterval> fullState : fullStates) {
+ currentThreadIntervals.add(fullState.get(currentThreadQuark));
+ }
+ ITmfStateInterval currentThreadInterval = fullStates.get(fullStates.size() - 1).get(currentThreadQuark);
+ if (currentThreadInterval.getStateValue().unboxInt() == 0) {
+ long end = Math.min(currentThreadInterval.getEndTime() + 1, ss.getCurrentEndTime());
+ currentThreadIntervals.add(ss.querySingleState(end, currentThreadQuark));
+ }
+ } catch (AttributeNotFoundException e) {
+ Activator.getDefault().logError(e.getMessage());
+ return list;
+ } catch (StateSystemDisposedException e) {
+ /* Ignored */
+ return list;
+ }
+ int prevThread = 0;
+ long prevEnd = 0;
+ long lastEnd = 0;
+ for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) {
+ if (monitor.isCanceled()) {
+ return list;
+ }
+ if (currentThreadInterval.getEndTime() + 1 == lastEnd) {
+ continue;
+ }
+ long time = currentThreadInterval.getStartTime();
+ if (time != lastEnd) {
+ // don't create links where there are gaps in intervals due to the resolution
+ prevThread = 0;
+ prevEnd = 0;
+ }
+ int thread = currentThreadInterval.getStateValue().unboxInt();
+ if (thread > 0 && prevThread > 0) {
+ ITimeGraphEntry prevEntry = findEntry(entryList, trace, prevThread);
+ ITimeGraphEntry nextEntry = findEntry(entryList, trace, thread);
+ list.add(new TimeLinkEvent(prevEntry, nextEntry, prevEnd, time - prevEnd, 0));
+ }
+ lastEnd = currentThreadInterval.getEndTime() + 1;
+ if (thread != 0) {
+ prevThread = thread;
+ prevEnd = lastEnd;
+ }
+ }
+ }
+ }
+ return list;
+ }
+
+ private ControlFlowEntry findEntry(List<? extends ITimeGraphEntry> entryList, ITmfTrace trace, int threadId) {
+ for (ITimeGraphEntry entry : entryList) {
+ if (entry instanceof ControlFlowEntry) {
+ ControlFlowEntry controlFlowEntry = (ControlFlowEntry) entry;
+ if (controlFlowEntry.getThreadId() == threadId && controlFlowEntry.getTrace() == trace) {
+ return controlFlowEntry;
+ } else if (entry.hasChildren()) {
+ controlFlowEntry = findEntry(entry.getChildren(), trace, threadId);
+ if (controlFlowEntry != null) {
+ return controlFlowEntry;
+ }
+ }
+ }
+ }
+ return null;
+ }
+}
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;
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;
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;
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;