1 /**********************************************************************
2 * Copyright (c) 2016 Polytechnique de Montréal
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 package org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.ui
.views
.kernelmemoryusage
;
11 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
13 import java
.util
.ArrayList
;
14 import java
.util
.Collections
;
15 import java
.util
.HashMap
;
16 import java
.util
.List
;
19 import org
.eclipse
.jface
.viewers
.Viewer
;
20 import org
.eclipse
.jface
.viewers
.ViewerComparator
;
21 import org
.eclipse
.swt
.widgets
.Composite
;
22 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.KernelAnalysisModule
;
23 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.KernelThreadInformationProvider
;
24 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernelmemoryusage
.KernelMemoryAnalysisModule
;
25 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernelmemoryusage
.KernelMemoryStateProvider
;
26 import org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.ui
.Activator
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
29 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
35 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.tree
.AbstractTmfTreeViewer
;
36 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.tree
.ITmfTreeColumnDataProvider
;
37 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.tree
.ITmfTreeViewerEntry
;
38 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.tree
.TmfTreeColumnData
;
39 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.tree
.TmfTreeViewerEntry
;
42 * Tree viewer to select which process to display in the kernel memory usage
45 * @author Mahdi Zolnouri
46 * @author Wassim Nasrallah
47 * @author Najib Arbaoui
49 public class KernelMemoryUsageTreeViewer
extends AbstractTmfTreeViewer
{
51 private KernelMemoryAnalysisModule fModule
= null;
52 private String fSelectedThread
= null;
53 private static final String
[] COLUMN_NAMES
= new String
[] {
54 Messages
.KernelMemoryUsageComposite_ColumnTID
,
55 Messages
.KernelMemoryUsageComposite_ColumnProcess
58 /* A map that saves the mapping of a thread ID to its executable name */
59 private final Map
<String
, String
> fProcessNameMap
= new HashMap
<>();
61 /** Provides label for the Kernel memory usage tree viewer cells */
62 protected static class KernelMemoryLabelProvider
extends TreeLabelProvider
{
65 public String
getColumnText(Object element
, int columnIndex
) {
66 KernelMemoryUsageEntry obj
= (KernelMemoryUsageEntry
) element
;
67 if (columnIndex
== 0) {
69 } else if (columnIndex
== 1) {
70 return obj
.getProcessName();
72 return element
.toString();
80 * The parent composite that holds this viewer
82 public KernelMemoryUsageTreeViewer(Composite parent
) {
84 setLabelProvider(new KernelMemoryLabelProvider());
88 protected ITmfTreeColumnDataProvider
getColumnDataProvider() {
89 return new ITmfTreeColumnDataProvider() {
92 public List
<TmfTreeColumnData
> getColumnData() {
93 /* All columns are sortable */
94 List
<TmfTreeColumnData
> columns
= new ArrayList
<>();
95 TmfTreeColumnData column
= new TmfTreeColumnData(COLUMN_NAMES
[0]);
96 column
.setComparator(new ViewerComparator() {
98 public int compare(Viewer viewer
, Object e1
, Object e2
) {
99 KernelMemoryUsageEntry n1
= (KernelMemoryUsageEntry
) e1
;
100 KernelMemoryUsageEntry n2
= (KernelMemoryUsageEntry
) e2
;
102 return n1
.getTid().compareTo(n2
.getTid());
106 column
= new TmfTreeColumnData(COLUMN_NAMES
[1]);
107 column
.setComparator(new ViewerComparator() {
109 public int compare(Viewer viewer
, Object e1
, Object e2
) {
110 KernelMemoryUsageEntry n1
= (KernelMemoryUsageEntry
) e1
;
111 KernelMemoryUsageEntry n2
= (KernelMemoryUsageEntry
) e2
;
113 return n1
.getProcessName().compareTo(n2
.getProcessName());
122 // ------------------------------------------------------------------------
124 // ------------------------------------------------------------------------
127 protected void contentChanged(ITmfTreeViewerEntry rootEntry
) {
128 String selectedThread
= fSelectedThread
;
129 if (selectedThread
!= null) {
130 /* Find the selected thread among the inputs */
131 for (ITmfTreeViewerEntry entry
: rootEntry
.getChildren()) {
132 if (entry
instanceof KernelMemoryUsageEntry
) {
133 if (selectedThread
.equals(((KernelMemoryUsageEntry
) entry
).getTid())) {
134 List
<ITmfTreeViewerEntry
> list
= Collections
.singletonList(entry
);
135 super.setSelection(list
);
144 public void initializeDataSource() {
145 /* Should not be called while trace is still null */
146 ITmfTrace trace
= checkNotNull(getTrace());
148 fModule
= TmfTraceUtils
.getAnalysisModuleOfClass(trace
, KernelMemoryAnalysisModule
.class, KernelMemoryAnalysisModule
.ID
);
149 if (fModule
== null) {
153 fModule
.waitForInitialization();
154 fProcessNameMap
.clear();
158 protected ITmfTreeViewerEntry
updateElements(long start
, long end
, boolean isSelection
) {
159 if (isSelection
|| (start
== end
)) {
162 KernelMemoryAnalysisModule module
= fModule
;
163 if (getTrace() == null || module
== null) {
166 module
.waitForInitialization();
167 ITmfStateSystem ss
= module
.getStateSystem();
172 TmfTreeViewerEntry root
= new TmfTreeViewerEntry(""); //$NON-NLS-1$
173 List
<ITmfTreeViewerEntry
> entryList
= root
.getChildren();
176 long newStart
= Math
.max(start
, ss
.getStartTime());
177 long newEnd
= Math
.min(end
, ss
.getCurrentEndTime());
178 if (ss
.getStartTime() > newEnd
|| ss
.getCurrentEndTime() < start
) {
181 List
<ITmfStateInterval
> memoryStates
= ss
.queryFullState(newStart
);
182 List
<Integer
> threadQuarkList
= ss
.getSubAttributes(ITmfStateSystem
.ROOT_ATTRIBUTE
, false);
184 for (Integer threadQuark
: threadQuarkList
) {
185 ITmfStateInterval threadMemoryInterval
= memoryStates
.get(threadQuark
);
186 if (threadMemoryInterval
.getEndTime() < end
) {
187 String tid
= ss
.getAttributeName(threadQuark
);
188 String procname
= getProcessName(tid
);
189 KernelMemoryUsageEntry obj
= new KernelMemoryUsageEntry(tid
, procname
);
193 } catch (StateSystemDisposedException e
) {
194 Activator
.getDefault().logError(e
.getMessage(), e
);
200 * Get the process name from its TID by using the LTTng kernel analysis
203 private String
getProcessName(String tid
) {
204 String execName
= fProcessNameMap
.get(tid
);
205 if (execName
!= null) {
208 if (tid
.equals(KernelMemoryStateProvider
.OTHER_TID
)) {
209 fProcessNameMap
.put(tid
, tid
);
212 ITmfTrace trace
= checkNotNull(getTrace());
213 KernelAnalysisModule kernelModule
= TmfTraceUtils
.getAnalysisModuleOfClass(trace
, KernelAnalysisModule
.class, KernelAnalysisModule
.ID
);
214 if (kernelModule
== null) {
217 execName
= KernelThreadInformationProvider
.getExecutableName(kernelModule
, Integer
.parseInt(tid
));
218 if (execName
== null) {
221 fProcessNameMap
.put(tid
, execName
);
226 * Set the currently selected thread ID
229 * The selected thread ID
231 public void setSelectedThread(String tid
) {
232 fSelectedThread
= tid
;
237 public void traceSelected(TmfTraceSelectedSignal signal
) {
238 setSelectedThread(null);
239 super.traceSelected(signal
);
244 public void traceOpened(TmfTraceOpenedSignal signal
) {
245 setSelectedThread(null);
246 super.traceOpened(signal
);