blob: 9a4c2d24c8e4ceb017dcfa8cabc7765d15f97790 [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2018 Ericsson, École Polytechnique de Montréal
*
* 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
**********************************************************************/
package org.eclipse.tracecompass.incubator.internal.ros.core.analysis;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.incubator.internal.ros.core.trace.layout.IRosEventLayout;
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;
import org.eclipse.tracecompass.tmf.core.util.Pair;
import com.google.common.collect.Maps;
/**
* Base state provider for the ROS analyses
*
* @author Christophe Bedard
*/
public abstract class AbstractRosStateProvider extends AbstractTmfStateProvider implements IRosStateProviderInstantiator {
/** Timer scheduled */
public static final String TIMER_SCHEDULED = "scheduled"; //$NON-NLS-1$
/** Node subscribers */
public static final String SUBSCRIBERS_LIST = "Subscribers"; //$NON-NLS-1$
/** Node publishers */
public static final String PUBLISHERS_LIST = "Publishers"; //$NON-NLS-1$
/** Node callbacks */
public static final String CALLBACKS = "callbacks"; //$NON-NLS-1$
/** Subscriber callback for message processing */
public static final String SUBSCRIBER_MESSAGE_PROCESSING = "message processing"; //$NON-NLS-1$
/** Topic pub/sub Queue */
public static final String QUEUE = "queue"; //$NON-NLS-1$
/** Queue drops */
public static final String DROPS = "drops"; //$NON-NLS-1$
/** Topic name prefix */
public static final String TOPIC_PREFIX = "/"; //$NON-NLS-1$
private static final int UNKNOWN = -1;
private static final String UNKNOWN_NODE_NAME = "UNKNOWN_NODE"; //$NON-NLS-1$
/** The event layout */
protected final IRosEventLayout fLayout;
/**
* Map for pid -> (node_type, node_instance_name)
*/
private Map<Long, Pair<String, String>> fNodesNamesPid = Maps.newHashMap();
/**
* Constructor
*
* @param trace
* the trace
* @param id
* the ID of the corresponding analysis
*/
public AbstractRosStateProvider(ITmfTrace trace, @NonNull String id) {
super(checkNotNull(trace), id);
fLayout = IRosEventLayout.getDefault();
}
@Override
abstract public int getVersion();
@Override
public @NonNull ITmfStateProvider getNewInstance() {
return getNewRosStateProviderInstance(this.getClass(), getTrace());
}
/**
* Basic check to figure out if further processing should be done with an
* event
*
* @param event
* the event
* @return true if the event should be handled, false otherwise
*/
protected static boolean considerEvent(@NonNull ITmfEvent event) {
// Consider if the provider name matches
return event.getName().startsWith(IRosEventLayout.PROVIDER_NAME);
}
@Override
protected void eventHandle(@NonNull ITmfEvent event) {
// Get node name association from init_node event
if (isEvent(event, fLayout.eventInitNode())) {
// Add info to map for later
putNodeName(event);
}
}
// ------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------
/**
* Check if an event is of a given type
*
* @param event
* the event
* @param eventName
* the event name to check for
* @return true if the event is of the given type, false otherwise
*/
protected static boolean isEvent(@NonNull ITmfEvent event, @NonNull String eventName) {
return event.getName().equals(eventName);
}
/**
* Get field value from an event
*
* @param event
* the event
* @param fieldName
* the field name to get
* @return the value of the given field name
*/
protected static Object getField(@NonNull ITmfEvent event, @NonNull String fieldName) {
Object val = event.getContent().getFieldValue(Object.class, fieldName);
if (val == null) {
System.out.println("woops"); //$NON-NLS-1$
}
return val;
}
/**
* Add a pid -> (node_type, node_instance_name) association to the map for
* later use. This makes it possible to identify a node based on its PID.
*
* @param event
* the node_init event
*/
private void putNodeName(@NonNull ITmfEvent initEvent) {
/**
* For this event, the procname is the node type, and the instance name
* is available from the node_name field.
*/
fNodesNamesPid.put((Long) getField(initEvent, fLayout.contextVpid()),
new Pair<>((String) getField(initEvent, fLayout.contextProcname()),
(String) getField(initEvent, fLayout.fieldNodeName())));
}
/**
* Get the full node name an event is associated to
*
* @param event
* the event
* @return the full node name (format: node_type/node_instance_name)
*/
protected String getNodeName(@NonNull ITmfEvent event) {
@Nullable Pair<String, String> nodeNames = fNodesNamesPid.get(getField(event, fLayout.contextVpid()));
if (nodeNames == null) {
return UNKNOWN_NODE_NAME;
}
return nodeNames.getFirst() + nodeNames.getSecond();
}
/**
* Extract generic task name from full task name field
* <p>
* This is simply done by truncating everything starting from the first
* underscore found, since the procname/node name is appended to the generic
* task name with an underscore in ros::trace::task_init().
*
* @param fullTaskName
* the full task name field value
* @return the generic task name
*/
protected static String extractGenericTaskName(String fullTaskName) {
return StringUtils.substringBefore(fullTaskName, "_"); //$NON-NLS-1$
}
/**
* Get timer_added period time in nanoseconds
*
* @param event
* the event
* @return the period time in nanoseconds
*/
protected @NonNull Long getTimerPeriodInNs(@NonNull ITmfEvent event) {
Long sec = (Long) event.getContent().getField(fLayout.fieldPeriodSec()).getValue();
Long nSec = (Long) event.getContent().getField(fLayout.fieldPeriodNsec()).getValue();
return nSec + (sec * (long) Math.pow(10, 9));
}
/**
* @param event
* the event
* @return the procname
*/
protected String getProcname(@NonNull ITmfEvent event) {
return (String) event.getContent().getField(fLayout.contextProcname()).getValue();
}
/**
* @param event
* the event
* @return the vpid
*/
protected Long getProcessId(@NonNull ITmfEvent event) {
Long vpid = (Long) event.getContent().getField(fLayout.contextVpid()).getValue();
if (vpid == null) {
return (long) UNKNOWN;
}
return vpid;
}
/**
* Dec number to hex string format
*
* @param dec
* the base ten number
* @return the hex number as a string
*/
protected static String formatLongDecToHex(long dec) {
return "0x" + Long.toHexString(dec); //$NON-NLS-1$
}
}