tmf: Add a TmfTraceUtils class for advanced getter methods
[deliverable/tracecompass.git] / org.eclipse.tracecompass.lttng2.kernel.ui / src / org / eclipse / tracecompass / internal / lttng2 / kernel / ui / views / cpuusage / CpuUsageComposite.java
CommitLineData
dffc234f
GB
1/*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
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 * Contributors:
10 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
12
9bc60be7 13package org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.cpuusage;
dffc234f
GB
14
15import java.util.ArrayList;
e9a0d1cb 16import java.util.Collections;
dffc234f
GB
17import java.util.HashMap;
18import java.util.List;
19import java.util.Map;
20import java.util.Map.Entry;
21
e9a0d1cb 22import org.eclipse.jdt.annotation.NonNull;
dffc234f
GB
23import org.eclipse.jface.viewers.Viewer;
24import org.eclipse.jface.viewers.ViewerComparator;
dffc234f
GB
25import org.eclipse.osgi.util.NLS;
26import org.eclipse.swt.widgets.Composite;
9bc60be7 27import org.eclipse.tracecompass.internal.lttng2.kernel.core.Attributes;
42d5b5f2
AM
28import org.eclipse.tracecompass.lttng2.kernel.core.analysis.cpuusage.LttngKernelCpuUsageAnalysis;
29import org.eclipse.tracecompass.lttng2.kernel.core.analysis.kernel.LttngKernelAnalysis;
e894a508 30import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
1dd75589 31import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
e894a508
AM
32import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
33import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
34import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
35import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
2bdf0193
AM
36import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
37import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
b8585c7c 38import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
2bdf0193
AM
39import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
40import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeColumnDataProvider;
41import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeViewerEntry;
42import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeColumnData;
2bdf0193 43import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeColumnData.ITmfColumnPercentageProvider;
1dd75589 44import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeViewerEntry;
dffc234f
GB
45
46/**
47 * Tree viewer to display CPU usage information in a specified time range. It
48 * shows the process's TID, its name, the time spent on the CPU during that
49 * range, in % and absolute value.
50 *
51 * @author Geneviève Bastien
52 */
53public class CpuUsageComposite extends AbstractTmfTreeViewer {
54
d48661f2
GB
55 // Timeout between to wait for in the updateElements method
56 private static final long BUILD_UPDATE_TIMEOUT = 500;
57
dffc234f 58 private LttngKernelCpuUsageAnalysis fModule = null;
e9a0d1cb 59 private String fSelectedThread = null;
dffc234f
GB
60
61 private static final String[] COLUMN_NAMES = new String[] {
62 Messages.CpuUsageComposite_ColumnTID,
63 Messages.CpuUsageComposite_ColumnProcess,
64 Messages.CpuUsageComposite_ColumnPercent,
65 Messages.CpuUsageComposite_ColumnTime
66 };
67
68 /* A map that saves the mapping of a thread ID to its executable name */
69 private final Map<String, String> fProcessNameMap = new HashMap<>();
70
71 /** Provides label for the CPU usage tree viewer cells */
72 protected static class CpuLabelProvider extends TreeLabelProvider {
73
74 @Override
75 public String getColumnText(Object element, int columnIndex) {
76 CpuUsageEntry obj = (CpuUsageEntry) element;
77 if (columnIndex == 0) {
78 return obj.getTid();
79 } else if (columnIndex == 1) {
80 return obj.getProcessName();
81 } else if (columnIndex == 2) {
82 return String.format(Messages.CpuUsageComposite_TextPercent, obj.getPercent());
83 } else if (columnIndex == 3) {
84 return NLS.bind(Messages.CpuUsageComposite_TextTime, obj.getTime());
85 }
86
87 return element.toString();
88 }
89
90 }
91
92 /**
93 * Constructor
94 *
95 * @param parent
96 * The parent composite that holds this viewer
97 */
98 public CpuUsageComposite(Composite parent) {
99 super(parent, false);
100 setLabelProvider(new CpuLabelProvider());
101 }
102
103 @Override
104 protected ITmfTreeColumnDataProvider getColumnDataProvider() {
105 return new ITmfTreeColumnDataProvider() {
106
107 @Override
108 public List<TmfTreeColumnData> getColumnData() {
109 /* All columns are sortable */
110 List<TmfTreeColumnData> columns = new ArrayList<>();
111 TmfTreeColumnData column = new TmfTreeColumnData(COLUMN_NAMES[0]);
112 column.setComparator(new ViewerComparator() {
113 @Override
114 public int compare(Viewer viewer, Object e1, Object e2) {
115 CpuUsageEntry n1 = (CpuUsageEntry) e1;
116 CpuUsageEntry n2 = (CpuUsageEntry) e2;
117
118 return n1.getTid().compareTo(n2.getTid());
119
120 }
121 });
122 columns.add(column);
123 column = new TmfTreeColumnData(COLUMN_NAMES[1]);
124 column.setComparator(new ViewerComparator() {
125 @Override
126 public int compare(Viewer viewer, Object e1, Object e2) {
127 CpuUsageEntry n1 = (CpuUsageEntry) e1;
128 CpuUsageEntry n2 = (CpuUsageEntry) e2;
129
130 return n1.getProcessName().compareTo(n2.getProcessName());
131
132 }
133 });
134 columns.add(column);
135 column = new TmfTreeColumnData(COLUMN_NAMES[2]);
136 column.setComparator(new ViewerComparator() {
137 @Override
138 public int compare(Viewer viewer, Object e1, Object e2) {
139 CpuUsageEntry n1 = (CpuUsageEntry) e1;
140 CpuUsageEntry n2 = (CpuUsageEntry) e2;
141
142 return n1.getPercent().compareTo(n2.getPercent());
143
144 }
145 });
146 column.setPercentageProvider(new ITmfColumnPercentageProvider() {
147
148 @Override
149 public double getPercentage(Object data) {
150 CpuUsageEntry parent = (CpuUsageEntry) data;
151 return parent.getPercent() / 100;
152 }
153 });
154 columns.add(column);
155 column = new TmfTreeColumnData(COLUMN_NAMES[3]);
156 column.setComparator(new ViewerComparator() {
157 @Override
158 public int compare(Viewer viewer, Object e1, Object e2) {
159 CpuUsageEntry n1 = (CpuUsageEntry) e1;
160 CpuUsageEntry n2 = (CpuUsageEntry) e2;
161
162 return n1.getTime().compareTo(n2.getTime());
163
164 }
165 });
166 columns.add(column);
167
168 return columns;
169 }
170
171 };
172 }
173
174 // ------------------------------------------------------------------------
175 // Operations
176 // ------------------------------------------------------------------------
177
e9a0d1cb
GB
178 @Override
179 protected void contentChanged(ITmfTreeViewerEntry rootEntry) {
180 String selectedThread = fSelectedThread;
181 if (selectedThread != null) {
182 /* Find the selected thread among the inputs */
183 for (ITmfTreeViewerEntry entry : rootEntry.getChildren()) {
184 if (entry instanceof CpuUsageEntry) {
185 if (selectedThread.equals(((CpuUsageEntry) entry).getTid())) {
186 @SuppressWarnings("null")
187 @NonNull List<ITmfTreeViewerEntry> list = Collections.singletonList(entry);
188 super.setSelection(list);
189 return;
190 }
191 }
192 }
193 }
194 }
195
dffc234f
GB
196 @Override
197 public void initializeDataSource() {
b8585c7c 198 fModule = TmfTraceUtils.getAnalysisModuleOfClass(getTrace(), LttngKernelCpuUsageAnalysis.class, LttngKernelCpuUsageAnalysis.ID);
dffc234f
GB
199 if (fModule == null) {
200 return;
201 }
202 fModule.schedule();
203 fModule.waitForInitialization();
204 fProcessNameMap.clear();
205 }
206
207 @Override
208 protected ITmfTreeViewerEntry updateElements(long start, long end, boolean isSelection) {
209 if (isSelection || (start == end)) {
210 return null;
211 }
212 if (getTrace() == null || fModule == null) {
213 return null;
214 }
d48661f2 215 fModule.waitForInitialization();
dffc234f 216 ITmfStateSystem ss = fModule.getStateSystem();
dffc234f
GB
217 if (ss == null) {
218 return null;
219 }
220
d48661f2
GB
221 boolean complete = false;
222 long currentEnd = start;
223
224 while (!complete && currentEnd < end) {
225 complete = ss.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
226 currentEnd = ss.getCurrentEndTime();
227 }
228
dffc234f
GB
229 /* Initialize the data */
230 Map<String, Long> cpuUsageMap = fModule.getCpuUsageInRange(Math.max(start, getStartTime()), Math.min(end, getEndTime()));
231
232 TmfTreeViewerEntry root = new TmfTreeViewerEntry(""); //$NON-NLS-1$
233 List<ITmfTreeViewerEntry> entryList = root.getChildren();
234
235 for (Entry<String, Long> entry : cpuUsageMap.entrySet()) {
236 /*
237 * Process only entries representing the total of all CPUs and that
238 * have time on CPU
239 */
240 if (entry.getValue() == 0) {
241 continue;
242 }
243 if (!entry.getKey().startsWith(LttngKernelCpuUsageAnalysis.TOTAL)) {
244 continue;
245 }
246 String[] strings = entry.getKey().split(LttngKernelCpuUsageAnalysis.SPLIT_STRING, 2);
247
248 if ((strings.length > 1) && !(strings[1].equals(LttngKernelCpuUsageAnalysis.TID_ZERO))) {
249 CpuUsageEntry obj = new CpuUsageEntry(strings[1], getProcessName(strings[1]), (double) entry.getValue() / (double) (end - start) * 100, entry.getValue());
250 entryList.add(obj);
251 }
252 }
253
254 return root;
255 }
256
257 /*
258 * Get the process name from its TID by using the LTTng kernel analysis
259 * module
260 */
261 private String getProcessName(String tid) {
262 String execName = fProcessNameMap.get(tid);
263 if (execName != null) {
264 return execName;
265 }
72221aa4
AM
266 ITmfTrace trace = getTrace();
267 if (trace == null) {
dffc234f
GB
268 return tid;
269 }
42d5b5f2 270 ITmfStateSystem kernelSs = TmfStateSystemAnalysisModule.getStateSystem(trace, LttngKernelAnalysis.ID);
dffc234f
GB
271 if (kernelSs == null) {
272 return tid;
273 }
274
275 try {
276 int cpusNode = kernelSs.getQuarkAbsolute(Attributes.THREADS);
277
278 /* Get the quarks for each cpu */
279 List<Integer> cpuNodes = kernelSs.getSubAttributes(cpusNode, false);
280
281 for (Integer tidQuark : cpuNodes) {
282 if (kernelSs.getAttributeName(tidQuark).equals(tid)) {
283 int execNameQuark;
284 List<ITmfStateInterval> execNameIntervals;
285 try {
286 execNameQuark = kernelSs.getQuarkRelative(tidQuark, Attributes.EXEC_NAME);
1dd75589 287 execNameIntervals = StateSystemUtils.queryHistoryRange(kernelSs, execNameQuark, getStartTime(), getEndTime());
dffc234f
GB
288 } catch (AttributeNotFoundException e) {
289 /* No information on this thread (yet?), skip it for now */
290 continue;
291 } catch (StateSystemDisposedException e) {
292 /* State system is closing down, no point continuing */
293 break;
294 }
295
296 for (ITmfStateInterval execNameInterval : execNameIntervals) {
297 if (!execNameInterval.getStateValue().isNull() &&
298 execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
299 execName = execNameInterval.getStateValue().unboxStr();
300 fProcessNameMap.put(tid, execName);
301 return execName;
302 }
303 }
304 }
305 }
306
307 } catch (AttributeNotFoundException e) {
308 /* can't find the process name, just return the tid instead */
309 }
310 return tid;
311 }
312
e9a0d1cb
GB
313 /**
314 * Set the currently selected thread ID
315 *
316 * @param tid
317 * The selected thread ID
318 */
319 public void setSelectedThread(String tid) {
320 fSelectedThread = tid;
321 }
322
dffc234f 323}
This page took 0.048582 seconds and 5 git commands to generate.