Commit | Line | Data |
---|---|---|
451ba2f7 AM |
1 | /* |
2 | * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir <alexmonthy@efficios.com> | |
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.lttng.scope.lttng.kernel.core.views.kernel.controlflow2; | |
11 | ||
12 | import static java.util.Objects.requireNonNull; | |
13 | ||
14 | import java.util.LinkedList; | |
15 | import java.util.List; | |
16 | import java.util.concurrent.FutureTask; | |
17 | ||
18 | import org.eclipse.jdt.annotation.Nullable; | |
d8ab28e3 AM |
19 | import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule; |
20 | import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes; | |
21 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; | |
22 | import org.eclipse.tracecompass.statesystem.core.StateSystemUtils; | |
23 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; | |
24 | import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; | |
25 | import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; | |
451ba2f7 AM |
26 | import org.lttng.scope.tmf2.views.core.TimeRange; |
27 | import org.lttng.scope.tmf2.views.core.timegraph.model.provider.statesystem.StateSystemModelArrowProvider; | |
28 | import org.lttng.scope.tmf2.views.core.timegraph.model.render.FlatUIColors; | |
29 | import org.lttng.scope.tmf2.views.core.timegraph.model.render.TimeGraphEvent; | |
30 | import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrow; | |
31 | import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowRender; | |
32 | import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowSeries; | |
33 | import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowSeries.LineStyle; | |
34 | import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; | |
35 | import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; | |
36 | ||
37 | import com.google.common.collect.Iterables; | |
38 | import com.google.common.primitives.Ints; | |
39 | ||
451ba2f7 AM |
40 | public class ControlFlowModelArrowProviderCpus extends StateSystemModelArrowProvider { |
41 | ||
42 | private static final TimeGraphArrowSeries ARROW_SERIES = new TimeGraphArrowSeries( | |
43 | requireNonNull(Messages.arrowSeriesCPUs), | |
44 | FlatUIColors.RED, | |
45 | LineStyle.FULL); | |
46 | ||
47 | public ControlFlowModelArrowProviderCpus() { | |
48 | super(ARROW_SERIES, KernelAnalysisModule.ID); | |
49 | } | |
50 | ||
51 | @Override | |
52 | public TimeGraphArrowRender getArrowRender(TimeGraphTreeRender treeRender, TimeRange timeRange, @Nullable FutureTask<?> task) { | |
53 | ITmfStateSystem ss = getStateSystem(); | |
54 | if (ss == null) { | |
55 | return TimeGraphArrowRender.EMPTY_RENDER; | |
56 | } | |
57 | ||
58 | List<Integer> threadLineQuarks = ss.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$ | |
59 | List<List<TimeGraphArrow>> allArrows = new LinkedList<>(); | |
60 | try { | |
61 | for (int threadLineQuark : threadLineQuarks) { | |
d8ab28e3 | 62 | List<ITmfStateInterval> intervals = StateSystemUtils.queryHistoryRange(ss, threadLineQuark, timeRange.getStart(), timeRange.getEnd(), 1, null); |
451ba2f7 AM |
63 | if (task != null && task.isCancelled()) { |
64 | return TimeGraphArrowRender.EMPTY_RENDER; | |
65 | } | |
66 | if (intervals.size() < 2) { | |
67 | /* Not enough states to establish a timeline */ | |
68 | continue; | |
69 | } | |
70 | ||
71 | String cpuName = ss.getAttributeName(ss.getParentAttributeQuark(threadLineQuark)); | |
72 | Integer cpu = Ints.tryParse(cpuName); | |
73 | List<TimeGraphArrow> arrows = getArrowsFromStates(treeRender, intervals, cpu); | |
74 | allArrows.add(arrows); | |
75 | } | |
76 | ||
77 | } catch (AttributeNotFoundException | StateSystemDisposedException e) { | |
78 | e.printStackTrace(); | |
79 | return TimeGraphArrowRender.EMPTY_RENDER; | |
80 | } | |
81 | ||
82 | Iterable<TimeGraphArrow> flattenedArrows = Iterables.concat(allArrows); | |
83 | return new TimeGraphArrowRender(timeRange, flattenedArrows); | |
84 | } | |
85 | ||
86 | private List<TimeGraphArrow> getArrowsFromStates(TimeGraphTreeRender treeRender, List<ITmfStateInterval> threadTimeline, @Nullable Integer cpu) { | |
87 | List<TimeGraphArrow> arrows = new LinkedList<>(); | |
88 | for (int i = 1; i < threadTimeline.size(); i++) { | |
89 | ITmfStateInterval interval1 = threadTimeline.get(i - 1); | |
90 | ITmfStateInterval interval2 = threadTimeline.get(i); | |
91 | int thread1 = interval1.getStateValue().unboxInt(); | |
92 | int thread2 = interval2.getStateValue().unboxInt(); | |
93 | ||
94 | if (thread1 == -1 || thread2 == -1) { | |
95 | /* No arrow to draw here */ | |
96 | continue; | |
97 | } | |
98 | ||
99 | TimeGraphTreeElement startTreeElem = getTreeElementFromThread(treeRender, thread1, cpu); | |
100 | TimeGraphTreeElement endTreeElem = getTreeElementFromThread(treeRender, thread2, cpu); | |
101 | TimeGraphEvent startEvent = new TimeGraphEvent(interval1.getEndTime(), startTreeElem); | |
102 | TimeGraphEvent endEvent = new TimeGraphEvent(interval2.getStartTime(), endTreeElem); | |
103 | ||
104 | TimeGraphArrow arrow = new TimeGraphArrow(startEvent, endEvent, getArrowSeries()); | |
105 | arrows.add(arrow); | |
106 | } | |
107 | return arrows; | |
108 | } | |
109 | ||
110 | private static TimeGraphTreeElement getTreeElementFromThread(TimeGraphTreeRender treeRender, int tid, @Nullable Integer cpu) { | |
111 | if (tid != 0) { | |
112 | // FIXME Could be improved via indexing, to avoid iterating the | |
113 | // whole | |
114 | // array for every single tid. | |
115 | return Iterables.find(treeRender.getAllTreeElements(), treeElem -> { | |
116 | ControlFlowTreeElement cfvTreeElem = (ControlFlowTreeElement) treeElem; | |
117 | return (cfvTreeElem.getTid() == tid); | |
118 | }); | |
119 | } | |
120 | if (cpu == null) { | |
121 | throw new IllegalStateException(); | |
122 | } | |
123 | String prefix = "0/" + cpu.toString(); //$NON-NLS-1$ | |
124 | return Iterables.find(treeRender.getAllTreeElements(), treeElem -> { | |
125 | ControlFlowTreeElement cfvTreeElem = (ControlFlowTreeElement) treeElem; | |
126 | return cfvTreeElem.getName().startsWith(prefix); | |
127 | }); | |
128 | } | |
129 | } |