ss: Move plugins to Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / callstack / CallStackStateProvider.java
index d7f08cef087b9dfb9676e5a85b22d07463c637c5..54f02e3eac2c112fcf6b2cd80a6f95c9e79ba6be 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013 Ericsson
+ * Copyright (c) 2013, 2014 Ericsson
  *
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
 
 package org.eclipse.linuxtools.tmf.core.callstack;
 
+import org.eclipse.linuxtools.internal.tmf.core.Activator;
+import org.eclipse.linuxtools.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.StateValueTypeException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.TimeRangeException;
+import org.eclipse.linuxtools.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.linuxtools.statesystem.core.statevalue.TmfStateValue;
 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.exceptions.TimeRangeException;
-import org.eclipse.linuxtools.tmf.core.statesystem.AbstractStateChangeInput;
-import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
-import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
+import org.eclipse.linuxtools.tmf.core.statesystem.AbstractTmfStateProvider;
 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.
@@ -51,7 +53,8 @@ import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
  *</pre>
  * where:
  * <br>
- * (Thread n) is an attribute whose name is the name of the thread
+ * (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.
@@ -60,10 +63,8 @@ import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
  * @author Patrick Tasse
  * @since 2.0
  */
-public abstract class CallStackStateProvider extends AbstractStateChangeInput {
+public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
 
-    /** CallStack state system ID */
-    public static final String ID = "org.eclipse.linuxtools.tmf.callstack"; //$NON-NLS-1$
     /** Thread attribute */
     public static final String THREADS = "Threads"; //$NON-NLS-1$
     /** CallStack stack-attribute */
@@ -71,11 +72,10 @@ public abstract class CallStackStateProvider extends AbstractStateChangeInput {
     /** Undefined function exit name */
     public static final String UNDEFINED = "UNDEFINED"; //$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.
-     */
-    private static final int VERSION = 0;
+    /** 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
@@ -87,27 +87,50 @@ public abstract class CallStackStateProvider extends AbstractStateChangeInput {
         super(trace, ITmfEvent.class, ID);
     }
 
-    @Override
-    public int getVersion() {
-        return VERSION;
-    }
-
     @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);
-                int quark = ss.getQuarkAbsoluteAndAdd(THREADS, thread, CALL_STACK);
+                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, quark);
-            } else if (functionExit(event) != null) {
+                ss.pushAttribute(timestamp, value, callStackQuark);
+                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) {
@@ -118,23 +141,58 @@ public abstract class CallStackStateProvider extends AbstractStateChangeInput {
     }
 
     /**
-     * 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.
+     * @since 3.0
+     */
+    protected abstract boolean considerEvent(ITmfEvent event);
+
+    /**
+     * 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 functionEntry(ITmfEvent event);
+    protected abstract String functionExit(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.
+     * 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)
+     * @since 3.0
      */
-    public abstract String functionExit(ITmfEvent event);
+    protected abstract String getThreadName(ITmfEvent event);
 
     /**
-     * Return the thread name for a function entry or exit event
-     * @param event an event
-     * @return the thread name
+     * Return the thread id of a function entry event.
+     *
+     * @param event
+     *            The event
+     * @return The thread id, or null if undefined
+     * @since 3.1
      */
-    public abstract String threadName(ITmfEvent event);
+    protected Long getThreadId(ITmfEvent event) {
+        return null;
+    }
 }
This page took 0.027339 seconds and 5 git commands to generate.