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
index 825f98d1a1eadd596ad72a60810d26b15580444c..7159df876d35167379da355ece44bc32ba447bfe 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * 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
@@ -14,70 +14,93 @@ package org.eclipse.tracecompass.tmf.core.callstack;
 
 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
 
-import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
 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.exceptions.StateValueTypeException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
 import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 
 /**
  * The state provider for traces that support the Call Stack view.
  *
  * The attribute tree should have the following structure:
- *<pre>
+ *
+ * <pre>
  * (root)
- *   \-- Threads
- *        |-- (Thread 1)
- *        |    \-- CallStack (stack-attribute)
- *        |         |-- 1
- *        |         |-- 2
- *        |        ...
- *        |         \-- n
- *        |-- (Thread 2)
- *        |    \-- CallStack (stack-attribute)
- *        |         |-- 1
- *        |         |-- 2
- *        |        ...
- *        |         \-- n
- *       ...
- *        \-- (Thread n)
- *             \-- CallStack (stack-attribute)
- *                  |-- 1
- *                  |-- 2
- *                 ...
- *                  \-- n
- *</pre>
+ *   +-- Processes
+ *       +-- (PID 1000)
+ *       |    +-- (TID 1000)
+ *       |    |    +-- CallStack (stack-attribute)
+ *       |    |         +-- 1
+ *       |    |         +-- 2
+ *       |    |        ...
+ *       |    |         +-- n
+ *       |    +-- (TID 1001)
+ *       |         +-- CallStack (stack-attribute)
+ *       |              +-- 1
+ *       |              +-- 2
+ *       |             ...
+ *       |              +-- n
+ *       |
+ *       +-- (PID 2000)
+ *            +-- (TID 2000)
+ *                 +-- CallStack (stack-attribute)
+ *                      +-- 1
+ *                      +-- 2
+ *                     ...
+ *                      +-- n
+ * </pre>
+ *
  * where:
- * <br>
- * (Thread 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.
- * <br>
- * 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.
+ * <ul>
+ * <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 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>
+ * </ul>
  *
  * @author Patrick Tasse
  */
+@NonNullByDefault
 public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
 
-    /** Thread attribute */
-    public static final String THREADS = "Threads"; //$NON-NLS-1$
+    /**
+     * 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 function exit name */
-    public static final String UNDEFINED = "UNDEFINED"; //$NON-NLS-1$
+
+    /**
+     * Unknown process ID
+     *
+     * @since 2.0
+     */
+    public static final int UNKNOWN_PID = -1;
+
+    /**
+     * Unknown name
+     *
+     * @since 2.0
+     */
+    public static final String UNKNOWN = "UNKNOWN"; //$NON-NLS-1$
 
     /** CallStack state system ID */
-    private static final @NonNull 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$
+    private static final String ID = "org.eclipse.linuxtools.tmf.callstack"; //$NON-NLS-1$
 
     /**
      * Default constructor
@@ -85,7 +108,7 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
      * @param trace
      *            The trace for which we build this state system
      */
-    public CallStackStateProvider(@NonNull ITmfTrace trace) {
+    public CallStackStateProvider(ITmfTrace trace) {
         super(trace, ID);
     }
 
@@ -97,54 +120,69 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
 
         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();
-                String thread = getThreadName(event);
-                int threadQuark = ss.getQuarkAbsoluteAndAdd(THREADS, thread);
-                Long threadId = getThreadId(event);
-                if (threadId != null) {
-                    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();
-                String thread = getThreadName(event);
-                int quark = ss.getQuarkAbsoluteAndAdd(THREADS, 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 (TimeRangeException e) {
-            e.printStackTrace();
-        } catch (AttributeNotFoundException e) {
-            e.printStackTrace();
-        } catch (StateValueTypeException 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));
+            }
         }
     }
 
+    /**
+     * Restrict the return type for {@link ITmfStateProvider#getNewInstance}.
+     *
+     * @since 2.0
+     */
+    @Override
+    public abstract CallStackStateProvider getNewInstance();
+
     /**
      * Check if this event should be considered at all for function entry/exit
      * analysis. This check is only run once per event, before
@@ -163,38 +201,70 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
      *
      * @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 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 String functionExit(ITmfEvent event);
+    protected abstract @Nullable ITmfStateValue functionExit(ITmfEvent event);
 
     /**
-     * Return the thread name of a function entry or exit event.
+     * Return the process ID of a function entry event.
+     * <p>
+     * Use {@link #UNKNOWN_PID} if it is not known.
      *
      * @param event
      *            The event
-     * @return The thread name (as will be shown in the view)
+     * @return The process ID
+     * @since 2.0
      */
-    protected abstract String getThreadName(ITmfEvent 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 id, or null if undefined
+     * @return The thread id
+     * @since 2.0
+     */
+    protected abstract long getThreadId(ITmfEvent event);
+
+    /**
+     * 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) or null to use the
+     *         thread id formatted as a string
      */
-    protected Long getThreadId(ITmfEvent event) {
+    protected @Nullable String getThreadName(ITmfEvent event) {
+        /* Override to provide a thread name */
         return null;
     }
 }
This page took 0.027036 seconds and 5 git commands to generate.