analysis: Add the critical path view
authorFrancis Giraldeau <francis.giraldeau@gmail.com>
Mon, 3 Aug 2015 14:03:49 +0000 (10:03 -0400)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Thu, 22 Oct 2015 18:55:32 +0000 (14:55 -0400)
Added in a new org.eclipse.tracecompass.analysis.graph.ui plugin

Change-Id: Id1f9691273c35e3e91b3ef57c000a37ee8bc4ad1
Signed-off-by: Francis Giraldeau <francis.giraldeau@gmail.com>
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/41481
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
analysis/org.eclipse.tracecompass.analysis.graph.core/META-INF/MANIFEST.MF
analysis/org.eclipse.tracecompass.analysis.graph.ui/META-INF/MANIFEST.MF
analysis/org.eclipse.tracecompass.analysis.graph.ui/plugin.xml
analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathBaseEntry.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathEntry.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathPresentationProvider.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathView.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/Messages.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/messages.properties [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/package-info.java [new file with mode: 0644]

index ffb137c2974f4644a7b1e94b430c72f6731f8f99..65f22a7a10872a2edb8165f67dfd0e789ed0442a 100644 (file)
@@ -18,6 +18,6 @@ Export-Package: org.eclipse.tracecompass.analysis.graph.core.base,
  org.eclipse.tracecompass.analysis.graph.core.criticalpath,
  org.eclipse.tracecompass.internal.analysis.graph.core;x-internal=true;uses:="org.eclipse.tracecompass.common.core",
  org.eclipse.tracecompass.internal.analysis.graph.core.base;x-friends:="org.eclipse.tracecompass.analysis.graph.ui,org.eclipse.tracecompass.analysis.graph.core.tests",
- org.eclipse.tracecompass.internal.analysis.graph.core.criticalpath;x-friends:="org.eclipse.tracecompass.analysis.graph.core.tests"
+ org.eclipse.tracecompass.internal.analysis.graph.core.criticalpath;x-friends:="org.eclipse.tracecompass.analysis.graph.ui,org.eclipse.tracecompass.analysis.graph.core.tests"
 Import-Package: com.google.common.collect,
  com.google.common.hash
index 2e11eae069dce9b637b238d313ec5098325826bc..f97935c967329498e11549c8a1e6501c9e6b9b91 100644 (file)
@@ -15,5 +15,7 @@ Require-Bundle: org.eclipse.ui,
  org.eclipse.tracecompass.common.core,
  org.eclipse.tracecompass.statesystem.core,
  org.eclipse.tracecompass.tmf.core,
- org.eclipse.tracecompass.tmf.ui
-Export-Package: org.eclipse.tracecompass.internal.analysis.graph.ui;x-internal:=true
+ org.eclipse.tracecompass.tmf.ui,
+ org.eclipse.core.resources;bundle-version="3.10.1"
+Export-Package: org.eclipse.tracecompass.internal.analysis.graph.ui;x-internal:=true,
+ org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view;x-friends:="org.eclipse.tracecompass.lttng2.kernel.ui"
index f422d55d6a3db6c2e32d71d3d05c09ecefd8ef34..8857f1140c466e4ffcccba1261bd2756a794b2c0 100644 (file)
@@ -1,4 +1,25 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?eclipse version="3.4"?>
 <plugin>
+   <extension
+            point="org.eclipse.ui.views">
+      <view
+            allowMultiple="false"
+            category="org.eclipse.linuxtools.lttng2.ui.views.category"
+            class="org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view.CriticalPathView"
+            id="org.eclipse.linuxtools.tmf.analysis.graph.ui.criticalpath.view.criticalpathview"
+            name="%view.criticalpath"
+            restorable="true">
+      </view>
+   </extension>
+   <extension
+         point="org.eclipse.linuxtools.tmf.core.analysis">
+      <output
+            class="org.eclipse.tracecompass.tmf.ui.analysis.TmfAnalysisViewOutput"
+            id="org.eclipse.linuxtools.tmf.analysis.graph.ui.criticalpath.view.criticalpathview">
+         <analysisModuleClass
+               class="org.eclipse.tracecompass.analysis.graph.core.criticalpath.CriticalPathModule">
+         </analysisModuleClass>
+      </output>
+   </extension>
 </plugin>
diff --git a/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathBaseEntry.java b/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathBaseEntry.java
new file mode 100644 (file)
index 0000000..8087289
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2015 É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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view;
+
+import org.eclipse.tracecompass.analysis.graph.core.base.IGraphWorker;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
+
+/**
+ * A time graph for the critical path to be used by the view itself to identify
+ * the base worker from which to get the critical path.
+ *
+ * @author Geneviève Bastien
+ */
+public class CriticalPathBaseEntry extends TimeGraphEntry {
+
+    private final IGraphWorker fWorker;
+
+    /**
+     * Constructor
+     *
+     * @param worker
+     *            The worker associated with this entry
+     */
+    public CriticalPathBaseEntry(IGraphWorker worker) {
+        super("Base entry", Long.MIN_VALUE, Long.MAX_VALUE); //$NON-NLS-1$
+        fWorker = worker;
+    }
+
+    /**
+     * Get the worker associated with this entry
+     *
+     * @return The worker
+     */
+    public IGraphWorker getWorker() {
+        return fWorker;
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathEntry.java b/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathEntry.java
new file mode 100644 (file)
index 0000000..7358a21
--- /dev/null
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2015 É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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view;
+
+import org.eclipse.tracecompass.analysis.graph.core.base.IGraphWorker;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
+
+/**
+ * An entry in the Control Flow view
+ *
+ * @author Geneviève Bastien
+ */
+public class CriticalPathEntry extends TimeGraphEntry {
+
+    private final IGraphWorker fWorker;
+
+    /**
+     * Constructor
+     *
+     * @param taskname
+     *            Name of the task
+     * @param trace
+     *            The trace on which we are working
+     * @param startTime
+     *            The start time of this process's lifetime
+     * @param endTime
+     *            The end time of this process
+     * @param worker
+     *            The worker object of this entry
+     */
+    public CriticalPathEntry(String taskname, ITmfTrace trace, long startTime, long endTime, IGraphWorker worker) {
+        super(taskname, startTime, endTime);
+        fWorker = worker;
+    }
+
+    /**
+     * Get the worker object associated with the entry
+     *
+     * @return The worker object
+     */
+    public IGraphWorker getWorker() {
+        return fWorker;
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathPresentationProvider.java b/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathPresentationProvider.java
new file mode 100644 (file)
index 0000000..01d8dcb
--- /dev/null
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2015 É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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+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.TimeEvent;
+
+/**
+ * Presentation provider for the critical path view
+ *
+ * @author Geneviève Bastien
+ */
+public class CriticalPathPresentationProvider extends TimeGraphPresentationProvider {
+
+    /**
+     * The enumeration of possible states for the view
+     */
+    public static enum State {
+        /** Worker is running */
+        RUNNING         (new RGB(0x33, 0x99, 0x00)),
+        /** Worker is interrupted */
+        INTERRUPTED     (new RGB(0xff, 0xdc, 0x00)),
+        /** Worker has been preempted */
+        PREEMPTED       (new RGB(0xc8, 0x64, 0x00)),
+        /** Worker waiting on a timer */
+        TIMER           (new RGB(0x33, 0x66, 0x99)),
+        /** Worker is blocked, waiting on a device */
+        BLOCK_DEVICE    (new RGB(0x66, 0x00, 0xcc)),
+        /** Worker is waiting for user input */
+        USER_INPUT      (new RGB(0x5a, 0x01, 0x01)),
+        /** Worker is waiting on network */
+        NETWORK         (new RGB(0xff, 0x9b, 0xff)),
+        /** Any other reason */
+        UNKNOWN         (new RGB(0x40, 0x3b, 0x33));
+
+        /** RGB color associated with a state */
+        public final RGB rgb;
+
+        private State (RGB rgb) {
+            this.rgb = rgb;
+        }
+    }
+
+    @Override
+    public String getStateTypeName() {
+        return Messages.getMessage(Messages.CriticalFlowView_stateTypeName);
+    }
+
+    @Override
+    public StateItem[] getStateTable() {
+        StateItem[] stateTable = new StateItem[State.values().length];
+        for (int i = 0; i < stateTable.length; i++) {
+            State state = State.values()[i];
+            stateTable[i] = new StateItem(state.rgb, state.toString());
+        }
+        return stateTable;
+    }
+
+    @Override
+    public int getStateTableIndex(@Nullable ITimeEvent event) {
+        if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) {
+            return ((TimeEvent) event).getValue();
+        }
+        return TRANSPARENT;
+    }
+
+    private static State getMatchingState(int status) {
+        switch (status) {
+        case 0:
+            return State.RUNNING;
+        case 1:
+            return State.INTERRUPTED;
+        case 2:
+            return State.PREEMPTED;
+        case 3:
+            return State.TIMER;
+        case 4:
+            return State.BLOCK_DEVICE;
+        case 5:
+            return State.USER_INPUT;
+        case 6:
+            return State.NETWORK;
+        default:
+            return State.UNKNOWN;
+        }
+    }
+
+    @Override
+    public String getEventName(@Nullable ITimeEvent event) {
+        if (event instanceof TimeEvent) {
+            TimeEvent ev = (TimeEvent) event;
+            if (ev.hasValue()) {
+                return NonNullUtils.nullToEmptyString(getMatchingState(ev.getValue()));
+            }
+        }
+        return Messages.getMessage(Messages.CriticalFlowView_multipleStates);
+    }
+}
+
diff --git a/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathView.java b/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathView.java
new file mode 100644 (file)
index 0000000..f00b205
--- /dev/null
@@ -0,0 +1,564 @@
+/*******************************************************************************
+ * Copyright (c) 2015 É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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.tracecompass.analysis.graph.core.base.IGraphWorker;
+import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge;
+import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge.EdgeType;
+import org.eclipse.tracecompass.analysis.graph.core.base.TmfGraph;
+import org.eclipse.tracecompass.analysis.graph.core.base.TmfVertex;
+import org.eclipse.tracecompass.analysis.graph.core.criticalpath.CriticalPathModule;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.graph.core.base.TmfGraphStatistics;
+import org.eclipse.tracecompass.internal.analysis.graph.core.base.TmfGraphVisitor;
+import org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view.CriticalPathPresentationProvider.State;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfStartAnalysisSignal;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractTimeGraphView;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvider;
+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.TimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeLinkEvent;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Table;
+
+/**
+ * The Critical Path view
+ *
+ * @author Geneviève Bastien
+ * @author Francis Giraldeau
+ */
+public class CriticalPathView extends AbstractTimeGraphView {
+
+    // ------------------------------------------------------------------------
+    // Constants
+    // ------------------------------------------------------------------------
+
+    /** View ID */
+    public static final String ID = "org.eclipse.linuxtools.tmf.analysis.graph.ui.criticalpath.view.criticalpathview"; //$NON-NLS-1$
+
+    private static final double NANOINV = 0.000000001;
+
+    private static final String COLUMN_PROCESS = Messages.getMessage(Messages.CriticalFlowView_columnProcess);
+    private static final String COLUMN_ELAPSED = Messages.getMessage(Messages.CriticalFlowView_columnElapsed);
+    private static final String COLUMN_PERCENT = Messages.getMessage(Messages.CriticalFlowView_columnPercent);
+
+    private static final String[] COLUMN_NAMES = new String[] {
+            COLUMN_PROCESS,
+            COLUMN_ELAPSED,
+            COLUMN_PERCENT
+    };
+
+    private static final String[] FILTER_COLUMN_NAMES = new String[] {
+            COLUMN_PROCESS
+    };
+
+    private final Table<ITmfTrace, Object, List<ILinkEvent>> fLinks = NonNullUtils.checkNotNull(HashBasedTable.<ITmfTrace, Object, List<ILinkEvent>> create());
+    /** The trace to entry list hash map */
+    private final Table<ITmfTrace, Object, TmfGraphStatistics> fObjectStatistics = NonNullUtils.checkNotNull(HashBasedTable.<ITmfTrace, Object, TmfGraphStatistics> create());
+
+    private final CriticalPathContentProvider fContentProvider = new CriticalPathContentProvider();
+
+    private TmfGraphStatistics fStats = new TmfGraphStatistics();
+
+    private static final IGraphWorker DEFAULT_WORKER = new IGraphWorker() {
+        @Override
+        public String getHostId() {
+            return "default"; //$NON-NLS-1$
+        }
+    };
+
+    private class CriticalPathContentProvider implements ITimeGraphContentProvider {
+
+        private final class HorizontalLinksVisitor extends TmfGraphVisitor {
+            private final CriticalPathEntry fDefaultParent;
+            private final Map<String, CriticalPathEntry> fHostEntries;
+            private final TmfGraph fGraph;
+            private final ITmfTrace fTrace;
+            private final HashMap<Object, CriticalPathEntry> fRootList;
+
+            private HorizontalLinksVisitor(CriticalPathEntry defaultParent, Map<String, CriticalPathEntry> hostEntries, TmfGraph graph, ITmfTrace trace, HashMap<Object, CriticalPathEntry> rootList) {
+                fDefaultParent = defaultParent;
+                fHostEntries = hostEntries;
+                fGraph = graph;
+                fTrace = trace;
+                fRootList = rootList;
+            }
+
+            @Override
+            public void visitHead(TmfVertex node) {
+                /* TODO possible null pointer ? */
+                IGraphWorker owner = fGraph.getParentOf(node);
+                if (owner == null) {
+                    return;
+                }
+                if (fRootList.containsKey(owner)) {
+                    return;
+                }
+                TmfVertex first = fGraph.getHead(owner);
+                TmfVertex last = fGraph.getTail(owner);
+                if (first == null || last == null) {
+                    return;
+                }
+                setStartTime(Math.min(getStartTime(), first.getTs()));
+                setEndTime(Math.max(getEndTime(), last.getTs()));
+                // create host entry
+                CriticalPathEntry parent = fDefaultParent;
+                String host = owner.getHostId();
+                if (!fHostEntries.containsKey(host)) {
+                    fHostEntries.put(host, new CriticalPathEntry(host, fTrace, getStartTime(), getEndTime(), owner));
+                }
+                parent = fHostEntries.get(host);
+                CriticalPathEntry entry = new CriticalPathEntry(NonNullUtils.nullToEmptyString(owner), fTrace, getStartTime(), getEndTime(), owner);
+                parent.addChild(entry);
+
+                fRootList.put(owner, entry);
+            }
+
+            @Override
+            public void visit(TmfVertex node) {
+                setStartTime(Math.min(getStartTime(), node.getTs()));
+                setEndTime(Math.max(getEndTime(), node.getTs()));
+            }
+
+            @Override
+            public void visit(TmfEdge link, boolean horizontal) {
+                if (horizontal) {
+                    Object parent = fGraph.getParentOf(link.getVertexFrom());
+                    CriticalPathEntry entry = fRootList.get(parent);
+                    TimeEvent ev = new TimeEvent(entry, link.getVertexFrom().getTs(), link.getDuration(),
+                            getMatchingState(link.getType()).ordinal());
+                    entry.addEvent(ev);
+                }
+            }
+        }
+
+        private final class VerticalLinksVisitor extends TmfGraphVisitor {
+            private final TmfGraph fGraph;
+            private final List<ILinkEvent> fGraphLinks;
+            private final Map<Object, CriticalPathEntry> fEntryMap;
+
+            private VerticalLinksVisitor(TmfGraph graph, List<ILinkEvent> graphLinks, Map<Object, CriticalPathEntry> entryMap) {
+                fGraph = graph;
+                fGraphLinks = graphLinks;
+                fEntryMap = entryMap;
+            }
+
+            @Override
+            public void visitHead(TmfVertex node) {
+
+            }
+
+            @Override
+            public void visit(TmfVertex node) {
+
+            }
+
+            @Override
+            public void visit(TmfEdge link, boolean horizontal) {
+                if (!horizontal) {
+                    Object parentFrom = fGraph.getParentOf(link.getVertexFrom());
+                    Object parentTo = fGraph.getParentOf(link.getVertexTo());
+                    CriticalPathEntry entryFrom = fEntryMap.get(parentFrom);
+                    CriticalPathEntry entryTo = fEntryMap.get(parentTo);
+                    TimeLinkEvent lk = new TimeLinkEvent(entryFrom, entryTo, link.getVertexFrom().getTs(),
+                            link.getVertexTo().getTs() - link.getVertexFrom().getTs(), getMatchingState(link.getType()).ordinal());
+                    fGraphLinks.add(lk);
+                }
+            }
+        }
+
+        private Map<Object, Map<Object, CriticalPathEntry>> workerMaps = new HashMap<>();
+        private Map<Object, List<TimeGraphEntry>> workerEntries = new HashMap<>();
+        private Map<Object, List<ILinkEvent>> linkMap = new HashMap<>();
+        private @Nullable Object fCurrentObject;
+
+        @Override
+        public @Nullable ITimeGraphEntry[] getElements(@Nullable Object inputElement) {
+            ITimeGraphEntry[] ret = new ITimeGraphEntry[0];
+            if (inputElement instanceof List) {
+                List<?> list = (List<?>) inputElement;
+                if (!list.isEmpty()) {
+                    Object first = list.get(0);
+                    if (first instanceof CriticalPathBaseEntry) {
+                        IGraphWorker worker = ((CriticalPathBaseEntry) first).getWorker();
+                        ret = getWorkerEntries(worker);
+                    }
+                }
+            }
+            return ret;
+        }
+
+        private ITimeGraphEntry[] getWorkerEntries(IGraphWorker worker) {
+            fCurrentObject = worker;
+            List<TimeGraphEntry> entries = workerEntries.get(worker);
+            if (entries == null) {
+                buildEntryList(worker);
+                entries = workerEntries.get(worker);
+            }
+            return (entries == null) ?
+                new ITimeGraphEntry[0] :
+                NonNullUtils.checkNotNull(entries.toArray(new ITimeGraphEntry[entries.size()]));
+        }
+
+        private void buildEntryList(IGraphWorker worker) {
+            final ITmfTrace trace = getTrace();
+            if (trace == null) {
+                return;
+            }
+            final TmfGraph graph = getGraph(trace);
+            if (graph == null) {
+                return;
+            }
+            setStartTime(Long.MAX_VALUE);
+            setEndTime(Long.MIN_VALUE);
+
+            final HashMap<Object, CriticalPathEntry> rootList = new HashMap<>();
+            fLinks.remove(trace, worker);
+
+            TmfVertex vertex = graph.getHead();
+
+            /* Calculate statistics */
+            fStats = new TmfGraphStatistics();
+            fStats.computeGraphStatistics(graph, worker);
+            fObjectStatistics.put(trace, worker, fStats);
+
+            // Hosts entries are parent of each worker entries
+            final Map<String, CriticalPathEntry> hostEntries = new HashMap<>();
+
+            /* create all interval entries and horizontal links */
+
+            final CriticalPathEntry defaultParent = new CriticalPathEntry("default", trace, getStartTime(), getEndTime(), DEFAULT_WORKER); //$NON-NLS-1$
+            graph.scanLineTraverse(vertex, new HorizontalLinksVisitor(defaultParent, hostEntries, graph, trace, rootList));
+
+            workerMaps.put(worker, rootList);
+
+            List<TimeGraphEntry> list = new ArrayList<>();
+            list.addAll(hostEntries.values());
+            if (defaultParent.hasChildren()) {
+                list.add(defaultParent);
+            }
+
+            for (TimeGraphEntry entry : list) {
+                buildStatusEvents(trace, (CriticalPathEntry) NonNullUtils.checkNotNull(entry));
+            }
+            workerEntries.put(worker, list);
+        }
+
+        private @Nullable TmfGraph getGraph(final ITmfTrace trace) {
+            CriticalPathModule module = Iterables.getFirst(TmfTraceUtils.getAnalysisModulesOfClass(trace, CriticalPathModule.class), null);
+            if (module == null) {
+                return null;
+            }
+            module.schedule();
+            if (!module.waitForCompletion()) {
+                return null;
+            }
+            final TmfGraph graph = module.getCriticalPath();
+            return graph;
+        }
+
+        public @Nullable List<ILinkEvent> getLinkList(long startTime, long endTime) {
+            Object current = fCurrentObject;
+            if (current == null) {
+                return null;
+            }
+            /*
+             * Critical path typically has relatively few links, so we calculate
+             * and save them all, but just return those in range
+             */
+            List<ILinkEvent> links = linkMap.get(current);
+            if (links != null) {
+                return links;
+            }
+            final ITmfTrace trace = getTrace();
+            if (trace == null) {
+                return null;
+            }
+            CriticalPathModule module = Iterables.getFirst(TmfTraceUtils.getAnalysisModulesOfClass(trace, CriticalPathModule.class), null);
+            if (module == null) {
+                return null;
+            }
+            final TmfGraph graph = module.getCriticalPath();
+            if (graph == null) {
+                return null;
+            }
+            final Map<Object, CriticalPathEntry> entryMap = workerMaps.get(current);
+            if (entryMap == null) {
+                return null;
+            }
+
+            TmfVertex vertex = graph.getHead();
+
+            final List<ILinkEvent> graphLinks = new ArrayList<>();
+
+            /* find vertical links */
+            graph.scanLineTraverse(vertex, new VerticalLinksVisitor(graph, graphLinks, entryMap));
+            fLinks.put(trace, fCurrentObject, graphLinks);
+            links = graphLinks;
+
+            List<ILinkEvent> linksInRange = new ArrayList<>();
+            for (ILinkEvent link : links) {
+                if (((link.getTime() >= startTime) && (link.getTime() <= endTime)) ||
+                        ((link.getTime() + link.getDuration() >= startTime) && (link.getTime() + link.getDuration() <= endTime))) {
+                    linksInRange.add(link);
+                }
+            }
+            return linksInRange;
+        }
+
+        @Override
+        public void dispose() {
+
+        }
+
+        @Override
+        public void inputChanged(@Nullable Viewer viewer, @Nullable Object oldInput, @Nullable Object newInput) {
+        }
+
+        @Override
+        public @Nullable ITimeGraphEntry[] getChildren(@Nullable Object parentElement) {
+            if (parentElement instanceof CriticalPathEntry) {
+                List<? extends ITimeGraphEntry> children = ((CriticalPathEntry) parentElement).getChildren();
+                return children.toArray(new TimeGraphEntry[children.size()]);
+            }
+            return null;
+        }
+
+        @Override
+        public @Nullable ITimeGraphEntry getParent(@Nullable Object element) {
+            if (element instanceof CriticalPathEntry) {
+                return ((CriticalPathEntry) element).getParent();
+            }
+            return null;
+        }
+
+        @Override
+        public boolean hasChildren(@Nullable Object element) {
+            if (element instanceof CriticalPathEntry) {
+                return ((CriticalPathEntry) element).hasChildren();
+            }
+            return false;
+        }
+
+    }
+
+    private class CriticalPathTreeLabelProvider extends TreeLabelProvider {
+
+        @Override
+        public String getColumnText(@Nullable Object element, int columnIndex) {
+            if (element == null) {
+                return ""; //$NON-NLS-1$
+            }
+            CriticalPathEntry entry = (CriticalPathEntry) element;
+            if (columnIndex == 0) {
+                return NonNullUtils.nullToEmptyString(entry.getName());
+            } else if (columnIndex == 1) {
+                Long sum = fStats.getSum(entry.getWorker());
+                String value = String.format("%.9f", sum * NANOINV); //$NON-NLS-1$
+                return NonNullUtils.nullToEmptyString(value);
+            } else if (columnIndex == 2) {
+                Double percent = fStats.getPercent(entry.getWorker());
+                String value = String.format("%.2f", percent * 100); //$NON-NLS-1$
+                return NonNullUtils.nullToEmptyString(value);
+            }
+            return ""; //$NON-NLS-1$
+        }
+
+    }
+
+    private class CriticalPathEntryComparator implements Comparator<ITimeGraphEntry> {
+
+        @Override
+        public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) {
+
+            int result = 0;
+
+            if ((o1 instanceof CriticalPathEntry) && (o2 instanceof CriticalPathEntry)) {
+                CriticalPathEntry entry1 = (CriticalPathEntry) o1;
+                CriticalPathEntry entry2 = (CriticalPathEntry) o2;
+                result = -1 * fStats.getSum(entry1.getWorker()).compareTo(fStats.getSum(entry2.getWorker()));
+            }
+            return result;
+        }
+    }
+
+    /**
+     * Constructor
+     */
+    public CriticalPathView() {
+        super(ID, new CriticalPathPresentationProvider());
+        setTreeColumns(COLUMN_NAMES);
+        setFilterColumns(FILTER_COLUMN_NAMES);
+        setTreeLabelProvider(new CriticalPathTreeLabelProvider());
+        setTimeGraphContentProvider(fContentProvider);
+        setEntryComparator(new CriticalPathEntryComparator());
+    }
+
+    // ------------------------------------------------------------------------
+    // Internal
+    // ------------------------------------------------------------------------
+
+    private static State getMatchingState(EdgeType type) {
+        State state = State.UNKNOWN;
+        switch (type) {
+        case RUNNING:
+            state = State.RUNNING;
+            break;
+        case PREEMPTED:
+            state = State.PREEMPTED;
+            break;
+        case TIMER:
+            state = State.TIMER;
+            break;
+        case BLOCK_DEVICE:
+            state = State.BLOCK_DEVICE;
+            break;
+        case INTERRUPTED:
+            state = State.INTERRUPTED;
+            break;
+        case NETWORK:
+            state = State.NETWORK;
+            break;
+        case USER_INPUT:
+            state = State.USER_INPUT;
+            break;
+        case EPS:
+        case UNKNOWN:
+        case DEFAULT:
+        case BLOCKED:
+            break;
+        default:
+            break;
+        }
+        return state;
+    }
+
+    private void buildStatusEvents(ITmfTrace trace, CriticalPathEntry entry) {
+
+        long start = trace.getStartTime().getValue();
+        long end = trace.getEndTime().getValue() + 1;
+        long resolution = Math.max(1, (end - start) / getDisplayWidth());
+        List<ITimeEvent> eventList = getEventList(entry, entry.getStartTime(), entry.getEndTime(), resolution, new NullProgressMonitor());
+
+        entry.setZoomedEventList(eventList);
+
+        redraw();
+
+        for (ITimeGraphEntry child : entry.getChildren()) {
+            if (child == null) {
+                throw new NullPointerException();
+            }
+            buildStatusEvents(trace, (CriticalPathEntry) child);
+        }
+    }
+
+    @Override
+    protected void buildEventList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor) {
+        /* This class uses a content provider instead */
+    }
+
+    @Override
+    protected @Nullable List<ITimeEvent> getEventList(TimeGraphEntry entry,
+            long startTime, long endTime, long resolution,
+            IProgressMonitor monitor) {
+
+        final long realStart = Math.max(startTime, entry.getStartTime());
+        final long realEnd = Math.min(endTime, entry.getEndTime());
+        if (realEnd <= realStart) {
+            return null;
+        }
+        List<ITimeEvent> eventList = null;
+        entry.setZoomedEventList(null);
+        Iterator<ITimeEvent> iterator = entry.getTimeEventsIterator();
+        eventList = new ArrayList<>();
+
+        while (iterator.hasNext()) {
+            ITimeEvent event = iterator.next();
+            /* is event visible */
+            if (intersects(realStart, realEnd, NonNullUtils.checkNotNull(event))) {
+                eventList.add(event);
+            }
+        }
+        return eventList;
+    }
+
+    private static boolean intersects(final long realStart, final long realEnd, ITimeEvent event) {
+        return ((event.getTime() >= realStart) && (event.getTime() <= realEnd)) ||
+                ((event.getTime() + event.getDuration() > realStart) &&
+                        (event.getTime() + event.getDuration() < realEnd));
+    }
+
+    @Override
+    protected @Nullable List<ILinkEvent> getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
+        return fContentProvider.getLinkList(startTime, endTime);
+    }
+
+    /**
+     * Signal handler for analysis started
+     *
+     * @param signal
+     *            The signal
+     */
+    @TmfSignalHandler
+    public void analysisStarted(TmfStartAnalysisSignal signal) {
+        if (!(signal.getAnalysisModule() instanceof CriticalPathModule)) {
+            return;
+        }
+        CriticalPathModule module = (CriticalPathModule) signal.getAnalysisModule();
+        Object obj = module.getParameter(CriticalPathModule.PARAM_WORKER);
+        if (obj == null) {
+            return;
+        }
+        if (!(obj instanceof IGraphWorker)) {
+            throw new IllegalStateException("Wrong type for critical path module parameter " + //$NON-NLS-1$
+                    CriticalPathModule.PARAM_WORKER +
+                    " expected IGraphWorker got " + //$NON-NLS-1$
+                    obj.getClass().getSimpleName());
+        }
+        ITmfTrace trace = getTrace();
+        if (trace == null) {
+            throw new IllegalStateException("Trace is null"); //$NON-NLS-1$
+        }
+        IGraphWorker worker = (IGraphWorker) obj;
+        TmfGraphStatistics stats = fObjectStatistics.get(trace, worker);
+        if (stats == null) {
+            stats = new TmfGraphStatistics();
+            fObjectStatistics.put(trace, worker, stats);
+        }
+        fStats = stats;
+
+        TimeGraphEntry tge = new CriticalPathBaseEntry(worker);
+        List<TimeGraphEntry> list = Collections.singletonList(tge);
+        putEntryList(trace, list);
+        refresh();
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/Messages.java b/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/Messages.java
new file mode 100644 (file)
index 0000000..ff80959
--- /dev/null
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2015 É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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+
+/**
+ * Externalized strings for the critical path view
+ *
+ * @author Geneviève Bastien
+ */
+@SuppressWarnings("javadoc")
+public class Messages {
+    private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view.messages"; //$NON-NLS-1$
+
+    public static @Nullable String CriticalFlowView_multipleStates;
+
+    public static @Nullable String CriticalFlowView_stateTypeName;
+
+    public static @Nullable String CriticalFlowView_columnProcess;
+
+    public static @Nullable String CriticalFlowView_columnElapsed;
+
+    public static @Nullable String CriticalFlowView_columnPercent;
+
+    public static @Nullable String CriticalPathModule_waitingForGraph;
+
+    public static @Nullable String CriticalPathView_selectAlgorithm;
+
+    static {
+        // initialize resource bundle
+        NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+    }
+
+    private Messages() {
+    }
+
+    /**
+     * Helper method to expose externalized strings as non-null objects.
+     */
+    static String getMessage(@Nullable String msg) {
+        return NonNullUtils.nullToEmptyString(msg);
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/messages.properties b/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/messages.properties
new file mode 100644 (file)
index 0000000..f48b151
--- /dev/null
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2015 É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
+###############################################################################
+
+CriticalFlowView_columnProcess=Process
+CriticalFlowView_columnElapsed=Elapsed
+CriticalFlowView_columnPercent=Percent
+CriticalFlowView_stateTypeName=stateTypeName
+CriticalFlowView_multipleStates=multiple state
+CriticalPathModule_waitingForGraph=Waiting for {0} module to complete...
+CriticalPathView_selectAlgorithm=Select the critical path algorithm to use
\ No newline at end of file
diff --git a/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/package-info.java b/analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/package-info.java
new file mode 100644 (file)
index 0000000..7895965
--- /dev/null
@@ -0,0 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2015 É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
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view;
\ No newline at end of file
This page took 0.035689 seconds and 5 git commands to generate.