From b489a029a8762befe542695fa37df1cecd50f2e1 Mon Sep 17 00:00:00 2001 From: Alexandre Montplaisir Date: Wed, 11 Sep 2013 16:09:36 -0400 Subject: [PATCH] tmf: Tweaks to CallStackStateProvider - 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 Reviewed-on: https://git.eclipse.org/r/16393 Tested-by: Hudson CI Reviewed-by: Patrick Tasse IP-Clean: Patrick Tasse --- .../callstack/CallStackStateProvider.java | 83 +++++++++++++++---- .../tmf/core/callstack/Messages.java | 39 +++++++++ .../tmf/core/callstack/messages.properties | 13 +++ 3 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/Messages.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/messages.properties diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/CallStackStateProvider.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/CallStackStateProvider.java index cfc7f87abc..7284635fc9 100644 --- a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/CallStackStateProvider.java +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/CallStackStateProvider.java @@ -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 index 0000000000..6ad46425ed --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/Messages.java @@ -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 index 0000000000..4603be0526 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/callstack/messages.properties @@ -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. -- 2.34.1