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
.lttng
.scope
.lttng
.kernel
.core
.views
.timegraph
.threads
;
12 import static java
.util
.Objects
.requireNonNull
;
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
;
22 import org
.lttng
.scope
.lttng
.kernel
.core
.analysis
.os
.Attributes
;
23 import org
.lttng
.scope
.lttng
.kernel
.core
.analysis
.os
.KernelAnalysisModule
;
24 import org
.lttng
.scope
.tmf2
.views
.core
.timegraph
.model
.provider
.arrows
.ITimeGraphModelArrowProvider
;
25 import org
.lttng
.scope
.tmf2
.views
.core
.timegraph
.model
.provider
.states
.ITimeGraphModelStateProvider
;
26 import org
.lttng
.scope
.tmf2
.views
.core
.timegraph
.model
.provider
.statesystem
.StateSystemModelProvider
;
27 import org
.lttng
.scope
.tmf2
.views
.core
.timegraph
.model
.render
.tree
.TimeGraphTreeElement
;
28 import org
.lttng
.scope
.tmf2
.views
.core
.timegraph
.model
.render
.tree
.TimeGraphTreeRender
;
30 import com
.google
.common
.annotations
.VisibleForTesting
;
31 import com
.google
.common
.collect
.ImmutableList
;
33 import ca
.polymtl
.dorsal
.libdelorean
.ITmfStateSystem
;
34 import ca
.polymtl
.dorsal
.libdelorean
.StateSystemUtils
;
35 import ca
.polymtl
.dorsal
.libdelorean
.exceptions
.AttributeNotFoundException
;
36 import ca
.polymtl
.dorsal
.libdelorean
.interval
.ITmfStateInterval
;
38 public class ThreadsModelProvider
extends StateSystemModelProvider
{
40 private static final Supplier
<ITimeGraphModelStateProvider
> STATE_PROVIDER
= () -> {
41 return new ThreadsModelStateProvider();
44 private static final Supplier
<List
<ITimeGraphModelArrowProvider
>> ARROW_PROVIDERS
= () -> {
45 return ImmutableList
.of(
46 new ThreadsModelArrowProviderCpus()
50 private static final List
<SortingMode
> SORTING_MODES
= ImmutableList
.of(
51 ThreadsConfigModes
.SORTING_BY_TID
,
52 ThreadsConfigModes
.SORTING_BY_THREAD_NAME
);
54 private static final List
<FilterMode
> FILTER_MODES
= ImmutableList
.of(
55 ThreadsConfigModes
.FILTERING_INACTIVE_ENTRIES
);
57 // ------------------------------------------------------------------------
59 // ------------------------------------------------------------------------
62 * State values that are considered inactive, for purposes of filtering out
63 * when the "filter inactive entries" mode is enabled.
65 // private static final Set<ITmfStateValue> INACTIVE_STATE_VALUES = ImmutableSet.of(
66 // TmfStateValue.nullValue(),
67 // StateValues.PROCESS_STATUS_UNKNOWN_VALUE,
68 // StateValues.PROCESS_STATUS_WAIT_UNKNOWN_VALUE,
69 // StateValues.PROCESS_STATUS_WAIT_BLOCKED_VALUE
73 * Each "Thread" attribute has the following children:
77 * <li>System_call</li>
82 * The "Thread" is considered the base quark.
84 private static final String
[] BASE_QUARK_PATTERN
= { Attributes
.THREADS
, "*" }; //$NON-NLS-1$
87 * Get the tree element name for every thread. It consists of the TID
88 * followed by the first available exec_name for this thread.
90 * FIXME This implies a static tree definition for every TID, which does not
91 * handle TID re-use correctly. The state system structure should be updated
95 public static final Function
<TreeRenderContext
, TimeGraphTreeRender
> SS_TO_TREE_RENDER_FUNCTION
= (treeContext
) -> {
96 ITmfStateSystem ss
= treeContext
.ss
;
97 // List<ITmfStateInterval> fullState = treeContext.fullQueryAtRangeStart;
99 Stream
<ThreadsTreeElement
> treeElems
= ss
.getQuarks(BASE_QUARK_PATTERN
).stream()
101 String tid
= ss
.getAttributeName(baseQuark
);
105 int execNameQuark
= ss
.getQuarkRelative(baseQuark
, Attributes
.EXEC_NAME
);
106 // TODO We should look starting at
107 // treeContext.renderTimeRangeStart first, and if we
108 // don't find anything use ss.getStartTime(), so that we
109 // catch subsequent process name changes
110 ITmfStateInterval firstInterval
= StateSystemUtils
.queryUntilNonNullValue(ss
,
111 execNameQuark
, ss
.getStartTime(), Long
.MAX_VALUE
);
112 if (firstInterval
== null) {
115 threadName
= firstInterval
.getStateValue().unboxStr();
117 } catch (AttributeNotFoundException e
) {
121 return new ThreadsTreeElement(tid
, threadName
, Collections
.emptyList(), baseQuark
);
124 /* Run the entries through the active filter modes */
125 // Set<FilterMode> filterModes = treeContext.filterModes;
126 // if (filterModes.contains(ControlFlowConfigModes.FILTERING_INACTIVE_ENTRIES)) {
128 // * Filter out the tree elements whose state is considered inactive
129 // * for the whole duration of the configured time range.
131 // treeElems = treeElems.filter(elem -> {
132 // ITmfStateInterval interval = fullState.get(elem.getSourceQuark());
133 // if (interval.getEndTime() > treeContext.renderTimeRangeEnd &&
134 // INACTIVE_STATE_VALUES.contains(interval.getStateValue())) {
141 /* Sort entries according to the active sorting mode */
142 SortingMode sortingMode
= treeContext
.sortingMode
;
143 if (sortingMode
== ThreadsConfigModes
.SORTING_BY_TID
) {
144 treeElems
= treeElems
.sorted(Comparator
.comparingInt(ThreadsTreeElement
::getTid
));
145 } else if (sortingMode
== ThreadsConfigModes
.SORTING_BY_THREAD_NAME
) {
146 treeElems
= treeElems
.sorted((elem1
, elem2
) -> {
147 return elem1
.getThreadName().compareToIgnoreCase(elem2
.getThreadName());
151 List
<TimeGraphTreeElement
> treeElemsList
= treeElems
.collect(Collectors
.toList());
152 TimeGraphTreeElement rootElement
= new TimeGraphTreeElement(treeContext
.traceName
, treeElemsList
);
153 return new TimeGraphTreeRender(rootElement
);
159 public ThreadsModelProvider() {
160 super(requireNonNull(Messages
.threadsProviderName
),
163 STATE_PROVIDER
.get(),
164 ARROW_PROVIDERS
.get(),
165 /* Parameters specific to state system render providers */
166 KernelAnalysisModule
.ID
,
167 SS_TO_TREE_RENDER_FUNCTION
);