os.linux: Move Attributes class to internal package
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.core / src / org / eclipse / tracecompass / analysis / os / linux / core / contextswitch / KernelContextSwitchAnalysis.java
1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
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 * Alexis Cabana-Loriaux - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.analysis.os.linux.core.contextswitch;
14
15 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23
24 import org.eclipse.jdt.annotation.NonNull;
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
28 import org.eclipse.tracecompass.analysis.os.linux.core.trace.DefaultEventLayout;
29 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
30 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
31 import org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator;
32 import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
33 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
34 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
35 import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
36 import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
37 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
38 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
39 import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
40 import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
41 import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
42 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
43 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
44
45 /**
46 * This analysis module computes the number of context switches of a system from
47 * a kernel trace.
48 *
49 * @author Alexis Cabana-Loriaux
50 * @since 2.0
51 */
52 @NonNullByDefault
53 public class KernelContextSwitchAnalysis extends TmfStateSystemAnalysisModule {
54
55 /** The ID of this analysis */
56 public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.contextswitch"; //$NON-NLS-1$
57
58 /** Integer used to identify 'total' entries in the returned maps */
59 public static final Integer TOTAL = -1;
60
61 @Override
62 protected ITmfStateProvider createStateProvider() {
63 ITmfTrace trace = checkNotNull(getTrace());
64 IKernelAnalysisEventLayout layout;
65
66 if (trace instanceof IKernelTrace) {
67 layout = ((IKernelTrace) trace).getKernelEventLayout();
68 } else {
69 /* Fall-back to the base LttngEventLayout */
70 layout = DefaultEventLayout.getInstance();
71 }
72
73 return new KernelContextSwitchStateProvider(trace, layout);
74 }
75
76 @Override
77 protected StateSystemBackendType getBackendType() {
78 return StateSystemBackendType.FULL;
79 }
80
81 @Override
82 protected Iterable<IAnalysisModule> getDependentAnalyses() {
83 Set<IAnalysisModule> modules = new HashSet<>();
84
85 ITmfTrace trace = getTrace();
86 if (trace == null) {
87 throw new IllegalStateException();
88 }
89 /*
90 * This analysis depends on the LTTng kernel analysis, so it's added to
91 * dependent modules.
92 */
93 Iterable<KernelAnalysisModule> kernelModules = TmfTraceUtils.getAnalysisModulesOfClass(trace, KernelAnalysisModule.class);
94 for (KernelAnalysisModule kernelModule : kernelModules) {
95 /* Only add the first one we find, if there is one */
96 modules.add(kernelModule);
97 break;
98 }
99 return modules;
100 }
101
102 /**
103 * Get a map of the number of context switch per CPU during a time range.
104 *
105 * @param startParam
106 * Start time of requested range
107 * @param endParam
108 * End time of requested range
109 * @return A map of CPU# -> nb of context switch in the [start, end]
110 * interval. CPU# == -1 represents the total number of context
111 * switch
112 * @throws TimeRangeException
113 * if one or more of the parameters is outside the range the
114 * state history
115 */
116 public @NonNullByDefault({}) @NonNull Map<Integer, Long> getContextSwitchesRange(final long startParam, final long endParam) {
117 final @Nullable ITmfStateSystem stateSystem = getStateSystem();
118 ITmfTrace trace = getTrace();
119 if (trace == null || stateSystem == null) {
120 return Collections.<Integer, Long> emptyMap();
121 }
122 long start = Math.max(startParam, stateSystem.getStartTime());
123 long end = Math.min(endParam, stateSystem.getCurrentEndTime());
124 ITmfStateSystem contextSwitchStateSystem = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelContextSwitchAnalysis.ID);
125 if (contextSwitchStateSystem == null) {
126 return Collections.<Integer, Long> emptyMap();
127 }
128
129 /*
130 * Make sure the start/end times are within the state history, so we
131 * don't get TimeRange exceptions.
132 */
133 long startTime = contextSwitchStateSystem.getStartTime();
134 long endTime = contextSwitchStateSystem.getCurrentEndTime();
135 if (endTime < startTime) {
136 return Collections.<Integer, Long> emptyMap();
137 }
138
139 Map<Integer, Long> map = new HashMap<>();
140 try {
141 /* Get the list of quarks for each CPU */
142 int cpusNode = contextSwitchStateSystem.getQuarkAbsolute(Attributes.CPUS);
143 List<Integer> cpuQuarks = contextSwitchStateSystem.getSubAttributes(cpusNode, false);
144 /* Query full states at start and end times */
145 List<ITmfStateInterval> kernelEndState = contextSwitchStateSystem.queryFullState(end);
146 List<ITmfStateInterval> kernelStartState = contextSwitchStateSystem.queryFullState(start);
147 Long totalNbCxtSwt = 0l;
148 for (Integer cpuQuark : cpuQuarks) {
149 int cpuNb = Integer.parseInt(contextSwitchStateSystem.getAttributeName(cpuQuark.intValue()));
150 Long nbCxtSwtForCore = kernelEndState.get(cpuQuark).getStateValue().unboxLong() - kernelStartState.get(cpuQuark).getStateValue().unboxLong();
151 map.put(cpuNb, nbCxtSwtForCore);
152 totalNbCxtSwt += nbCxtSwtForCore;
153 }
154
155 /* Put the total number of context switches in the interval */
156 map.put(TOTAL, totalNbCxtSwt);
157 } catch (TimeRangeException | AttributeNotFoundException e) {
158 /*
159 * Assume there is no events or the attribute does not exist yet,
160 * nothing will be put in the map.
161 */
162 } catch (StateValueTypeException | StateSystemDisposedException e) {
163 /*
164 * These other exception types would show a logic problem, so they
165 * should not happen.
166 */
167 Activator.getDefault().logError("Error getting CPU context switches in a time range", e); //$NON-NLS-1$
168 }
169
170 return map;
171 }
172
173 }
This page took 0.035779 seconds and 5 git commands to generate.