tmf: Tweaks to CallStackStateProvider
authorAlexandre Montplaisir <alexmonthy@voxpopuli.im>
Wed, 11 Sep 2013 20:09:36 +0000 (16:09 -0400)
committerAlexandre Montplaisir <alexmonthy@voxpopuli.im>
Tue, 17 Sep 2013 22:18:20 +0000 (18:18 -0400)
- Add a considerEvent() method to put all checks in. This avoids
  running checks more than once per event.
- Make the abstract methods protected instead, they should not be called
  by external components.
- Add a check when popping state values if func_exit names are available.
  This makes sure the value matches the current function we are in. If it
  doesn't, log a warning in the error log. This will most definitely happen
  if there are lost events in the trace.

Change-Id: I1f2014486768c9317cbddb9556faf3e061f130b0
Signed-off-by: Alexandre Montplaisir <alexmonthy@voxpopuli.im>
Reviewed-on: https://git.eclipse.org/r/16393
Tested-by: Hudson CI
Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com>
IP-Clean: Patrick Tasse <patrick.tasse@gmail.com>

org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/CallStackStateProvider.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/Messages.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/messages.properties [new file with mode: 0644]

index cfc7f87abc62f2e069a016b51e48a62a892738f1..7284635fc9649310c4010402162ad02db719a92f 100644 (file)
@@ -12,6 +12,7 @@
 
 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;
@@ -21,6 +22,7 @@ import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
 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.
@@ -71,6 +73,9 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
     /** 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.
@@ -94,20 +99,43 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
 
     @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) {
@@ -118,23 +146,44 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
     }
 
     /**
-     * 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);
 }
diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/Messages.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/Messages.java
new file mode 100644 (file)
index 0000000..6ad4642
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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() {
+    }
+}
diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/messages.properties b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/messages.properties
new file mode 100644 (file)
index 0000000..4603be0
--- /dev/null
@@ -0,0 +1,13 @@
+###############################################################################
+# 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
+###############################################################################
+
+CallStackStateProvider_UnmatchedPoppedValue=Function exit name in event ({0}) different from the expected one ({1}). You may have lost events in your trace.
This page took 0.109133 seconds and 5 git commands to generate.