tmf: Make process and thread names optional in call stack state provider
authorPatrick Tasse <patrick.tasse@gmail.com>
Mon, 2 May 2016 13:01:57 +0000 (09:01 -0400)
committerPatrick Tasse <patrick.tasse@gmail.com>
Tue, 17 May 2016 13:21:41 +0000 (09:21 -0400)
- Update call stack state provider to allow the optional specification
of the process name for an event.

- Make the specification of the thread name for an event optional.

- Use the process id (or UKNOWN) as attribute name if the process name
is unspecified.

- Use the thread id as attribute name if the thread name is unspecified.

- Store the process id as int state value of the process attribute in
the default state provider implementation.

- Update call stack view to use the process attribute's int state value
for the process id if available, otherwise try to use the attribute name
parsed as an int.

- Use the thread attribute's long state value for the thread id if
available, otherwise try to use the attribute name parsed as a long.

Change-Id: I91fc5d3eaebaaeed6f44009a1e2185a0bfe6a878
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/71824
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
lttng/org.eclipse.tracecompass.lttng2.ust.core.tests/src/org/eclipse/tracecompass/lttng2/ust/core/tests/callstack/AbstractProviderTest.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/callstack/LttngUstCallStackProvider.java
lttng/org.eclipse.tracecompass.lttng2.ust.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/ust/ui/swtbot/tests/CallStackViewTest.java
tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/callstack/CallStackStateProvider.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackView.java

index 05e379a940205e5caf34ab7dfb549b3497f7cc22..a50dcea7c8f5de55d113b818d3bb01f32fbc6045 100644 (file)
@@ -32,6 +32,7 @@ import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedE
 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
+import org.eclipse.tracecompass.tmf.core.callstack.CallStackStateProvider;
 import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
 import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
 import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
