package org.eclipse.linuxtools.tmf.core.callstack;
+import org.eclipse.linuxtools.internal.tmf.core.Activator;
import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
+import org.eclipse.osgi.util.NLS;
/**
* The state provider for traces that support the Call Stack view.
/** Undefined function exit name */
public static final String UNDEFINED = "UNDEFINED"; //$NON-NLS-1$
+ /** Dummy function name for when no function is expected */
+ private static final String NO_FUNCTION = "no function"; //$NON-NLS-1$
+
/**
* Version number of this state provider. Please bump this if you modify
* the contents of the generated state history in some way.
@Override
protected void eventHandle(ITmfEvent event) {
- String functionEntryName = functionEntry(event);
+ if (!considerEvent(event)) {
+ return;
+ }
try {
+ /* Check if the event is a function entry */
+ String functionEntryName = functionEntry(event);
if (functionEntryName != null) {
long timestamp = event.getTimestamp().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- String thread = threadName(event);
+ String thread = getThreadName(event);
int quark = ss.getQuarkAbsoluteAndAdd(THREADS, thread, CALL_STACK);
ITmfStateValue value = TmfStateValue.newValueString(functionEntryName);
ss.pushAttribute(timestamp, value, quark);
- } else if (functionExit(event) != null) {
+ return;
+ }
+
+ /* Check if the event is a function exit */
+ String functionExitName = functionExit(event);
+ if (functionExitName != null) {
long timestamp = event.getTimestamp().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
- String thread = threadName(event);
+ String thread = getThreadName(event);
int quark = ss.getQuarkAbsoluteAndAdd(THREADS, thread, CALL_STACK);
- ss.popAttribute(timestamp, quark);
+ ITmfStateValue poppedValue = ss.popAttribute(timestamp, quark);
+ String poppedName = (poppedValue == null ? NO_FUNCTION : poppedValue.unboxStr());
+
+ /*
+ * Verify that the value we are popping matches the one in the
+ * event field, unless the latter is undefined.
+ */
+ if (!functionExitName.equals(UNDEFINED) &&
+ !functionExitName.equals(poppedName)) {
+ Activator.logWarning(NLS.bind(
+ Messages.CallStackStateProvider_UnmatchedPoppedValue,
+ functionExitName,
+ poppedName));
+ }
}
+
} catch (TimeRangeException e) {
e.printStackTrace();
} catch (AttributeNotFoundException e) {
}
/**
- * Check an event for function entry
- * @param event an event to check for function entry
- * @return the function name for a function entry, or null otherwise.
+ * Check if this event should be considered at all for function entry/exit
+ * analysis. This check is only run once per event, before
+ * {@link #functionEntry} and {@link #functionExit} (to avoid repeating
+ * checks in those methods).
+ *
+ * @param event
+ * The event to check
+ * @return If false, the event will be ignored by the state provider. If
+ * true processing will continue.
*/
- public abstract String functionEntry(ITmfEvent event);
+ protected abstract boolean considerEvent(ITmfEvent event);
/**
- * Check an event for function exit
- * @param event an event to check for function exit
- * @return the function name or UNDEFINED for a function exit, or null otherwise.
+ * Check an event if it indicates a function entry.
+ *
+ * @param event
+ * An event to check for function entry
+ * @return The function name of the function entry, or null if not a
+ * function entry.
+ */
+ protected abstract String functionEntry(ITmfEvent event);
+
+ /**
+ * Check an event if it indicates a function exit.
+ *
+ * @param event
+ * An event to check for function exit
+ * @return The function name, or UNDEFINED, for a function exit, or null if
+ * not a function exit.
*/
- public abstract String functionExit(ITmfEvent event);
+ protected abstract String functionExit(ITmfEvent event);
/**
- * Return the thread name for a function entry or exit event
- * @param event an event
- * @return the thread name
+ * Return the thread name of a function entry or exit event.
+ *
+ * @param event
+ * The event
+ * @return The thread name (as will be shown in the view)
*/
- public abstract String threadName(ITmfEvent event);
+ protected abstract String getThreadName(ITmfEvent event);
}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2013 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alexandre Montplaisir - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.core.callstack;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Message bundle for the call stack state provider.
+ *
+ * @since 2.1
+ */
+public class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.eclipse.linuxtools.tmf.core.callstack"; //$NON-NLS-1$
+
+ /**
+ * The value popped from a 'func_exit' event doesn't match the current
+ * function name.
+ */
+ public static String CallStackStateProvider_UnmatchedPoppedValue;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}