critical path: bug 495020 fix statistics when reopening a trace
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.graph.ui / src / org / eclipse / tracecompass / internal / analysis / graph / ui / criticalpath / view / CriticalPathView.java
index 64afc95099fae183f599e7ee0b54b34ecf61c279..dd649a5f10eb80eed18899d69e4b3987a2a2834e 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015 École Polytechnique de Montréal
+ * Copyright (c) 2015, 2016 É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
@@ -15,9 +15,10 @@ 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 java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
@@ -29,6 +30,7 @@ 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.building.TmfGraphBuilderModule;
 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;
@@ -82,9 +84,9 @@ public class CriticalPathView extends AbstractTimeGraphView {
             COLUMN_PROCESS
     };
 
-    private final Table<ITmfTrace, Object, List<ILinkEvent>> fLinks = NonNullUtils.checkNotNull(HashBasedTable.<ITmfTrace, Object, List<ILinkEvent>> create());
+    private final Table<ITmfTrace, Object, List<ILinkEvent>> fLinks = HashBasedTable.create();
     /** The trace to entry list hash map */
-    private final Table<ITmfTrace, Object, TmfGraphStatistics> fObjectStatistics = NonNullUtils.checkNotNull(HashBasedTable.<ITmfTrace, Object, TmfGraphStatistics> create());
+    private final Table<ITmfTrace, Object, TmfGraphStatistics> fObjectStatistics = HashBasedTable.create();
 
     private final CriticalPathContentProvider fContentProvider = new CriticalPathContentProvider();
 
@@ -144,17 +146,11 @@ public class CriticalPathView extends AbstractTimeGraphView {
                 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 = checkNotNull(fRootList.get(parent));
+                    CriticalPathEntry entry = fRootList.get(parent);
                     TimeEvent ev = new TimeEvent(entry, link.getVertexFrom().getTs(), link.getDuration(),
                             getMatchingState(link.getType()).ordinal());
                     entry.addEvent(ev);
@@ -197,13 +193,54 @@ public class CriticalPathView extends AbstractTimeGraphView {
             }
         }
 
-        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 class BuildThread extends Thread {
+            private final ITmfTrace fBuildTrace;
+            private final IProgressMonitor fMonitor;
+
+            public BuildThread(final ITmfTrace trace) {
+                super("Critical path view build"); //$NON-NLS-1$
+                fBuildTrace = trace;
+                fMonitor = new NullProgressMonitor();
+            }
+
+            @Override
+            public void run() {
+                try {
+                    CriticalPathModule module = Iterables.<@Nullable CriticalPathModule> getFirst(
+                            TmfTraceUtils.getAnalysisModulesOfClass(fBuildTrace, CriticalPathModule.class),
+                            null);
+                    if (module == null) {
+                        return;
+                    }
+                    module.schedule();
+                    if (module.waitForCompletion(fMonitor)) {
+                        // Module is completed, set the start and end time of
+                        // this view
+                        setStartEndTime(module);
+                        refresh();
+                    }
+
+                } finally {
+                    fSyncLock.lock();
+                    fBuildThread = null;
+                    fSyncLock.unlock();
+                }
+            }
+
+            public void cancel() {
+                fMonitor.setCanceled(true);
+            }
+        }
+
+        private final Lock fSyncLock = new ReentrantLock();
+        private final Map<Object, Map<Object, CriticalPathEntry>> workerMaps = new HashMap<>();
+        private final Map<Object, List<TimeGraphEntry>> workerEntries = new HashMap<>();
+        private final Map<Object, List<ILinkEvent>> linkMap = new HashMap<>();
         private @Nullable Object fCurrentObject;
+        private @Nullable BuildThread fBuildThread = null;
 
         @Override
