b671c7af2218fc4455bf3728e72c08cf155b81ac
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / callstack / CallStackStateProvider.java
1 /*******************************************************************************
2 * Copyright (c) 2013, 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 * 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.NonNull;
18 import org.eclipse.osgi.util.NLS;
19 import org.eclipse.tracecompass.internal.tmf.core.Activator;
20 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
21 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
22 import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
23 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
24 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
25 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
26 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
27 import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
28 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
29 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
30
31 /**
32 * The state provider for traces that support the Call Stack view.
33 *
34 * The attribute tree should have the following structure:
35 *<pre>
36 * (root)
37 * \-- Threads
38 * |-- (Thread 1)
39 * | \-- CallStack (stack-attribute)
40 * | |-- 1
41 * | |-- 2
42 * | ...
43 * | \-- n
44 * |-- (Thread 2)
45 * | \-- CallStack (stack-attribute)
46 * | |-- 1
47 * | |-- 2
48 * | ...
49 * | \-- n
50 * ...
51 * \-- (Thread n)
52 * \-- CallStack (stack-attribute)
53 * |-- 1
54 * |-- 2
55 * ...
56 * \-- n
57 *</pre>
58 * where:
59 * <br>
60 * (Thread n) is an attribute whose name is the display name of the thread.
61 * Optionally, its value is a long representing the thread id, used for sorting.
62 * <br>
63 * CallStack is a stack-attribute whose pushed values are either a string,
64 * int or long representing the function name or address in the call stack.
65 * The type of value used must be constant for a particular CallStack.
66 *
67 * @author Patrick Tasse
68 */
69 public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
70
71 /** Thread attribute */
72 public static final String THREADS = "Threads"; //$NON-NLS-1$
73 /** CallStack stack-attribute */
74 public static final String CALL_STACK = "CallStack"; //$NON-NLS-1$
75 /** Undefined function exit name */
76 public static final String UNDEFINED = "UNDEFINED"; //$NON-NLS-1$
77
78 /** CallStack state system ID */
79 private static final @NonNull String ID = "org.eclipse.linuxtools.tmf.callstack"; //$NON-NLS-1$
80 /** Dummy function name for when no function is expected */
81 private static final String NO_FUNCTION = "no function"; //$NON-NLS-1$
82
83 /**
84 * Default constructor
85 *
86 * @param trace
87 * The trace for which we build this state system
88 */
89 public CallStackStateProvider(@NonNull ITmfTrace trace) {
90 super(trace, ID);
91 }
92
93 @Override
94 protected void eventHandle(ITmfEvent event) {
95 if (!considerEvent(event)) {
96 return;
97 }
98
99 ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
100
101 try {
102 /* Check if the event is a function entry */
103 String functionEntryName = functionEntry(event);
104 if (functionEntryName != null) {
105 long timestamp = event.getTimestamp().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
106 String thread = getThreadName(event);
107 int threadQuark = ss.getQuarkAbsoluteAndAdd(THREADS, thread);
108 Long threadId = getThreadId(event);
109 if (threadId != null) {
110 ss.updateOngoingState(TmfStateValue.newValueLong(threadId), threadQuark);
111 }
112 int callStackQuark = ss.getQuarkRelativeAndAdd(threadQuark, CALL_STACK);
113 ITmfStateValue value = TmfStateValue.newValueString(functionEntryName);
114 ss.pushAttribute(timestamp, value, callStackQuark);
115 return;
116 }
117
118 /* Check if the event is a function exit */
119 String functionExitName = functionExit(event);
120 if (functionExitName != null) {
121 long timestamp = event.getTimestamp().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
122 String thread = getThreadName(event);
123 int quark = ss.getQuarkAbsoluteAndAdd(THREADS, thread, CALL_STACK);
124 ITmfStateValue poppedValue = ss.popAttribute(timestamp, quark);
125 String poppedName = (poppedValue == null ? NO_FUNCTION : poppedValue.unboxStr());
126
127 /*
128 * Verify that the value we are popping matches the one in the
129 * event field, unless the latter is undefined.
130 */
131 if (!functionExitName.equals(UNDEFINED) &&
132 !functionExitName.equals(poppedName)) {
133 Activator.logWarning(NLS.bind(
134 Messages.CallStackStateProvider_UnmatchedPoppedValue,
135 functionExitName,
136 poppedName));
137 }
138 }
139
140 } catch (TimeRangeException e) {
141 e.printStackTrace();
142 } catch (AttributeNotFoundException e) {
143 e.printStackTrace();
144 } catch (StateValueTypeException e) {
145 e.printStackTrace();
146 }
147 }
148
149 /**
150 * Check if this event should be considered at all for function entry/exit
151 * analysis. This check is only run once per event, before
152 * {@link #functionEntry} and {@link #functionExit} (to avoid repeating
153 * checks in those methods).
154 *
155 * @param event
156 * The event to check
157 * @return If false, the event will be ignored by the state provider. If
158 * true processing will continue.
159 */
160 protected abstract boolean considerEvent(ITmfEvent event);
161
162 /**
163 * Check an event if it indicates a function entry.
164 *
165 * @param event
166 * An event to check for function entry
167 * @return The function name of the function entry, or null if not a
168 * function entry.
169 */
170 protected abstract String functionEntry(ITmfEvent event);
171
172 /**
173 * Check an event if it indicates a function exit.
174 *
175 * @param event
176 * An event to check for function exit
177 * @return The function name, or UNDEFINED, for a function exit, or null if
178 * not a function exit.
179 */
180 protected abstract String functionExit(ITmfEvent event);
181
182 /**
183 * Return the thread name of a function entry or exit event.
184 *
185 * @param event
186 * The event
187 * @return The thread name (as will be shown in the view)
188 */
189 protected abstract String getThreadName(ITmfEvent event);
190
191 /**
192 * Return the thread id of a function entry event.
193 *
194 * @param event
195 * The event
196 * @return The thread id, or null if undefined
197 */
198 protected Long getThreadId(ITmfEvent event) {
199 return null;
200 }
201 }
This page took 0.035214 seconds and 4 git commands to generate.