ss: Replace AttributeNotFoundException with IOOBE for quark parameters
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / callstack / CallStackStateProvider.java
1 /*******************************************************************************
2 * Copyright (c) 2013, 2016 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 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.tmf.core.callstack;
14
15 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.eclipse.osgi.util.NLS;
20 import org.eclipse.tracecompass.internal.tmf.core.Activator;
21 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
22 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
23 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
24 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
25 import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
26 import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
27 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
28
29 /**
30 * The state provider for traces that support the Call Stack view.
31 *
32 * The attribute tree should have the following structure:
33 *
34 * <pre>
35 * (root)
36 * +-- Processes
37 * +-- (PID 1000)
38 * | +-- (TID 1000)
39 * | | +-- CallStack (stack-attribute)
40 * | | +-- 1
41 * | | +-- 2
42 * | | ...
43 * | | +-- n
44 * | +-- (TID 1001)
45 * | +-- CallStack (stack-attribute)
46 * | +-- 1
47 * | +-- 2
48 * | ...
49 * | +-- n
50 * |
51 * +-- (PID 2000)
52 * +-- (TID 2000)
53 * +-- CallStack (stack-attribute)
54 * +-- 1
55 * +-- 2
56 * ...
57 * +-- n
58 * </pre>
59 *
60 * where:
61 * <ul>
62 * <li>(PID n) is an attribute whose name is the display name of the process.
63 * Optionally, its value can be an int representing the process id. Otherwise,
64 * the attribute name can be set to the process id formatted as a string.</li>
65 * <li>(TID n) is an attribute whose name is the display name of the thread.
66 * Optionally, its value can be a long representing the thread id. Otherwise,
67 * the attribute name can be set to the thread id formatted as a string.</li>
68 * <li>"CallStack" is a stack-attribute whose pushed values are either a string,
69 * int or long representing the function name or address in the call stack. The
70 * type of value used must be constant for a particular CallStack.</li>
71 * </ul>
72 *
73 * @author Patrick Tasse
74 */
75 @NonNullByDefault
76 public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
77
78 /**
79 * Thread attribute
80 *
81 * @since 2.0
82 */
83 public static final String PROCESSES = "Processes"; //$NON-NLS-1$
84
85 /** CallStack stack-attribute */
86 public static final String CALL_STACK = "CallStack"; //$NON-NLS-1$
87
88 /**
89 * Unknown process ID
90 *
91 * @since 2.0
92 */
93 public static final int UNKNOWN_PID = -1;
94
95 /**
96 * Unknown name
97 *
98 * @since 2.0
99 */
100 public static final String UNKNOWN = "UNKNOWN"; //$NON-NLS-1$
101
102 /** CallStack state system ID */
103 private static final String ID = "org.eclipse.linuxtools.tmf.callstack"; //$NON-NLS-1$
104
105 /**
106 * Default constructor
107 *
108 * @param trace
109 * The trace for which we build this state system
110 */
111 public CallStackStateProvider(ITmfTrace trace) {
112 super(trace, ID);
113 }
114
115 @Override
116 protected void eventHandle(ITmfEvent event) {
117 if (!considerEvent(event)) {
118 return;
119 }
120
121 ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
122
123 /* Check if the event is a function entry */
124 ITmfStateValue functionEntryName = functionEntry(event);
125 if (functionEntryName != null) {
126 long timestamp = event.getTimestamp().toNanos();
127
128 String processName = getProcessName(event);
129 int processId = getProcessId(event);
130 if (processName == null) {
131 processName = (processId == UNKNOWN_PID) ? UNKNOWN : Integer.toString(processId);
132 }
133 int processQuark = ss.getQuarkAbsoluteAndAdd(PROCESSES, processName);
134 ss.updateOngoingState(TmfStateValue.newValueInt(processId), processQuark);
135
136 String threadName = getThreadName(event);
137 long threadId = getThreadId(event);
138 if (threadName == null) {
139 threadName = Long.toString(threadId);
140 }
141 int threadQuark = ss.getQuarkRelativeAndAdd(processQuark, threadName);
142 ss.updateOngoingState(TmfStateValue.newValueLong(threadId), threadQuark);
143
144 int callStackQuark = ss.getQuarkRelativeAndAdd(threadQuark, CALL_STACK);
145 ITmfStateValue value = functionEntryName;
146 ss.pushAttribute(timestamp, value, callStackQuark);
147 return;
148 }
149
150 /* Check if the event is a function exit */
151 ITmfStateValue functionExitState = functionExit(event);
152 if (functionExitState != null) {
153 long timestamp = event.getTimestamp().toNanos();
154 String processName = getProcessName(event);
155 if (processName == null) {
156 int processId = getProcessId(event);
157 processName = (processId == UNKNOWN_PID) ? UNKNOWN : Integer.toString(processId);
158 }
159 String threadName = getThreadName(event);
160 if (threadName == null) {
161 threadName = Long.toString(getThreadId(event));
162 }
163 int quark = ss.getQuarkAbsoluteAndAdd(PROCESSES, processName, threadName, CALL_STACK);
164 ITmfStateValue poppedValue = ss.popAttribute(timestamp, quark);
165 /*
166 * Verify that the value we are popping matches the one in the
167 * event field, unless the latter is undefined.
168 */
169 if (!functionExitState.isNull() && !functionExitState.equals(poppedValue)) {
170 Activator.logWarning(NLS.bind(
171 Messages.CallStackStateProvider_UnmatchedPoppedValue,
172 functionExitState,
173 poppedValue));
174 }
175 }
176 }
177
178 /**
179 * Restrict the return type for {@link ITmfStateProvider#getNewInstance}.
180 *
181 * @since 2.0
182 */
183 @Override
184 public abstract CallStackStateProvider getNewInstance();
185
186 /**
187 * Check if this event should be considered at all for function entry/exit
188 * analysis. This check is only run once per event, before
189 * {@link #functionEntry} and {@link #functionExit} (to avoid repeating
190 * checks in those methods).
191 *
192 * @param event
193 * The event to check
194 * @return If false, the event will be ignored by the state provider. If
195 * true processing will continue.
196 */
197 protected abstract boolean considerEvent(ITmfEvent event);
198
199 /**
200 * Check an event if it indicates a function entry.
201 *
202 * @param event
203 * An event to check for function entry
204 * @return The state value representing the function being entered, or null
205 * if not a function entry
206 * @since 2.0
207 */
208 protected abstract @Nullable ITmfStateValue functionEntry(ITmfEvent event);
209
210 /**
211 * Check an event if it indicates a function exit.
212 *
213 * @param event
214 * An event to check for function exit
215 * @return The state value representing the function being exited, or
216 * TmfStateValue#nullValue() if the exited function is undefined,
217 * or null if not a function exit.
218 * @since 2.0
219 */
220 protected abstract @Nullable ITmfStateValue functionExit(ITmfEvent event);
221
222 /**
223 * Return the process ID of a function entry event.
224 * <p>
225 * Use {@link #UNKNOWN_PID} if it is not known.
226 *
227 * @param event
228 * The event
229 * @return The process ID
230 * @since 2.0
231 */
232 protected abstract int getProcessId(ITmfEvent event);
233
234 /**
235 * Return the process name of a function entry event.
236 *
237 * @param event
238 * The event
239 * @return The process name (as will be shown in the view) or null to use
240 * the process ID formatted as a string (or {@link #UNKNOWN})
241 * @since 2.0
242 */
243 protected @Nullable String getProcessName(ITmfEvent event) {
244 /* Override to provide a process name */
245 return null;
246 }
247
248 /**
249 * Return the thread id of a function entry event.
250 *
251 * @param event
252 * The event
253 * @return The thread id
254 * @since 2.0
255 */
256 protected abstract long getThreadId(ITmfEvent event);
257
258 /**
259 * Return the thread name of a function entry or exit event.
260 *
261 * @param event
262 * The event
263 * @return The thread name (as will be shown in the view) or null to use the
264 * thread id formatted as a string
265 */
266 protected @Nullable String getThreadName(ITmfEvent event) {
267 /* Override to provide a thread name */
268 return null;
269 }
270 }
This page took 0.037223 seconds and 5 git commands to generate.