-        public @Nullable ITimeGraphEntry[] getElements(@Nullable Object inputElement) {
+        public ITimeGraphEntry[] getElements(@Nullable Object inputElement) {
             ITimeGraphEntry[] ret = new ITimeGraphEntry[0];
             if (inputElement instanceof List) {
                 List<?> list = (List<?>) inputElement;
@@ -221,13 +258,26 @@ public class CriticalPathView extends AbstractTimeGraphView {
         private ITimeGraphEntry[] getWorkerEntries(IGraphWorker worker) {
             fCurrentObject = worker;
             List<TimeGraphEntry> entries = workerEntries.get(worker);
+            ITmfTrace trace = getTrace();
             if (entries == null) {
                 buildEntryList(worker);
                 entries = workerEntries.get(worker);
+            } else if (trace != null) {
+                // Get the statistics object for this worker
+                TmfGraphStatistics stats = fObjectStatistics.get(trace, worker);
+                if (stats == null) {
+                    stats = new TmfGraphStatistics();
+                    final TmfGraph graph = getGraph(trace);
+                    if (graph != null) {
+                        stats.computeGraphStatistics(graph, worker);
+                    }
+                }
+                fStats = stats;
             }
+
             return (entries == null) ?
                 new ITimeGraphEntry[0] :
-                NonNullUtils.checkNotNull(entries.toArray(new ITimeGraphEntry[entries.size()]));
+                entries.toArray(new @NonNull ITimeGraphEntry[entries.size()]);
         }
 
         private void buildEntryList(IGraphWorker worker) {
@@ -239,8 +289,6 @@ public class CriticalPathView extends AbstractTimeGraphView {
             if (graph == null) {
                 return;
             }
-            setStartTime(Long.MAX_VALUE);
-            setEndTime(Long.MIN_VALUE);
 
             final HashMap<Object, CriticalPathEntry> rootList = new HashMap<>();
             fLinks.remove(trace, worker);
@@ -268,21 +316,17 @@ public class CriticalPathView extends AbstractTimeGraphView {
                 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);
+            CriticalPathModule module = Iterables.<@Nullable CriticalPathModule> getFirst(
+                    TmfTraceUtils.getAnalysisModulesOfClass(trace, CriticalPathModule.class),
+                    null);
             if (module == null) {
-                return null;
-            }
-            module.schedule();
-            if (!module.waitForCompletion()) {
-                return null;
+                throw new IllegalStateException("View requires an analysis module"); //$NON-NLS-1$
             }
+
             final TmfGraph graph = module.getCriticalPath();
             return graph;
         }
@@ -304,10 +348,12 @@ public class CriticalPathView extends AbstractTimeGraphView {
             if (trace == null) {
                 return null;
             }
-            CriticalPathModule module = Iterables.getFirst(TmfTraceUtils.getAnalysisModulesOfClass(trace, CriticalPathModule.class), null);
+            CriticalPathModule module = Iterables.<@Nullable CriticalPathModule> getFirst(
+                    TmfTraceUtils.getAnalysisModulesOfClass(trace, CriticalPathModule.class), null);
             if (module == null) {
-                return null;
+                throw new IllegalStateException("View requires an analysis module"); //$NON-NLS-1$
             }
+
             final TmfGraph graph = module.getCriticalPath();
             if (graph == null) {
                 return null;
@@ -323,7 +369,7 @@ public class CriticalPathView extends AbstractTimeGraphView {
 
             /* find vertical links */
             graph.scanLineTraverse(vertex, new VerticalLinksVisitor(graph, graphLinks, entryMap));
-            fLinks.put(trace, fCurrentObject, graphLinks);
+            fLinks.put(trace, checkNotNull(fCurrentObject), graphLinks);
             links = graphLinks;
 
             List<ILinkEvent> linksInRange = new ArrayList<>();
@@ -338,15 +384,50 @@ public class CriticalPathView extends AbstractTimeGraphView {
 
         @Override
         public void dispose() {
-
+            fSyncLock.lock();
+            try {
+                BuildThread buildThread = fBuildThread;
+                if (buildThread != null) {
+                    buildThread.cancel();
+                }
+            } finally {
+                fSyncLock.unlock();
+            }
         }
 
         @Override
         public void inputChanged(@Nullable Viewer viewer, @Nullable Object oldInput, @Nullable Object newInput) {
+            // The input has changed, the critical path will be re-computed,
+            // wait for the analysis to be finished, then call the refresh
+            // method of the view
+            if (!(newInput instanceof List)) {
+                return;
+            }
+            List<?> list = (List<?>) newInput;
+            if (list.isEmpty()) {
+                return;
+            }
+            final ITmfTrace trace = getTrace();
+            if (trace == null) {
+                return;
+            }
+
+            fSyncLock.lock();
+            try {
+                BuildThread buildThread = fBuildThread;
+                if (buildThread != null) {
+                    buildThread.cancel();
+                }
+                buildThread = new BuildThread(trace);
+                buildThread.start();
+                fBuildThread = buildThread;
+            } finally {
+                fSyncLock.unlock();
+            }
         }
 
         @Override
-        public @Nullable ITimeGraphEntry[] getChildren(@Nullable Object parentElement) {
+        public ITimeGraphEntry @Nullable [] getChildren(@Nullable Object parentElement) {
             if (parentElement instanceof CriticalPathEntry) {
                 List<? extends ITimeGraphEntry> children = ((CriticalPathEntry) parentElement).getChildren();
                 return children.toArray(new TimeGraphEntry[children.size()]);
@@ -452,6 +533,9 @@ public class CriticalPathView extends AbstractTimeGraphView {
         case USER_INPUT:
             state = State.USER_INPUT;
             break;
+        case IPI:
+            state = State.IPI;
+            break;
         case EPS:
         case UNKNOWN:
         case DEFAULT:
@@ -463,27 +547,8 @@ public class CriticalPathView extends AbstractTimeGraphView {
         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) {
+    protected void buildEntryList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor) {
         /* This class uses a content provider instead */
     }
 
@@ -491,31 +556,11 @@ public class CriticalPathView extends AbstractTimeGraphView {
     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));
+        /*
+         * The event list is built in the HorizontalLinksVisitor. This is called
+         * only from the zoom thread and only for the CriticalPathBaseEntry.
+         */
+        return null;
     }
 
     @Override
@@ -550,12 +595,6 @@ public class CriticalPathView extends AbstractTimeGraphView {
             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);
@@ -563,4 +602,36 @@ public class CriticalPathView extends AbstractTimeGraphView {
         refresh();
     }
 
+    private void setStartEndTime(CriticalPathModule module) {
+        // Initialize the start/end time of the view to trace's times
+        ITmfTrace trace = getTrace();
+        if (trace == null) {
+            throw new IllegalStateException("The trace should not be null when we have a critical path to display"); //$NON-NLS-1$
+        }
+        long start = trace.getStartTime().toNanos();
+        long end = trace.getEndTime().toNanos();
+
+        // Set the start/end time of the view
+        Object paramGraph = module.getParameter(CriticalPathModule.PARAM_GRAPH);
+        if (paramGraph instanceof TmfGraphBuilderModule) {
+            TmfGraphBuilderModule graphModule = (TmfGraphBuilderModule) paramGraph;
+            TmfGraph graph = graphModule.getGraph();
+            if (graph == null) {
+                return;
+            }
+            TmfVertex head = graph.getHead();
+            if (head != null) {
+                start = Math.min(start, head.getTs());
+                for (IGraphWorker w : graph.getWorkers()) {
+                    TmfVertex tail = graph.getTail(w);
+                    if (tail != null) {
+                        end = Math.max(end, tail.getTs());
+                    }
+                }
+            }
+        }
+        setStartTime(start);
+        setEndTime(end);
+    }
+
 }
This page took 0.030515 seconds and 5 git commands to generate.