/*******************************************************************************
- * Copyright (c) 2013, 2015 Ericsson
+ * Copyright (c) 2013, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
import org.eclipse.osgi.util.NLS;
import org.eclipse.tracecompass.internal.tmf.core.Activator;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
-import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
*
* where:
* <ul>
- * <li>(PID n) is an attribute name representing a unique process identifier.
- * </li>
+ * <li>(PID n) is an attribute whose name is the display name of the process.
+ * Optionally, its value can be an int representing the process id. Otherwise,
+ * the attribute name can be set to the process id formatted as a string.</li>
* <li>(TID n) is an attribute whose name is the display name of the thread.
- * Optionally, its value is a long representing the thread id, used for sorting.
- * </li>
+ * Optionally, its value can be a long representing the thread id. Otherwise,
+ * the attribute name can be set to the thread id formatted as a string.</li>
* <li>"CallStack" is a stack-attribute whose pushed values are either a string,
* int or long representing the function name or address in the call stack. The
* type of value used must be constant for a particular CallStack.</li>
@NonNullByDefault
public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
- /** Thread attribute
- * @since 2.0 */
+ /**
+ * Thread attribute
+ *
+ * @since 2.0
+ */
public static final String PROCESSES = "Processes"; //$NON-NLS-1$
/** CallStack stack-attribute */
public static final String CALL_STACK = "CallStack"; //$NON-NLS-1$
- /** Undefined process ID
- * @since 2.0 */
- protected static final int UNDEFINED_PID = -1;
+ /**
+ * Unknown process ID
+ *
+ * @since 2.0
+ */
+ public static final int UNKNOWN_PID = -1;
- /** Undefined function exit name */
- protected static final String UNDEFINED = "UNDEFINED"; //$NON-NLS-1$
+ /**
+ * Unknown name
+ *
+ * @since 2.0
+ */
+ public static final String UNKNOWN = "UNKNOWN"; //$NON-NLS-1$
/** CallStack state system ID */
private static final String ID = "org.eclipse.linuxtools.tmf.callstack"; //$NON-NLS-1$
- /** Dummy function name for when no function is expected */
- private static final String NO_FUNCTION = "no function"; //$NON-NLS-1$
-
/**
* Default constructor
*
ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
- try {
- /* Check if the event is a function entry */
- String functionEntryName = functionEntry(event);
- if (functionEntryName != null) {
- long timestamp = event.getTimestamp().toNanos();
- int pid = getProcessId(event);
- String threadName = getThreadName(event);
- int threadQuark = ss.getQuarkAbsoluteAndAdd(PROCESSES, Integer.toString(pid), threadName);
-
- long threadId = getThreadId(event);
- ss.updateOngoingState(TmfStateValue.newValueLong(threadId), threadQuark);
-
- int callStackQuark = ss.getQuarkRelativeAndAdd(threadQuark, CALL_STACK);
- ITmfStateValue value = TmfStateValue.newValueString(functionEntryName);
- ss.pushAttribute(timestamp, value, callStackQuark);
- return;
+ /* Check if the event is a function entry */
+ ITmfStateValue functionEntryName = functionEntry(event);
+ if (functionEntryName != null) {
+ long timestamp = event.getTimestamp().toNanos();
+
+ String processName = getProcessName(event);
+ int processId = getProcessId(event);
+ if (processName == null) {
+ processName = (processId == UNKNOWN_PID) ? UNKNOWN : Integer.toString(processId);
}
+ int processQuark = ss.getQuarkAbsoluteAndAdd(PROCESSES, processName);
+ ss.updateOngoingState(TmfStateValue.newValueInt(processId), processQuark);
- /* Check if the event is a function exit */
- String functionExitName = functionExit(event);
- if (functionExitName != null) {
- long timestamp = event.getTimestamp().toNanos();
- int pid = getProcessId(event);
- String thread = getThreadName(event);
- int quark = ss.getQuarkAbsoluteAndAdd(PROCESSES, Integer.toString(pid), thread, CALL_STACK);
- 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));
- }
+ String threadName = getThreadName(event);
+ long threadId = getThreadId(event);
+ if (threadName == null) {
+ threadName = Long.toString(threadId);
}
+ int threadQuark = ss.getQuarkRelativeAndAdd(processQuark, threadName);
+ ss.updateOngoingState(TmfStateValue.newValueLong(threadId), threadQuark);
+
+ int callStackQuark = ss.getQuarkRelativeAndAdd(threadQuark, CALL_STACK);
+ ITmfStateValue value = functionEntryName;
+ ss.pushAttribute(timestamp, value, callStackQuark);
+ return;
+ }
- } catch (AttributeNotFoundException e) {
- e.printStackTrace();
+ /* Check if the event is a function exit */
+ ITmfStateValue functionExitState = functionExit(event);
+ if (functionExitState != null) {
+ long timestamp = event.getTimestamp().toNanos();
+ String processName = getProcessName(event);
+ if (processName == null) {
+ int processId = getProcessId(event);
+ processName = (processId == UNKNOWN_PID) ? UNKNOWN : Integer.toString(processId);
+ }
+ String threadName = getThreadName(event);
+ if (threadName == null) {
+ threadName = Long.toString(getThreadId(event));
+ }
+ int quark = ss.getQuarkAbsoluteAndAdd(PROCESSES, processName, threadName, CALL_STACK);
+ ITmfStateValue poppedValue = ss.popAttribute(timestamp, quark);
+ /*
+ * Verify that the value we are popping matches the one in the
+ * event field, unless the latter is undefined.
+ */
+ if (!functionExitState.isNull() && !functionExitState.equals(poppedValue)) {
+ Activator.logWarning(NLS.bind(
+ Messages.CallStackStateProvider_UnmatchedPoppedValue,
+ functionExitState,
+ poppedValue));
+ }
}
}
*
* @param event
* An event to check for function entry
- * @return The function name of the function entry, or null if not a
- * function entry.
+ * @return The state value representing the function being entered, or null
+ * if not a function entry
+ * @since 2.0
*/
- protected abstract @Nullable String functionEntry(ITmfEvent event);
+ protected abstract @Nullable ITmfStateValue 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.
+ * @return The state value representing the function being exited, or
+ * TmfStateValue#nullValue() if the exited function is undefined,
+ * or null if not a function exit.
+ * @since 2.0
*/
- protected abstract @Nullable String functionExit(ITmfEvent event);
+ protected abstract @Nullable ITmfStateValue functionExit(ITmfEvent event);
/**
* Return the process ID of a function entry event.
- *
- * Use {@link #UNDEFINED_PID} if it is not known.
+ * <p>
+ * Use {@link #UNKNOWN_PID} if it is not known.
*
* @param event
* The event
*/
protected abstract int getProcessId(ITmfEvent event);
+ /**
+ * Return the process name of a function entry event.
+ *
+ * @param event
+ * The event
+ * @return The process name (as will be shown in the view) or null to use
+ * the process ID formatted as a string (or {@link #UNKNOWN})
+ * @since 2.0
+ */
+ protected @Nullable String getProcessName(ITmfEvent event) {
+ /* Override to provide a process name */
+ return null;
+ }
+
/**
* Return the thread id of a function entry event.
*
*
* @param event
* The event
- * @return The thread name (as will be shown in the view)
+ * @return The thread name (as will be shown in the view) or null to use the
+ * thread id formatted as a string
*/
- protected abstract String getThreadName(ITmfEvent event);
+ protected @Nullable String getThreadName(ITmfEvent event) {
+ /* Override to provide a thread name */
+ return null;
+ }
}