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 115035ddeeb34b767a3877717c42ab450ce59663..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;
@@ -144,12 +146,6 @@ 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) {
@@ -197,10 +193,51 @@ 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 ITimeGraphEntry[] getElements(@Nullable Object inputElement) {
@@ -221,9 +258,21 @@ 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) ?
@@ -240,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);
@@ -269,9 +316,6 @@ public class CriticalPathView extends AbstractTimeGraphView {
                 list.add(defaultParent);
             }
 
-            for (TimeGraphEntry entry : list) {
-                buildStatusEvents(trace, (CriticalPathEntry) entry);
-            }
             workerEntries.put(worker, list);
         }
 
@@ -283,10 +327,6 @@ public class CriticalPathView extends AbstractTimeGraphView {
                 throw new IllegalStateException("View requires an analysis module"); //$NON-NLS-1$
             }
 
-            module.schedule();
-            if (!module.waitForCompletion()) {
-                return null;
-            }
             final TmfGraph graph = module.getCriticalPath();
             return graph;
         }
@@ -344,11 +384,46 @@ 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
@@ -472,24 +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()) {
-            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 */
     }
 
@@ -497,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, 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
@@ -556,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);
@@ -569,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.037859 seconds and 5 git commands to generate.