1 /*******************************************************************************
2 * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir
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 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.core
.views
.controlflow2
;
12 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.nullToEmptyString
;
14 import java
.util
.Collections
;
15 import java
.util
.Comparator
;
16 import java
.util
.List
;
19 import java
.util
.function
.Function
;
20 import java
.util
.function
.Supplier
;
21 import java
.util
.stream
.Collectors
;
22 import java
.util
.stream
.Stream
;
24 import org
.eclipse
.jdt
.annotation
.Nullable
;
25 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.KernelAnalysisModule
;
26 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.StateValues
;
27 import org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.core
.kernel
.Attributes
;
28 import org
.eclipse
.tracecompass
.internal
.provisional
.tmf
.core
.views
.timegraph2
.ColorDefinition
;
29 import org
.eclipse
.tracecompass
.internal
.provisional
.tmf
.core
.views
.timegraph2
.TimeGraphTreeElement
;
30 import org
.eclipse
.tracecompass
.internal
.provisional
.tmf
.core
.views
.timegraph2
.TimeGraphTreeRender
;
31 import org
.eclipse
.tracecompass
.internal
.provisional
.tmf
.core
.views
.timegraph2
.TimeGraphStateInterval
.LineThickness
;
32 import org
.eclipse
.tracecompass
.internal
.provisional
.tmf
.core
.views
.timegraph2
.statesystem
.StateSystemModelRenderProvider
;
33 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
34 import org
.eclipse
.tracecompass
.statesystem
.core
.StateSystemUtils
;
35 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
36 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
37 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
38 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
39 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
41 import com
.google
.common
.annotations
.VisibleForTesting
;
42 import com
.google
.common
.collect
.ImmutableList
;
43 import com
.google
.common
.collect
.ImmutableSet
;
45 public class ControlFlowRenderProvider
extends StateSystemModelRenderProvider
{
47 private static final List
<SortingMode
> SORTING_MODES
= ImmutableList
.of(
48 ControlFlowConfigModes
.SORTING_BY_TID
,
49 ControlFlowConfigModes
.SORTING_BY_THREAD_NAME
);
51 private static final List
<FilterMode
> FILTER_MODES
= ImmutableList
.of(
52 ControlFlowConfigModes
.FILTERING_INACTIVE_ENTRIES
);
55 * State values that are considered inactive, for purposes of filtering out
56 * when the "filter inactive entries" mode is enabled.
58 private static final Set
<ITmfStateValue
> INACTIVE_STATE_VALUES
= ImmutableSet
.of(
59 TmfStateValue
.nullValue(),
60 StateValues
.PROCESS_STATUS_UNKNOWN_VALUE
,
61 StateValues
.PROCESS_STATUS_WAIT_UNKNOWN_VALUE
,
62 StateValues
.PROCESS_STATUS_WAIT_BLOCKED_VALUE
66 * Each "Thread" attribute has the following children:
70 * <li>System_call</li>
75 * The "Thread" is considered the base quark.
77 private static final String
[] BASE_QUARK_PATTERN
= { Attributes
.THREADS
, "*" }; //$NON-NLS-1$
80 * Get the tree element name for every thread. It consists of the TID
81 * followed by the first available exec_name for this thread.
83 * FIXME This implies a static tree definition for every TID, which does not
84 * handle TID re-use correctly. The state system structure should be updated
88 public static final Function
<TreeRenderContext
, TimeGraphTreeRender
> SS_TO_TREE_RENDER_FUNCTION
= (treeContext
) -> {
89 ITmfStateSystem ss
= treeContext
.ss
;
90 List
<ITmfStateInterval
> fullState
= treeContext
.fullQueryAtRangeStart
;
92 Stream
<ControlFlowTreeElement
> treeElems
= ss
.getQuarks(BASE_QUARK_PATTERN
).stream()
94 String tid
= ss
.getAttributeName(baseQuark
);
98 int execNameQuark
= ss
.getQuarkRelative(baseQuark
, Attributes
.EXEC_NAME
);
99 // TODO We should look starting at treeContext.renderTimeRangeStart
100 // first, and if we don't find anything use ss.getStartTime(), so that
101 // we catch subsequent process name changes
102 ITmfStateInterval firstInterval
= StateSystemUtils
.queryUntilNonNullValue(ss
,
103 execNameQuark
, ss
.getStartTime(), Long
.MAX_VALUE
);
104 if (firstInterval
== null) {
107 threadName
= firstInterval
.getStateValue().unboxStr();
109 } catch (AttributeNotFoundException
| StateValueTypeException e
) {
113 return new ControlFlowTreeElement(tid
, threadName
, Collections
.emptyList(), baseQuark
);
116 /* Run the entries through the active filter modes */
117 Set
<FilterMode
> filterModes
= treeContext
.filterModes
;
118 if (filterModes
.contains(ControlFlowConfigModes
.FILTERING_INACTIVE_ENTRIES
)) {
120 * Filter out the tree elements whose state is considered inactive
121 * for the whole duration of the configured time range.
123 treeElems
= treeElems
.filter(elem
-> {
124 ITmfStateInterval interval
= fullState
.get(elem
.getSourceQuark());
125 if (interval
.getEndTime() > treeContext
.renderTimeRangeEnd
&&
126 INACTIVE_STATE_VALUES
.contains(interval
.getStateValue())) {
133 /* Sort entries according to the active sorting mode */
134 SortingMode sortingMode
= treeContext
.sortingMode
;
135 if (sortingMode
== ControlFlowConfigModes
.SORTING_BY_TID
) {
136 treeElems
= treeElems
.sorted(Comparator
.comparingInt(ControlFlowTreeElement
::getTid
));
137 } else if (sortingMode
== ControlFlowConfigModes
.SORTING_BY_THREAD_NAME
) {
138 treeElems
= treeElems
.sorted((elem1
, elem2
) -> {
139 return elem1
.getThreadName().compareToIgnoreCase(elem2
.getThreadName());
143 List
<TimeGraphTreeElement
> treeElemsList
= treeElems
.collect(Collectors
.toList());
144 return new TimeGraphTreeRender(treeElemsList
);
150 * Function mapping state names
153 * State value representing the state
154 * @return The state name to display, should be localized
157 public static String
mapStateValueToStateName(int value
) {
160 case StateValues
.PROCESS_STATUS_WAIT_UNKNOWN
:
161 return nullToEmptyString(Messages
.ControlFlowRenderProvider_State_WaitUnknown
);
162 case StateValues
.PROCESS_STATUS_WAIT_BLOCKED
:
163 return nullToEmptyString(Messages
.ControlFlowRenderProvider_State_WaitBlocked
);
164 case StateValues
.PROCESS_STATUS_WAIT_FOR_CPU
:
165 return nullToEmptyString(Messages
.ControlFlowRenderProvider_State_WaitForCpu
);
166 case StateValues
.PROCESS_STATUS_RUN_USERMODE
:
167 return nullToEmptyString(Messages
.ControlFlowRenderProvider_State_UserMode
);
168 case StateValues
.PROCESS_STATUS_RUN_SYSCALL
:
169 return nullToEmptyString(Messages
.ControlFlowRenderProvider_State_Syscall
);
170 case StateValues
.PROCESS_STATUS_INTERRUPTED
:
171 return nullToEmptyString(Messages
.ControlFlowRenderProvider_State_Interrupted
);
173 return nullToEmptyString(Messages
.ControlFlowRenderProvider_State_Unknown
);
176 } catch (StateValueTypeException e
) {
177 return nullToEmptyString(Messages
.ControlFlowRenderProvider_State_Unknown
);
181 private static final Function
<StateIntervalContext
, String
> STATE_NAME_MAPPING_FUNCTION
= ssCtx
-> {
182 int statusQuark
= ssCtx
.baseTreeElement
.getSourceQuark();
183 ITmfStateValue val
= ssCtx
.fullQueryAtIntervalStart
.get(statusQuark
).getStateValue();
184 int status
= val
.unboxInt();
185 return mapStateValueToStateName(status
);
189 private static final ColorDefinition NO_COLOR
= new ColorDefinition( 0, 0, 0, 0);
190 private static final ColorDefinition COLOR_UNKNOWN
= new ColorDefinition(100, 100, 100);
191 private static final ColorDefinition COLOR_WAIT_UNKNOWN
= new ColorDefinition(200, 200, 200);
192 private static final ColorDefinition COLOR_WAIT_BLOCKED
= new ColorDefinition(200, 200, 0);
193 private static final ColorDefinition COLOR_WAIT_FOR_CPU
= new ColorDefinition(200, 100, 0);
194 private static final ColorDefinition COLOR_USERMODE
= new ColorDefinition( 0, 200, 0);
195 private static final ColorDefinition COLOR_SYSCALL
= new ColorDefinition( 0, 0, 200);
196 private static final ColorDefinition COLOR_INTERRUPTED
= new ColorDefinition(200, 0, 100);
198 private static final Function
<StateIntervalContext
, ColorDefinition
> COLOR_MAPPING_FUNCTION
= ssCtx
-> {
200 int statusQuark
= ssCtx
.baseTreeElement
.getSourceQuark();
201 ITmfStateValue val
= ssCtx
.fullQueryAtIntervalStart
.get(statusQuark
).getStateValue();
207 int status
= val
.unboxInt();
209 case StateValues
.PROCESS_STATUS_WAIT_UNKNOWN
:
210 return COLOR_WAIT_UNKNOWN
;
211 case StateValues
.PROCESS_STATUS_WAIT_BLOCKED
:
212 return COLOR_WAIT_BLOCKED
;
213 case StateValues
.PROCESS_STATUS_WAIT_FOR_CPU
:
214 return COLOR_WAIT_FOR_CPU
;
215 case StateValues
.PROCESS_STATUS_RUN_USERMODE
:
216 return COLOR_USERMODE
;
217 case StateValues
.PROCESS_STATUS_RUN_SYSCALL
:
218 return COLOR_SYSCALL
;
219 case StateValues
.PROCESS_STATUS_INTERRUPTED
:
220 return COLOR_INTERRUPTED
;
222 return COLOR_UNKNOWN
;
225 } catch (StateValueTypeException e
) {
226 return COLOR_UNKNOWN
;
230 /* No variation for now */
231 private static final Function
<StateIntervalContext
, LineThickness
> LINE_THICKNESS_MAPPING_FUNCTION
= ssCtx
-> {
232 // int statusQuark = ssCtx.baseTreeElement.getSourceQuark();
233 // ITmfStateValue val = ssCtx.fullQueryAtIntervalStart.get(statusQuark).getStateValue();
235 // // For demo purposes only!
236 // if (val.equals(StateValues.PROCESS_STATUS_RUN_SYSCALL_VALUE)) {
237 // return LineThickness.SMALL;
240 return LineThickness
.NORMAL
;
244 private static final Function
<StateIntervalContext
, @Nullable Supplier
<Map
<String
, String
>>> PROPERTY_MAPPING_FUNCTION
= ssCtx
-> {
251 public ControlFlowRenderProvider() {
254 /* Parameters specific to state system render providers */
255 KernelAnalysisModule
.ID
,
256 SS_TO_TREE_RENDER_FUNCTION
,
257 STATE_NAME_MAPPING_FUNCTION
,
258 COLOR_MAPPING_FUNCTION
,
259 LINE_THICKNESS_MAPPING_FUNCTION
,
260 PROPERTY_MAPPING_FUNCTION
);