@@ -265,7 +266,8 @@ public abstract class AbstractProviderTest {
     /** Get the callstack for the given timestamp, for this particular trace */
     private static String[] getCallStack(ITmfStateSystem ss, int pid, String threadName, long timestamp) {
         try {
-            int stackAttribute = ss.getQuarkAbsolute("Processes", Integer.toString(pid), threadName, "CallStack");
+            String processName = (pid == CallStackStateProvider.UNKNOWN_PID) ? CallStackStateProvider.UNKNOWN : Integer.toString(pid);
+            int stackAttribute = ss.getQuarkAbsolute("Processes", processName, threadName, "CallStack");
             List<ITmfStateInterval> state = ss.queryFullState(timestamp);
             int depth = state.get(stackAttribute).getStateValue().unboxInt();
 
index 1ff8606ce69d5e4197e33d37d33b3079c008342f..3486465acdf7f6ab5e253c3724fe6cb07ddf769b 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
@@ -162,7 +162,7 @@ public class LttngUstCallStackProvider extends CallStackStateProvider {
         ITmfEventField content = event.getContent();
         ITmfEventField vpidContextField = content.getField(fLayout.contextVpid());
         if (vpidContextField == null) {
-            return UNDEFINED_PID;
+            return UNKNOWN_PID;
         }
         return ((Long) vpidContextField.getValue()).intValue();
     }
@@ -175,7 +175,7 @@ public class LttngUstCallStackProvider extends CallStackStateProvider {
     }
 
     @Override
-    public String getThreadName(ITmfEvent event) {
+    public @Nullable String getThreadName(ITmfEvent event) {
         /* We checked earlier that the "procname" context is present */
         ITmfEventField content = event.getContent();
         String procName = (String) content.getField(fLayout.contextProcname()).getValue();
index 1f4d225293d84d2687ee18bc64fcf085eab6d4ed..89cb7cc3d87f3573fa7bae1dc9b45cded8910665 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015 Ericsson
+ * Copyright (c) 2015, 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
@@ -189,7 +189,7 @@ public class CallStackViewTest {
     @Test
     public void testOpenCallstack() {
         String node = "glxgears-cyg-profile";
-        String pid = "-1";
+        String processName = "UNKNOWN";
         String childName = "glxgears-16073";
         List<String> expected = ImmutableList.of("0x40472b", "", "", "", "");
 
@@ -197,7 +197,7 @@ public class CallStackViewTest {
         viewBot.setFocus();
         final SWTBotView viewBot1 = viewBot;
         SWTBotTree tree = viewBot1.bot().tree();
-        SWTBotTreeItem treeItem = tree.getTreeItem(node).getNode(pid);
+        SWTBotTreeItem treeItem = tree.getTreeItem(node).getNode(processName);
         assertEquals(childName, treeItem.getNodes().get(0));
         List<String> names = treeItem.getNode(childName).getNodes();
         assertEquals(expected, names);
index f1e3dd133d433fbae28129c3898967bacdae56df..245876e50838c346fd0eb2d7caaada421f9e5922 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
@@ -60,11 +60,12 @@ import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
  *
  * 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>
@@ -86,14 +87,18 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
     public static final String CALL_STACK = "CallStack"; //$NON-NLS-1$
 
     /**
-     * Undefined process ID
+     * Unknown process ID
      *
      * @since 2.0
      */
-    protected static final int UNDEFINED_PID = -1;
+    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$
@@ -121,11 +126,21 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
             ITmfStateValue 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);
 
+                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);
+
+                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);
@@ -138,9 +153,16 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
             ITmfStateValue functionExitState = functionExit(event);
             if (functionExitState != 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);
+                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
@@ -205,8 +227,8 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
 
     /**
      * 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
@@ -215,6 +237,20 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
      */
     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.
      *
@@ -230,7 +266,11 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
      *
      * @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;
+    }
 }
index 7256c1c38cddaff2d66b96f3016908a9d821e052..a66943a1ecf7e26e87fcd97ce3645788c899b1c9 100644 (file)
@@ -577,40 +577,49 @@ public class CallStackView extends AbstractTimeGraphView {
                 traceEntry.updateEndTime(end);
             }
 
-            List<Integer> processQuarks = ss.getQuarks(module.getProcessesPattern());
-            for (int processQuark : processQuarks) {
-
-                /*
-                 * Default to trace entry, overwrite if a process entry exists.
-                 */
-                TimeGraphEntry threadParent = traceEntry;
-                int processId = -1;
-                if (processQuark != ITmfStateSystem.ROOT_ATTRIBUTE) {
-                    /* Create the entry for the process */
-                    ProcessEntry processEntry = processEntryMap.get(processQuark);
-                    if (processEntry == null) {
-                        String name = ss.getAttributeName(processQuark);
-                        /* The attribute name should already be parseable to integer */
-                        processId = Integer.parseInt(name);
-                        processEntry = new ProcessEntry(name, processId, start, end);
-                        processEntryMap.put(processQuark, processEntry);
-                        traceEntry.addChild(processEntry);
-                    } else {
-                        processEntry.updateEndTime(end);
+            try {
+                List<ITmfStateInterval> endStates = ss.queryFullState(ss.getCurrentEndTime());
+
+                List<Integer> processQuarks = ss.getQuarks(module.getProcessesPattern());
+                for (int processQuark : processQuarks) {
+
+                    /*
+                     * Default to trace entry, overwrite if a process entry exists.
+                     */
+                    TimeGraphEntry threadParent = traceEntry;
+                    int processId = -1;
+                    if (processQuark != ITmfStateSystem.ROOT_ATTRIBUTE) {
+                        /* Create the entry for the process */
+                        ProcessEntry processEntry = processEntryMap.get(processQuark);
+                        if (processEntry == null) {
+                            String processName = ss.getAttributeName(processQuark);
+                            ITmfStateValue processStateValue = endStates.get(processQuark).getStateValue();
+                            if (processStateValue.getType() == Type.INTEGER) {
+                                processId = processStateValue.unboxInt();
+                            } else {
+                                try {
+                                    processId = Integer.parseInt(processName);
+                                } catch (NumberFormatException e) {
+                                    /* use default processId */
+                                }
+                            }
+                            processEntry = new ProcessEntry(processName, processId, start, end);
+                            processEntryMap.put(processQuark, processEntry);
+                            traceEntry.addChild(processEntry);
+                        } else {
+                            processEntry.updateEndTime(end);
+                        }
+                        /* The parent of the thread entries will be a process */
+                        threadParent = processEntry;
                     }
-                    /* The parent of the thread entries will be a process */
-                    threadParent = processEntry;
-                }
 
-                /* Create the threads under the process */
-                try {
+                    /* Create the threads under the process */
                     List<Integer> threadQuarks = ss.getQuarks(processQuark, module.getThreadsPattern());
 
                     /*
                      * Only query startStates if necessary (threadEntry == null)
                      */
                     List<ITmfStateInterval> startStates = null;
-                    List<ITmfStateInterval> endStates = ss.queryFullState(ss.getCurrentEndTime());
                     for (int threadQuark : threadQuarks) {
                         if (monitor.isCanceled()) {
                             return;
@@ -634,7 +643,17 @@ public class CallStackView extends AbstractTimeGraphView {
                                 if (startStates == null) {
                                     startStates = ss.queryFullState(ss.getStartTime());
                                 }
-                                long threadId = endStates.get(threadQuark).getStateValue().unboxLong();
+                                long threadId = -1;
+                                ITmfStateValue threadStateValue = endStates.get(threadQuark).getStateValue();
+                                if (threadStateValue.getType() == Type.LONG || threadStateValue.getType() == Type.INTEGER) {
+                                    threadId = threadStateValue.unboxLong();
+                                } else {
+                                    try {
+                                        threadId = Long.parseLong(threadName);
+                                    } catch (NumberFormatException e) {
+                                        /* use default threadId */
+                                    }
+                                }
                                 long threadStart = start;
                                 ITmfStateInterval startInterval = startStates.get(callStackQuark);
                                 if (startInterval.getStateValue().isNull()) {
@@ -658,11 +677,11 @@ public class CallStackView extends AbstractTimeGraphView {
                             level++;
                         }
                     }
-                } catch (AttributeNotFoundException e) {
-                    Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
-                } catch (StateSystemDisposedException e) {
-                    /* Ignored */
                 }
+            } catch (AttributeNotFoundException e) {
+                Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
+            } catch (StateSystemDisposedException e) {
+                /* Ignored */
             }
 
             if (parentTrace == getTrace()) {
This page took 0.031018 seconds and 5 git commands to generate.