tmf: Introduce the notion of PID to the Callstack analysis
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / callstack / CallStackStateProvider.java
index 825f98d1a1eadd596ad72a60810d26b15580444c..1eed618d9290ee701409c459085282878ed38368 100644 (file)
@@ -14,68 +14,84 @@ 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.
+ * <ul>
+ * <li>(PID n) is an attribute name representing a unique process identifier.
+ * </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.
- * <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.
+ * </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 process ID
+     * @since 2.0 */
+    protected static final int UNDEFINED_PID = -1;
+
     /** Undefined function exit name */
-    public static final String UNDEFINED = "UNDEFINED"; //$NON-NLS-1$
+    protected static final String UNDEFINED = "UNDEFINED"; //$NON-NLS-1$
 
     /** CallStack state system ID */
-    private static final @NonNull String ID = "org.eclipse.linuxtools.tmf.callstack"; //$NON-NLS-1$
+    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$
 
@@ -85,7 +101,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);
     }
 
@@ -102,12 +118,13 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
             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 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);
@@ -118,8 +135,9 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
             String functionExitName = functionExit(event);
             if (functionExitName != null) {
                 long timestamp = event.getTimestamp().toNanos();
+                int pid = getProcessId(event);
                 String thread = getThreadName(event);
-                int quark = ss.getQuarkAbsoluteAndAdd(THREADS, thread, CALL_STACK);
+                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());
 
@@ -136,15 +154,19 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
                 }
             }
 
-        } catch (TimeRangeException e) {
-            e.printStackTrace();
         } catch (AttributeNotFoundException e) {
             e.printStackTrace();
-        } catch (StateValueTypeException e) {
-            e.printStackTrace();
         }
     }
 
+    /**
+     * 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
@@ -166,7 +188,7 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
      * @return The function name of the function entry, or null if not a
      *         function entry.
      */
-    protected abstract String functionEntry(ITmfEvent event);
+    protected abstract @Nullable String functionEntry(ITmfEvent event);
 
     /**
      * Check an event if it indicates a function exit.
@@ -176,25 +198,36 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
      * @return The function name, or UNDEFINED, for a function exit, or null if
      *         not a function exit.
      */
-    protected abstract String functionExit(ITmfEvent event);
+    protected abstract @Nullable String functionExit(ITmfEvent event);
 
     /**
-     * Return the thread name of a function entry or exit event.
+     * Return the process ID of a function entry event.
+     *
+     * Use {@link #UNDEFINED_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 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 Long getThreadId(ITmfEvent event) {
-        return null;
-    }
+    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)
+     */
+    protected abstract String getThreadName(ITmfEvent event);
 }
This page took 0.036976 seconds and 5 git commands to generate.