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