Commit | Line | Data |
---|---|---|
44d8e2f1 | 1 | /******************************************************************************* |
f8f46a52 | 2 | * Copyright (c) 2015, 2016 École Polytechnique de Montréal |
44d8e2f1 FG |
3 | * |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | *******************************************************************************/ | |
9 | ||
10 | package org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view; | |
11 | ||
94411c58 AM |
12 | import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; |
13 | ||
44d8e2f1 FG |
14 | import java.util.ArrayList; |
15 | import java.util.Collections; | |
16 | import java.util.Comparator; | |
17 | import java.util.HashMap; | |
44d8e2f1 FG |
18 | import java.util.List; |
19 | import java.util.Map; | |
585f9916 GB |
20 | import java.util.concurrent.locks.Lock; |
21 | import java.util.concurrent.locks.ReentrantLock; | |
44d8e2f1 | 22 | |
b3c8181f | 23 | import org.apache.commons.lang3.StringUtils; |
44d8e2f1 | 24 | import org.eclipse.core.runtime.IProgressMonitor; |
585f9916 | 25 | import org.eclipse.core.runtime.NullProgressMonitor; |
44d8e2f1 FG |
26 | import org.eclipse.jdt.annotation.NonNull; |
27 | import org.eclipse.jdt.annotation.Nullable; | |
28 | import org.eclipse.jface.viewers.Viewer; | |
29 | import org.eclipse.tracecompass.analysis.graph.core.base.IGraphWorker; | |
30 | import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge; | |
31 | import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge.EdgeType; | |
32 | import org.eclipse.tracecompass.analysis.graph.core.base.TmfGraph; | |
33 | import org.eclipse.tracecompass.analysis.graph.core.base.TmfVertex; | |
2244d4af | 34 | import org.eclipse.tracecompass.analysis.graph.core.building.TmfGraphBuilderModule; |
44d8e2f1 | 35 | import org.eclipse.tracecompass.analysis.graph.core.criticalpath.CriticalPathModule; |
925f06a2 | 36 | import org.eclipse.tracecompass.analysis.graph.core.criticalpath.ICriticalPathProvider; |
44d8e2f1 FG |
37 | import org.eclipse.tracecompass.common.core.NonNullUtils; |
38 | import org.eclipse.tracecompass.internal.analysis.graph.core.base.TmfGraphStatistics; | |
39 | import org.eclipse.tracecompass.internal.analysis.graph.core.base.TmfGraphVisitor; | |
40 | import org.eclipse.tracecompass.internal.analysis.graph.ui.criticalpath.view.CriticalPathPresentationProvider.State; | |
41 | import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; | |
42 | import org.eclipse.tracecompass.tmf.core.signal.TmfStartAnalysisSignal; | |
43 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
44 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; | |
45 | import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractTimeGraphView; | |
46 | import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvider; | |
47 | import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent; | |
48 | import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; | |
49 | import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; | |
50 | import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent; | |
51 | import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry; | |
52 | import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeLinkEvent; | |
53 | ||
54 | import com.google.common.collect.HashBasedTable; | |
55 | import com.google.common.collect.Iterables; | |
56 | import com.google.common.collect.Table; | |
57 | ||
58 | /** | |
59 | * The Critical Path view | |
60 | * | |
61 | * @author Geneviève Bastien | |
62 | * @author Francis Giraldeau | |
63 | */ | |
64 | public class CriticalPathView extends AbstractTimeGraphView { | |
65 | ||
66 | // ------------------------------------------------------------------------ | |
67 | // Constants | |
68 | // ------------------------------------------------------------------------ | |
69 | ||
70 | /** View ID */ | |
71 | public static final String ID = "org.eclipse.linuxtools.tmf.analysis.graph.ui.criticalpath.view.criticalpathview"; //$NON-NLS-1$ | |
72 | ||
73 | private static final double NANOINV = 0.000000001; | |
74 | ||
75 | private static final String COLUMN_PROCESS = Messages.getMessage(Messages.CriticalFlowView_columnProcess); | |
76 | private static final String COLUMN_ELAPSED = Messages.getMessage(Messages.CriticalFlowView_columnElapsed); | |
77 | private static final String COLUMN_PERCENT = Messages.getMessage(Messages.CriticalFlowView_columnPercent); | |
78 | ||
79 | private static final String[] COLUMN_NAMES = new String[] { | |
80 | COLUMN_PROCESS, | |
81 | COLUMN_ELAPSED, | |
82 | COLUMN_PERCENT | |
83 | }; | |
84 | ||
85 | private static final String[] FILTER_COLUMN_NAMES = new String[] { | |
86 | COLUMN_PROCESS | |
87 | }; | |
88 | ||
dc303fab | 89 | private final Table<ITmfTrace, Object, List<ILinkEvent>> fLinks = HashBasedTable.create(); |
44d8e2f1 | 90 | /** The trace to entry list hash map */ |
dc303fab | 91 | private final Table<ITmfTrace, Object, TmfGraphStatistics> fObjectStatistics = HashBasedTable.create(); |
44d8e2f1 FG |
92 | |
93 | private final CriticalPathContentProvider fContentProvider = new CriticalPathContentProvider(); | |
94 | ||
95 | private TmfGraphStatistics fStats = new TmfGraphStatistics(); | |
96 | ||
97 | private static final IGraphWorker DEFAULT_WORKER = new IGraphWorker() { | |
98 | @Override | |
99 | public String getHostId() { | |
100 | return "default"; //$NON-NLS-1$ | |
101 | } | |
102 | }; | |
103 | ||
104 | private class CriticalPathContentProvider implements ITimeGraphContentProvider { | |
105 | ||
106 | private final class HorizontalLinksVisitor extends TmfGraphVisitor { | |
107 | private final CriticalPathEntry fDefaultParent; | |
108 | private final Map<String, CriticalPathEntry> fHostEntries; | |
109 | private final TmfGraph fGraph; | |
110 | private final ITmfTrace fTrace; | |
111 | private final HashMap<Object, CriticalPathEntry> fRootList; | |
112 | ||
113 | private HorizontalLinksVisitor(CriticalPathEntry defaultParent, Map<String, CriticalPathEntry> hostEntries, TmfGraph graph, ITmfTrace trace, HashMap<Object, CriticalPathEntry> rootList) { | |
114 | fDefaultParent = defaultParent; | |
115 | fHostEntries = hostEntries; | |
116 | fGraph = graph; | |
117 | fTrace = trace; | |
118 | fRootList = rootList; | |
119 | } | |
120 | ||
121 | @Override | |
122 | public void visitHead(TmfVertex node) { | |
123 | /* TODO possible null pointer ? */ | |
124 | IGraphWorker owner = fGraph.getParentOf(node); | |
125 | if (owner == null) { | |
126 | return; | |
127 | } | |
128 | if (fRootList.containsKey(owner)) { | |
129 | return; | |
130 | } | |
131 | TmfVertex first = fGraph.getHead(owner); | |
132 | TmfVertex last = fGraph.getTail(owner); | |
133 | if (first == null || last == null) { | |
134 | return; | |
135 | } | |
136 | setStartTime(Math.min(getStartTime(), first.getTs())); | |
137 | setEndTime(Math.max(getEndTime(), last.getTs())); | |
138 | // create host entry | |
139 | CriticalPathEntry parent = fDefaultParent; | |
140 | String host = owner.getHostId(); | |
141 | if (!fHostEntries.containsKey(host)) { | |
142 | fHostEntries.put(host, new CriticalPathEntry(host, fTrace, getStartTime(), getEndTime(), owner)); | |
143 | } | |
94411c58 | 144 | parent = checkNotNull(fHostEntries.get(host)); |
44d8e2f1 FG |
145 | CriticalPathEntry entry = new CriticalPathEntry(NonNullUtils.nullToEmptyString(owner), fTrace, getStartTime(), getEndTime(), owner); |
146 | parent.addChild(entry); | |
147 | ||
148 | fRootList.put(owner, entry); | |
149 | } | |
150 | ||
44d8e2f1 FG |
151 | @Override |
152 | public void visit(TmfEdge link, boolean horizontal) { | |
153 | if (horizontal) { | |
154 | Object parent = fGraph.getParentOf(link.getVertexFrom()); | |
0e4f957e | 155 | CriticalPathEntry entry = fRootList.get(parent); |
44d8e2f1 FG |
156 | TimeEvent ev = new TimeEvent(entry, link.getVertexFrom().getTs(), link.getDuration(), |
157 | getMatchingState(link.getType()).ordinal()); | |
158 | entry.addEvent(ev); | |
159 | } | |
160 | } | |
161 | } | |
162 | ||
163 | private final class VerticalLinksVisitor extends TmfGraphVisitor { | |
164 | private final TmfGraph fGraph; | |
165 | private final List<ILinkEvent> fGraphLinks; | |
166 | private final Map<Object, CriticalPathEntry> fEntryMap; | |
167 | ||
168 | private VerticalLinksVisitor(TmfGraph graph, List<ILinkEvent> graphLinks, Map<Object, CriticalPathEntry> entryMap) { | |
169 | fGraph = graph; | |
170 | fGraphLinks = graphLinks; | |
171 | fEntryMap = entryMap; | |
172 | } | |
173 | ||
174 | @Override | |
175 | public void visitHead(TmfVertex node) { | |
176 | ||
177 | } | |
178 | ||
179 | @Override | |
180 | public void visit(TmfVertex node) { | |
181 | ||
182 | } | |
183 | ||
184 | @Override | |
185 | public void visit(TmfEdge link, boolean horizontal) { | |
186 | if (!horizontal) { | |
187 | Object parentFrom = fGraph.getParentOf(link.getVertexFrom()); | |
188 | Object parentTo = fGraph.getParentOf(link.getVertexTo()); | |
189 | CriticalPathEntry entryFrom = fEntryMap.get(parentFrom); | |
190 | CriticalPathEntry entryTo = fEntryMap.get(parentTo); | |
191 | TimeLinkEvent lk = new TimeLinkEvent(entryFrom, entryTo, link.getVertexFrom().getTs(), | |
192 | link.getVertexTo().getTs() - link.getVertexFrom().getTs(), getMatchingState(link.getType()).ordinal()); | |
193 | fGraphLinks.add(lk); | |
194 | } | |
195 | } | |
196 | } | |
197 | ||
585f9916 | 198 | private class BuildThread extends Thread { |
925f06a2 | 199 | private final CriticalPathModule fModule; |
585f9916 GB |
200 | private final IProgressMonitor fMonitor; |
201 | ||
925f06a2 | 202 | public BuildThread(final CriticalPathModule module) { |
585f9916 | 203 | super("Critical path view build"); //$NON-NLS-1$ |
925f06a2 | 204 | fModule = module; |
585f9916 GB |
205 | fMonitor = new NullProgressMonitor(); |
206 | } | |
207 | ||
208 | @Override | |
209 | public void run() { | |
210 | try { | |
925f06a2 | 211 | CriticalPathModule module = fModule; |
585f9916 GB |
212 | module.schedule(); |
213 | if (module.waitForCompletion(fMonitor)) { | |
2244d4af GB |
214 | // Module is completed, set the start and end time of |
215 | // this view | |
216 | setStartEndTime(module); | |
585f9916 GB |
217 | refresh(); |
218 | } | |
219 | ||
220 | } finally { | |
221 | fSyncLock.lock(); | |
222 | fBuildThread = null; | |
223 | fSyncLock.unlock(); | |
224 | } | |
225 | } | |
226 | ||
227 | public void cancel() { | |
228 | fMonitor.setCanceled(true); | |
229 | } | |
230 | } | |
231 | ||
232 | private final Lock fSyncLock = new ReentrantLock(); | |
233 | private final Map<Object, Map<Object, CriticalPathEntry>> workerMaps = new HashMap<>(); | |
234 | private final Map<Object, List<TimeGraphEntry>> workerEntries = new HashMap<>(); | |
44d8e2f1 | 235 | private @Nullable Object fCurrentObject; |
585f9916 | 236 | private @Nullable BuildThread fBuildThread = null; |
44d8e2f1 FG |
237 | |
238 | @Override | |
df2597e0 | 239 | public ITimeGraphEntry[] getElements(@Nullable Object inputElement) { |
44d8e2f1 FG |
240 | ITimeGraphEntry[] ret = new ITimeGraphEntry[0]; |
241 | if (inputElement instanceof List) { | |
242 | List<?> list = (List<?>) inputElement; | |
243 | if (!list.isEmpty()) { | |
244 | Object first = list.get(0); | |
245 | if (first instanceof CriticalPathBaseEntry) { | |
246 | IGraphWorker worker = ((CriticalPathBaseEntry) first).getWorker(); | |
247 | ret = getWorkerEntries(worker); | |
248 | } | |
249 | } | |
250 | } | |
251 | return ret; | |
252 | } | |
253 | ||
254 | private ITimeGraphEntry[] getWorkerEntries(IGraphWorker worker) { | |
255 | fCurrentObject = worker; | |
256 | List<TimeGraphEntry> entries = workerEntries.get(worker); | |
2244d4af | 257 | ITmfTrace trace = getTrace(); |
44d8e2f1 FG |
258 | if (entries == null) { |
259 | buildEntryList(worker); | |
260 | entries = workerEntries.get(worker); | |
2244d4af GB |
261 | } else if (trace != null) { |
262 | // Get the statistics object for this worker | |
263 | TmfGraphStatistics stats = fObjectStatistics.get(trace, worker); | |
264 | if (stats == null) { | |
265 | stats = new TmfGraphStatistics(); | |
27150837 GB |
266 | final TmfGraph graph = getGraph(trace); |
267 | if (graph != null) { | |
268 | stats.computeGraphStatistics(graph, worker); | |
269 | } | |
2244d4af GB |
270 | } |
271 | fStats = stats; | |
44d8e2f1 | 272 | } |
df2597e0 | 273 | |
44d8e2f1 FG |
274 | return (entries == null) ? |
275 | new ITimeGraphEntry[0] : | |
367e2932 | 276 | entries.toArray(new @NonNull ITimeGraphEntry[entries.size()]); |
44d8e2f1 FG |
277 | } |
278 | ||
279 | private void buildEntryList(IGraphWorker worker) { | |
280 | final ITmfTrace trace = getTrace(); | |
281 | if (trace == null) { | |
282 | return; | |
283 | } | |
284 | final TmfGraph graph = getGraph(trace); | |
285 | if (graph == null) { | |
286 | return; | |
287 | } | |
44d8e2f1 FG |
288 | |
289 | final HashMap<Object, CriticalPathEntry> rootList = new HashMap<>(); | |
290 | fLinks.remove(trace, worker); | |
291 | ||
292 | TmfVertex vertex = graph.getHead(); | |
293 | ||
294 | /* Calculate statistics */ | |
295 | fStats = new TmfGraphStatistics(); | |
296 | fStats.computeGraphStatistics(graph, worker); | |
297 | fObjectStatistics.put(trace, worker, fStats); | |
298 | ||
299 | // Hosts entries are parent of each worker entries | |
300 | final Map<String, CriticalPathEntry> hostEntries = new HashMap<>(); | |
301 | ||
302 | /* create all interval entries and horizontal links */ | |
303 | ||
304 | final CriticalPathEntry defaultParent = new CriticalPathEntry("default", trace, getStartTime(), getEndTime(), DEFAULT_WORKER); //$NON-NLS-1$ | |
305 | graph.scanLineTraverse(vertex, new HorizontalLinksVisitor(defaultParent, hostEntries, graph, trace, rootList)); | |
306 | ||
307 | workerMaps.put(worker, rootList); | |
308 | ||
309 | List<TimeGraphEntry> list = new ArrayList<>(); | |
310 | list.addAll(hostEntries.values()); | |
311 | if (defaultParent.hasChildren()) { | |
312 | list.add(defaultParent); | |
313 | } | |
314 | ||
44d8e2f1 FG |
315 | workerEntries.put(worker, list); |
316 | } | |
317 | ||
318 | private @Nullable TmfGraph getGraph(final ITmfTrace trace) { | |
925f06a2 GB |
319 | ICriticalPathProvider module = Iterables.<@Nullable ICriticalPathProvider> getFirst( |
320 | TmfTraceUtils.getAnalysisModulesOfClass(trace, ICriticalPathProvider.class), | |
df2597e0 | 321 | null); |
44d8e2f1 | 322 | if (module == null) { |
9ee366e2 | 323 | throw new IllegalStateException("View requires an analysis module"); //$NON-NLS-1$ |
44d8e2f1 | 324 | } |
df2597e0 | 325 | |
44d8e2f1 FG |
326 | final TmfGraph graph = module.getCriticalPath(); |
327 | return graph; | |
328 | } | |
329 | ||
330 | public @Nullable List<ILinkEvent> getLinkList(long startTime, long endTime) { | |
331 | Object current = fCurrentObject; | |
332 | if (current == null) { | |
333 | return null; | |
334 | } | |
d2120996 GB |
335 | final ITmfTrace trace = getTrace(); |
336 | if (trace == null) { | |
337 | return null; | |
338 | } | |
44d8e2f1 FG |
339 | /* |
340 | * Critical path typically has relatively few links, so we calculate | |
341 | * and save them all, but just return those in range | |
342 | */ | |
d2120996 | 343 | List<ILinkEvent> links = fLinks.get(trace, current); |
44d8e2f1 | 344 | if (links != null) { |
d2120996 | 345 | return getLinksInRange(links, startTime, endTime); |
44d8e2f1 | 346 | } |
d2120996 | 347 | |
925f06a2 GB |
348 | ICriticalPathProvider module = Iterables.<@Nullable ICriticalPathProvider> getFirst( |
349 | TmfTraceUtils.getAnalysisModulesOfClass(trace, ICriticalPathProvider.class), null); | |
44d8e2f1 | 350 | if (module == null) { |
9ee366e2 | 351 | throw new IllegalStateException("View requires an analysis module"); //$NON-NLS-1$ |
44d8e2f1 | 352 | } |
df2597e0 | 353 | |
44d8e2f1 FG |
354 | final TmfGraph graph = module.getCriticalPath(); |
355 | if (graph == null) { | |
356 | return null; | |
357 | } | |
358 | final Map<Object, CriticalPathEntry> entryMap = workerMaps.get(current); | |
359 | if (entryMap == null) { | |
360 | return null; | |
361 | } | |
362 | ||
363 | TmfVertex vertex = graph.getHead(); | |
364 | ||
365 | final List<ILinkEvent> graphLinks = new ArrayList<>(); | |
366 | ||
367 | /* find vertical links */ | |
368 | graph.scanLineTraverse(vertex, new VerticalLinksVisitor(graph, graphLinks, entryMap)); | |
d2120996 GB |
369 | fLinks.put(trace, current, graphLinks); |
370 | ||
371 | return getLinksInRange(graphLinks, startTime, endTime); | |
372 | } | |
44d8e2f1 | 373 | |
d2120996 | 374 | private List<ILinkEvent> getLinksInRange(List<ILinkEvent> allLinks, long startTime, long endTime) { |
44d8e2f1 | 375 | List<ILinkEvent> linksInRange = new ArrayList<>(); |
d2120996 | 376 | for (ILinkEvent link : allLinks) { |
44d8e2f1 FG |
377 | if (((link.getTime() >= startTime) && (link.getTime() <= endTime)) || |
378 | ((link.getTime() + link.getDuration() >= startTime) && (link.getTime() + link.getDuration() <= endTime))) { | |
379 | linksInRange.add(link); | |
380 | } | |
381 | } | |
382 | return linksInRange; | |
383 | } | |
384 | ||
385 | @Override | |
386 | public void dispose() { | |
585f9916 GB |
387 | fSyncLock.lock(); |
388 | try { | |
389 | BuildThread buildThread = fBuildThread; | |
390 | if (buildThread != null) { | |
391 | buildThread.cancel(); | |
392 | } | |
393 | } finally { | |
394 | fSyncLock.unlock(); | |
395 | } | |
44d8e2f1 FG |
396 | } |
397 | ||
398 | @Override | |
399 | public void inputChanged(@Nullable Viewer viewer, @Nullable Object oldInput, @Nullable Object newInput) { | |
585f9916 GB |
400 | // The input has changed, the critical path will be re-computed, |
401 | // wait for the analysis to be finished, then call the refresh | |
402 | // method of the view | |
403 | if (!(newInput instanceof List)) { | |
404 | return; | |
405 | } | |
406 | List<?> list = (List<?>) newInput; | |
407 | if (list.isEmpty()) { | |
408 | return; | |
409 | } | |
925f06a2 GB |
410 | |
411 | Object first = list.get(0); | |
412 | if (!(first instanceof CriticalPathBaseEntry)) { | |
585f9916 GB |
413 | return; |
414 | } | |
925f06a2 | 415 | CriticalPathModule module = ((CriticalPathBaseEntry) first).getModule(); |
585f9916 GB |
416 | |
417 | fSyncLock.lock(); | |
418 | try { | |
419 | BuildThread buildThread = fBuildThread; | |
420 | if (buildThread != null) { | |
421 | buildThread.cancel(); | |
422 | } | |
925f06a2 | 423 | buildThread = new BuildThread(module); |
585f9916 GB |
424 | buildThread.start(); |
425 | fBuildThread = buildThread; | |
426 | } finally { | |
427 | fSyncLock.unlock(); | |
428 | } | |
44d8e2f1 FG |
429 | } |
430 | ||
431 | @Override | |
4c4e2816 | 432 | public ITimeGraphEntry @Nullable [] getChildren(@Nullable Object parentElement) { |
44d8e2f1 FG |
433 | if (parentElement instanceof CriticalPathEntry) { |
434 | List<? extends ITimeGraphEntry> children = ((CriticalPathEntry) parentElement).getChildren(); | |
435 | return children.toArray(new TimeGraphEntry[children.size()]); | |
436 | } | |
437 | return null; | |
438 | } | |
439 | ||
440 | @Override | |
441 | public @Nullable ITimeGraphEntry getParent(@Nullable Object element) { | |
442 | if (element instanceof CriticalPathEntry) { | |
443 | return ((CriticalPathEntry) element).getParent(); | |
444 | } | |
445 | return null; | |
446 | } | |
447 | ||
448 | @Override | |
449 | public boolean hasChildren(@Nullable Object element) { | |
450 | if (element instanceof CriticalPathEntry) { | |
451 | return ((CriticalPathEntry) element).hasChildren(); | |
452 | } | |
453 | return false; | |
454 | } | |
455 | ||
456 | } | |
457 | ||
458 | private class CriticalPathTreeLabelProvider extends TreeLabelProvider { | |
459 | ||
460 | @Override | |
461 | public String getColumnText(@Nullable Object element, int columnIndex) { | |
462 | if (element == null) { | |
b3c8181f | 463 | return StringUtils.EMPTY; |
44d8e2f1 FG |
464 | } |
465 | CriticalPathEntry entry = (CriticalPathEntry) element; | |
466 | if (columnIndex == 0) { | |
467 | return NonNullUtils.nullToEmptyString(entry.getName()); | |
468 | } else if (columnIndex == 1) { | |
469 | Long sum = fStats.getSum(entry.getWorker()); | |
470 | String value = String.format("%.9f", sum * NANOINV); //$NON-NLS-1$ | |
471 | return NonNullUtils.nullToEmptyString(value); | |
472 | } else if (columnIndex == 2) { | |
473 | Double percent = fStats.getPercent(entry.getWorker()); | |
474 | String value = String.format("%.2f", percent * 100); //$NON-NLS-1$ | |
475 | return NonNullUtils.nullToEmptyString(value); | |
476 | } | |
b3c8181f | 477 | return StringUtils.EMPTY; |
44d8e2f1 FG |
478 | } |
479 | ||
480 | } | |
481 | ||
482 | private class CriticalPathEntryComparator implements Comparator<ITimeGraphEntry> { | |
483 | ||
484 | @Override | |
485 | public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { | |
486 | ||
487 | int result = 0; | |
488 | ||
489 | if ((o1 instanceof CriticalPathEntry) && (o2 instanceof CriticalPathEntry)) { | |
490 | CriticalPathEntry entry1 = (CriticalPathEntry) o1; | |
491 | CriticalPathEntry entry2 = (CriticalPathEntry) o2; | |
492 | result = -1 * fStats.getSum(entry1.getWorker()).compareTo(fStats.getSum(entry2.getWorker())); | |
493 | } | |
494 | return result; | |
495 | } | |
496 | } | |
497 | ||
498 | /** | |
499 | * Constructor | |
500 | */ | |
501 | public CriticalPathView() { | |
502 | super(ID, new CriticalPathPresentationProvider()); | |
503 | setTreeColumns(COLUMN_NAMES); | |
504 | setFilterColumns(FILTER_COLUMN_NAMES); | |
505 | setTreeLabelProvider(new CriticalPathTreeLabelProvider()); | |
506 | setTimeGraphContentProvider(fContentProvider); | |
507 | setEntryComparator(new CriticalPathEntryComparator()); | |
508 | } | |
509 | ||
510 | // ------------------------------------------------------------------------ | |
511 | // Internal | |
512 | // ------------------------------------------------------------------------ | |
513 | ||
514 | private static State getMatchingState(EdgeType type) { | |
515 | State state = State.UNKNOWN; | |
516 | switch (type) { | |
517 | case RUNNING: | |
518 | state = State.RUNNING; | |
519 | break; | |
520 | case PREEMPTED: | |
521 | state = State.PREEMPTED; | |
522 | break; | |
523 | case TIMER: | |
524 | state = State.TIMER; | |
525 | break; | |
526 | case BLOCK_DEVICE: | |
527 | state = State.BLOCK_DEVICE; | |
528 | break; | |
529 | case INTERRUPTED: | |
530 | state = State.INTERRUPTED; | |
531 | break; | |
532 | case NETWORK: | |
533 | state = State.NETWORK; | |
534 | break; | |
535 | case USER_INPUT: | |
536 | state = State.USER_INPUT; | |
537 | break; | |
5aa7fe19 FG |
538 | case IPI: |
539 | state = State.IPI; | |
540 | break; | |
44d8e2f1 FG |
541 | case EPS: |
542 | case UNKNOWN: | |
543 | case DEFAULT: | |
544 | case BLOCKED: | |
545 | break; | |
546 | default: | |
547 | break; | |
548 | } | |
549 | return state; | |
550 | } | |
551 | ||
44d8e2f1 | 552 | @Override |
f8f46a52 | 553 | protected void buildEntryList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor) { |
44d8e2f1 FG |
554 | /* This class uses a content provider instead */ |
555 | } | |
556 | ||
557 | @Override | |
558 | protected @Nullable List<ITimeEvent> getEventList(TimeGraphEntry entry, | |
559 | long startTime, long endTime, long resolution, | |
560 | IProgressMonitor monitor) { | |
32ba3b09 PT |
561 | /* |
562 | * The event list is built in the HorizontalLinksVisitor. This is called | |
563 | * only from the zoom thread and only for the CriticalPathBaseEntry. | |
564 | */ | |
565 | return null; | |
44d8e2f1 FG |
566 | } |
567 | ||
568 | @Override | |
569 | protected @Nullable List<ILinkEvent> getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) { | |
570 | return fContentProvider.getLinkList(startTime, endTime); | |
571 | } | |
572 | ||
573 | /** | |
574 | * Signal handler for analysis started | |
575 | * | |
576 | * @param signal | |
577 | * The signal | |
578 | */ | |
579 | @TmfSignalHandler | |
580 | public void analysisStarted(TmfStartAnalysisSignal signal) { | |
581 | if (!(signal.getAnalysisModule() instanceof CriticalPathModule)) { | |
582 | return; | |
583 | } | |
584 | CriticalPathModule module = (CriticalPathModule) signal.getAnalysisModule(); | |
585 | Object obj = module.getParameter(CriticalPathModule.PARAM_WORKER); | |
586 | if (obj == null) { | |
587 | return; | |
588 | } | |
589 | if (!(obj instanceof IGraphWorker)) { | |
590 | throw new IllegalStateException("Wrong type for critical path module parameter " + //$NON-NLS-1$ | |
591 | CriticalPathModule.PARAM_WORKER + | |
592 | " expected IGraphWorker got " + //$NON-NLS-1$ | |
593 | obj.getClass().getSimpleName()); | |
594 | } | |
595 | ITmfTrace trace = getTrace(); | |
596 | if (trace == null) { | |
597 | throw new IllegalStateException("Trace is null"); //$NON-NLS-1$ | |
598 | } | |
599 | IGraphWorker worker = (IGraphWorker) obj; | |
44d8e2f1 | 600 | |
925f06a2 | 601 | TimeGraphEntry tge = new CriticalPathBaseEntry(worker, module); |
44d8e2f1 FG |
602 | List<TimeGraphEntry> list = Collections.singletonList(tge); |
603 | putEntryList(trace, list); | |
604 | refresh(); | |
605 | } | |
606 | ||
2244d4af GB |
607 | private void setStartEndTime(CriticalPathModule module) { |
608 | // Initialize the start/end time of the view to trace's times | |
609 | ITmfTrace trace = getTrace(); | |
610 | if (trace == null) { | |
611 | throw new IllegalStateException("The trace should not be null when we have a critical path to display"); //$NON-NLS-1$ | |
612 | } | |
613 | long start = trace.getStartTime().toNanos(); | |
614 | long end = trace.getEndTime().toNanos(); | |
615 | ||
616 | // Set the start/end time of the view | |
617 | Object paramGraph = module.getParameter(CriticalPathModule.PARAM_GRAPH); | |
618 | if (paramGraph instanceof TmfGraphBuilderModule) { | |
619 | TmfGraphBuilderModule graphModule = (TmfGraphBuilderModule) paramGraph; | |
620 | TmfGraph graph = graphModule.getGraph(); | |
621 | if (graph == null) { | |
622 | return; | |
623 | } | |
624 | TmfVertex head = graph.getHead(); | |
625 | if (head != null) { | |
626 | start = Math.min(start, head.getTs()); | |
627 | for (IGraphWorker w : graph.getWorkers()) { | |
628 | TmfVertex tail = graph.getTail(w); | |
629 | if (tail != null) { | |
630 | end = Math.max(end, tail.getTs()); | |
631 | } | |
632 | } | |
633 | } | |
634 | } | |
635 | setStartTime(start); | |
636 | setEndTime(end); | |
637 | } | |
638 | ||
44d8e2f1 | 639 | } |