Commit | Line | Data |
---|---|---|
af3275f8 AM |
1 | /******************************************************************************* |
2 | * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir | |
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.timegraph.threads; | |
11 | ||
12 | import static java.util.Objects.requireNonNull; | |
13 | ||
14 | import java.util.Collections; | |
15 | import java.util.Comparator; | |
16 | import java.util.List; | |
17 | import java.util.function.Function; | |
18 | import java.util.function.Supplier; | |
19 | import java.util.stream.Collectors; | |
20 | import java.util.stream.Stream; | |
21 | ||
deecbf8e AM |
22 | import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule; |
23 | import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes; | |
24 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; | |
25 | import org.eclipse.tracecompass.statesystem.core.StateSystemUtils; | |
26 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; | |
27 | import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; | |
af3275f8 AM |
28 | import org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows.ITimeGraphModelArrowProvider; |
29 | import org.lttng.scope.tmf2.views.core.timegraph.model.provider.states.ITimeGraphModelStateProvider; | |
30 | import org.lttng.scope.tmf2.views.core.timegraph.model.provider.statesystem.StateSystemModelProvider; | |
31 | import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; | |
32 | import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; | |
33 | ||
34 | import com.google.common.annotations.VisibleForTesting; | |
35 | import com.google.common.collect.ImmutableList; | |
36 | ||
af3275f8 AM |
37 | public class ThreadsModelProvider extends StateSystemModelProvider { |
38 | ||
39 | private static final Supplier<ITimeGraphModelStateProvider> STATE_PROVIDER = () -> { | |
40 | return new ThreadsModelStateProvider(); | |
41 | }; | |
42 | ||
43 | private static final Supplier<List<ITimeGraphModelArrowProvider>> ARROW_PROVIDERS = () -> { | |
44 | return ImmutableList.of( | |
45 | new ThreadsModelArrowProviderCpus() | |
46 | ); | |
47 | }; | |
48 | ||
49 | private static final List<SortingMode> SORTING_MODES = ImmutableList.of( | |
50 | ThreadsConfigModes.SORTING_BY_TID, | |
51 | ThreadsConfigModes.SORTING_BY_THREAD_NAME); | |
52 | ||
53 | private static final List<FilterMode> FILTER_MODES = ImmutableList.of( | |
54 | ThreadsConfigModes.FILTERING_INACTIVE_ENTRIES); | |
55 | ||
56 | // ------------------------------------------------------------------------ | |
57 | // Tree render | |
58 | // ------------------------------------------------------------------------ | |
59 | ||
60 | /** | |
61 | * State values that are considered inactive, for purposes of filtering out | |
62 | * when the "filter inactive entries" mode is enabled. | |
63 | */ | |
64 | // private static final Set<ITmfStateValue> INACTIVE_STATE_VALUES = ImmutableSet.of( | |
65 | // TmfStateValue.nullValue(), | |
66 | // StateValues.PROCESS_STATUS_UNKNOWN_VALUE, | |
67 | // StateValues.PROCESS_STATUS_WAIT_UNKNOWN_VALUE, | |
68 | // StateValues.PROCESS_STATUS_WAIT_BLOCKED_VALUE | |
69 | // ); | |
70 | ||
71 | /** | |
72 | * Each "Thread" attribute has the following children: | |
73 | * | |
74 | * <ul> | |
75 | * <li>Prio</li> | |
76 | * <li>System_call</li> | |
77 | * <li>Exec_name</li> | |
78 | * <li>PPID</li> | |
79 | * </ul> | |
80 | * | |
81 | * The "Thread" is considered the base quark. | |
82 | */ | |
83 | private static final String[] BASE_QUARK_PATTERN = { Attributes.THREADS, "*" }; //$NON-NLS-1$ | |
84 | ||
85 | /** | |
86 | * Get the tree element name for every thread. It consists of the TID | |
87 | * followed by the first available exec_name for this thread. | |
88 | * | |
89 | * FIXME This implies a static tree definition for every TID, which does not | |
90 | * handle TID re-use correctly. The state system structure should be updated | |
91 | * accordingly. | |
92 | */ | |
93 | @VisibleForTesting | |
94 | public static final Function<TreeRenderContext, TimeGraphTreeRender> SS_TO_TREE_RENDER_FUNCTION = (treeContext) -> { | |
95 | ITmfStateSystem ss = treeContext.ss; | |
96 | // List<ITmfStateInterval> fullState = treeContext.fullQueryAtRangeStart; | |
97 | ||
98 | Stream<ThreadsTreeElement> treeElems = ss.getQuarks(BASE_QUARK_PATTERN).stream() | |
99 | .map(baseQuark -> { | |
100 | String tid = ss.getAttributeName(baseQuark); | |
101 | ||
102 | String threadName; | |
103 | try { | |
104 | int execNameQuark = ss.getQuarkRelative(baseQuark, Attributes.EXEC_NAME); | |
105 | // TODO We should look starting at | |
106 | // treeContext.renderTimeRangeStart first, and if we | |
107 | // don't find anything use ss.getStartTime(), so that we | |
108 | // catch subsequent process name changes | |
109 | ITmfStateInterval firstInterval = StateSystemUtils.queryUntilNonNullValue(ss, | |
110 | execNameQuark, ss.getStartTime(), Long.MAX_VALUE); | |
111 | if (firstInterval == null) { | |
112 | threadName = null; | |
113 | } else { | |
114 | threadName = firstInterval.getStateValue().unboxStr(); | |
115 | } | |
116 | } catch (AttributeNotFoundException e) { | |
117 | threadName = null; | |
118 | } | |
119 | ||
120 | return new ThreadsTreeElement(tid, threadName, Collections.emptyList(), baseQuark); | |
121 | }); | |
122 | ||
123 | /* Run the entries through the active filter modes */ | |
124 | // Set<FilterMode> filterModes = treeContext.filterModes; | |
125 | // if (filterModes.contains(ControlFlowConfigModes.FILTERING_INACTIVE_ENTRIES)) { | |
126 | // /* | |
127 | // * Filter out the tree elements whose state is considered inactive | |
128 | // * for the whole duration of the configured time range. | |
129 | // */ | |
130 | // treeElems = treeElems.filter(elem -> { | |
131 | // ITmfStateInterval interval = fullState.get(elem.getSourceQuark()); | |
132 | // if (interval.getEndTime() > treeContext.renderTimeRangeEnd && | |
133 | // INACTIVE_STATE_VALUES.contains(interval.getStateValue())) { | |
134 | // return false; | |
135 | // } | |
136 | // return true; | |
137 | // }); | |
138 | // } | |
139 | ||
140 | /* Sort entries according to the active sorting mode */ | |
141 | SortingMode sortingMode = treeContext.sortingMode; | |
142 | if (sortingMode == ThreadsConfigModes.SORTING_BY_TID) { | |
143 | treeElems = treeElems.sorted(Comparator.comparingInt(ThreadsTreeElement::getTid)); | |
144 | } else if (sortingMode == ThreadsConfigModes.SORTING_BY_THREAD_NAME) { | |
145 | treeElems = treeElems.sorted((elem1, elem2) -> { | |
146 | return elem1.getThreadName().compareToIgnoreCase(elem2.getThreadName()); | |
147 | }); | |
148 | } | |
149 | ||
150 | List<TimeGraphTreeElement> treeElemsList = treeElems.collect(Collectors.toList()); | |
151 | TimeGraphTreeElement rootElement = new TimeGraphTreeElement(treeContext.traceName, treeElemsList); | |
152 | return new TimeGraphTreeRender(rootElement); | |
153 | }; | |
154 | ||
155 | /** | |
156 | * Constructor | |
157 | */ | |
158 | public ThreadsModelProvider() { | |
159 | super(requireNonNull(Messages.threadsProviderName), | |
160 | SORTING_MODES, | |
161 | FILTER_MODES, | |
162 | STATE_PROVIDER.get(), | |
163 | ARROW_PROVIDERS.get(), | |
164 | /* Parameters specific to state system render providers */ | |
165 | KernelAnalysisModule.ID, | |
166 | SS_TO_TREE_RENDER_FUNCTION); | |
167 | ||
168 | enableFilterMode(0); | |
169 | } | |
170 | ||
171 | } |