import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
-import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import org.eclipse.tracecompass.internal.lttng2.kernel.core.event.matching.TcpEventMatching;
import org.eclipse.tracecompass.internal.lttng2.kernel.core.event.matching.TcpLttngEventMatching;
IMatchProcessingUnit procUnit = (IMatchProcessingUnit) method.invoke(twoTraceMatch);
assertEquals(46, procUnit.countMatches());
- /* Verify unmatched incoming */
- Field fieldIn = twoTraceMatch.getClass().getDeclaredField("fUnmatchedIn");
- fieldIn.setAccessible(true);
- Map<?, ?> unmatched = (Map<?, ?> ) fieldIn.get(twoTraceMatch);
- Map<?, ?> unmatchedTrace = (Map<?, ?>) unmatched.get(trace1);
- assertEquals(3, unmatchedTrace.size());
- unmatchedTrace = (Map<?, ?>) unmatched.get(trace2);
- assertEquals(2, unmatchedTrace.size());
-
- /* Verify unmatched outgoing */
- Field fieldOut = twoTraceMatch.getClass().getDeclaredField("fUnmatchedOut");
- fieldOut.setAccessible(true);
- unmatched = (Map<?, ?> ) fieldOut.get(twoTraceMatch);
- unmatchedTrace = (Map<?, ?>) unmatched.get(trace1);
- assertEquals(2, unmatchedTrace.size());
- unmatchedTrace = (Map<?, ?>) unmatched.get(trace2);
- assertEquals(1, unmatchedTrace.size());
-
- } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException e) {
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
fail(e.getMessage());
}
package org.eclipse.tracecompass.internal.lttng2.kernel.core.event.matching;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Set;
import org.eclipse.tracecompass.internal.lttng2.kernel.core.TcpEventStrings;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
+import org.eclipse.tracecompass.tmf.core.event.matching.IEventMatchingKey;
import org.eclipse.tracecompass.tmf.core.event.matching.ITmfNetworkMatchDefinition;
+import org.eclipse.tracecompass.tmf.core.event.matching.TcpEventKey;
import org.eclipse.tracecompass.tmf.core.event.matching.TmfEventMatching.MatchingType;
import org.eclipse.tracecompass.tmf.core.event.matching.TmfNetworkEventMatching.Direction;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
return null;
}
- /**
- * The key to uniquely identify a TCP packet depends on many fields. This
- * method computes the key for a given event.
- *
- * @param event
- * The event for which to compute the key
- * @return the unique key for this event
- */
@Override
- public List<Object> getUniqueField(ITmfEvent event) {
- List<Object> keys = new ArrayList<>();
-
- keys.add(event.getContent().getField(TcpEventStrings.SEQ).getValue());
- keys.add(event.getContent().getField(TcpEventStrings.ACKSEQ).getValue());
- keys.add(event.getContent().getField(TcpEventStrings.FLAGS).getValue());
-
- return keys;
+ public IEventMatchingKey getEventKey(ITmfEvent event) {
+ IEventMatchingKey key = new TcpEventKey((long) event.getContent().getField(TcpEventStrings.SEQ).getValue(),
+ (long) event.getContent().getField(TcpEventStrings.ACKSEQ).getValue(),
+ (long) event.getContent().getField(TcpEventStrings.FLAGS).getValue());
+ return key;
}
@Override
package org.eclipse.tracecompass.internal.lttng2.kernel.core.event.matching;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Set;
import org.eclipse.tracecompass.internal.lttng2.kernel.core.TcpEventStrings;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
+import org.eclipse.tracecompass.tmf.core.event.matching.IEventMatchingKey;
import org.eclipse.tracecompass.tmf.core.event.matching.ITmfNetworkMatchDefinition;
+import org.eclipse.tracecompass.tmf.core.event.matching.TcpEventKey;
import org.eclipse.tracecompass.tmf.core.event.matching.TmfEventMatching.MatchingType;
import org.eclipse.tracecompass.tmf.core.event.matching.TmfNetworkEventMatching.Direction;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
return false;
}
- /**
- * The key to uniquely identify a TCP packet depends on many fields. This
- * method computes the key for a given event.
- *
- * @param event
- * The event for which to compute the key
- * @return the unique key for this event
- */
- @Override
- public List<Object> getUniqueField(ITmfEvent event) {
- List<Object> keys = new ArrayList<>();
-
- TmfEventField field = (TmfEventField) event.getContent();
- ITmfEventField data;
-
- data = field.getSubField(key_seq);
- if (data != null) {
- keys.add(data.getValue());
- }
- data = field.getSubField(key_ackseq);
- if (data != null) {
- keys.add(data.getValue());
- }
- data = field.getSubField(key_flags);
- if (data != null) {
- keys.add(data.getValue());
- }
-
- return keys;
- }
-
@Override
public boolean canMatchTrace(ITmfTrace trace) {
if (!(trace instanceof ITmfTraceWithPreDefinedEvents)) {
return types;
}
+ @Override
+ public IEventMatchingKey getEventKey(ITmfEvent event) {
+ TmfEventField field = (TmfEventField) event.getContent();
+ ITmfEventField data;
+
+ long seq = -1, ackseq = -1, flags = -1;
+ data = field.getSubField(key_seq);
+ if (data != null) {
+ seq = (long) data.getValue();
+ } else {
+ return null;
+ }
+ data = field.getSubField(key_ackseq);
+ if (data != null) {
+ ackseq = (long) data.getValue();
+ } else {
+ return null;
+ }
+ data = field.getSubField(key_flags);
+ if (data != null) {
+ flags = (long) data.getValue();
+ } else {
+ return null;
+ }
+
+ IEventMatchingKey key = new TcpEventKey(seq, ackseq, flags);
+
+ return key;
+ }
+
}
org.eclipse.tracecompass.tmf.core.uml2sd,
org.eclipse.tracecompass.tmf.core.util
Import-Package: com.google.common.base,
- com.google.common.collect
+ com.google.common.collect,
+ com.google.common.hash;version="15.0.0"
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ * Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.core.event.matching;
+
+/**
+ * Interface that classes describing event matching keys should implement. An
+ * event matching key is a key obtained from an event's data/fields and that
+ * will be used to match events together.
+ *
+ * If you implement this interface, make sure to consider implementing the
+ * {@link Object#hashCode()} and {@link Object#equals(Object)} as they will be
+ * used to match 2 keys together. Keys will come from different events and 2
+ * keys that are identical using the {@link Object#equals(Object)} method will
+ * create a match.
+ *
+ * @author Geneviève Bastien
+ */
+public interface IEventMatchingKey {
+
+}
package org.eclipse.tracecompass.tmf.core.event.matching;
-import java.util.List;
-
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.event.matching.TmfEventMatching.MatchingType;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
public interface ITmfMatchEventDefinition {
/**
- * Returns a list of values for an event that uniquely identifies this event
+ * Returns a key for an event that uniquely identifies this event and will
+ * match the key from another event.
*
* @param event
* The event for which to compute the key
* @return the unique key for this event
*/
- List<Object> getUniqueField(ITmfEvent event);
+ IEventMatchingKey getEventKey(ITmfEvent event);
/**
* Verifies whether a trace has all required events to match using this
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2014 É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
+ *
+ * Contributors:
+ * Geneviève Bastien - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.core.event.matching;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+import com.google.common.hash.HashFunction;
+import com.google.common.hash.Hashing;
+
+/**
+ * Traces can be matched using TCP network packets. To uniquely match a TCP
+ * packet from a trace with one from another trace, the three following fields
+ * are used: sequence number, acknowledgment number and the 16-bits following
+ * the acknowledgment number (data offset, reserved and flags).
+ *
+ * All match definitions using TCP fields should return a key of this type so
+ * all TCP matching methods are compatible.
+ *
+ * @author Geneviève Bastien
+ */
+@NonNullByDefault
+public class TcpEventKey implements IEventMatchingKey {
+
+ @SuppressWarnings("null")
+ private static final @NonNull HashFunction hf = Hashing.goodFastHash(32);
+ private final long fSeq;
+ private final long fAckseq;
+ private final long fFlags;
+
+ /**
+ * Constructor
+ *
+ * @param sequence
+ * The sequence number of the TCP packet
+ * @param ack
+ * The acknowledgement number of the TCP packet
+ * @param flags
+ * The 16 bits following the acknowledgment: data offset,
+ * reserved and flags)
+ */
+ public TcpEventKey(long sequence, long ack, long flags) {
+ fSeq = sequence;
+ fAckseq = ack;
+ fFlags = flags;
+ }
+
+ @Override
+ public int hashCode() {
+ return hf.newHasher()
+ .putLong(fSeq)
+ .putLong(fAckseq)
+ .putLong(fFlags).hash().asInt();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (o instanceof TcpEventKey) {
+ TcpEventKey key = (TcpEventKey) o;
+ return (key.fSeq == fSeq &&
+ key.fAckseq == fAckseq &&
+ key.fFlags == fFlags);
+ }
+ return false;
+ }
+}
package org.eclipse.tracecompass.tmf.core.event.matching;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+
/**
* This class matches events typically network-style, ie. where some events are
* 'send' events and the other 'receive' events or out/in events
/**
* Hashtables for unmatches incoming events
*/
- private final Map<ITmfTrace, Map<List<Object>, ITmfEvent>> fUnmatchedIn = new LinkedHashMap<>();
+ private final Table<ITmfTrace, IEventMatchingKey, ITmfEvent> fUnmatchedIn = HashBasedTable.create();
/**
* Hashtables for unmatches outgoing events
*/
- private final Map<ITmfTrace, Map<List<Object>, ITmfEvent>> fUnmatchedOut = new LinkedHashMap<>();
+ private final Table<ITmfTrace, IEventMatchingKey, ITmfEvent> fUnmatchedOut = HashBasedTable.create();
/**
* Enum for in and out types
// Initialize the matching infrastructure (unmatched event lists)
fUnmatchedIn.clear();
fUnmatchedOut.clear();
- for (ITmfTrace trace : getIndividualTraces()) {
- fUnmatchedIn.put(trace, new HashMap<List<Object>, ITmfEvent>());
- fUnmatchedOut.put(trace, new HashMap<List<Object>, ITmfEvent>());
- }
super.initMatching();
}
- /**
- * Function that counts the events in a hashtable.
- *
- * @param tbl
- * The table to count events for
- * @return The number of events
- */
- protected int countEvents(Map<List<Object>, ITmfEvent> tbl) {
- return tbl.size();
- }
-
@Override
protected MatchingType getMatchingType() {
return MatchingType.NETWORK;
}
/* Get the event's unique fields */
- List<Object> eventKey = def.getUniqueField(event);
- Map<ITmfTrace, Map<List<Object>, ITmfEvent>> unmatchedTbl, companionTbl;
+ IEventMatchingKey eventKey = def.getEventKey(event);
+
+ if (eventKey == null) {
+ return;
+ }
+ Table<ITmfTrace, IEventMatchingKey, ITmfEvent> unmatchedTbl, companionTbl;
/* Point to the appropriate table */
switch (evType) {
boolean found = false;
TmfEventDependency dep = null;
/* Search for the event in the companion table */
- for (Map<List<Object>, ITmfEvent> map : companionTbl.values()) {
- if (map.containsKey(eventKey)) {
+ for (ITmfTrace mTrace : getIndividualTraces()) {
+ if (companionTbl.contains(mTrace, eventKey)) {
found = true;
- ITmfEvent companionEvent = map.get(eventKey);
+ ITmfEvent companionEvent = companionTbl.get(mTrace, eventKey);
/* Remove the element from the companion table */
- map.remove(eventKey);
+ companionTbl.remove(mTrace, eventKey);
/* Create the dependency object */
switch (evType) {
* events as value for the unmatched table. Not necessary right now
* though
*/
- if (!unmatchedTbl.get(event.getTrace()).containsKey(eventKey)) {
- unmatchedTbl.get(event.getTrace()).put(eventKey, event);
+ if (!unmatchedTbl.contains(event.getTrace(), eventKey)) {
+ unmatchedTbl.put(event.getTrace(), eventKey, event);
}
}
int i = 0;
for (ITmfTrace trace : getIndividualTraces()) {
b.append("Trace " + i++ + ":" + cr +
- " " + countEvents(fUnmatchedIn.get(trace)) + " unmatched incoming events" + cr +
- " " + countEvents(fUnmatchedOut.get(trace)) + " unmatched outgoing events" + cr);
+ " " + fUnmatchedIn.row(trace).size() + " unmatched incoming events" + cr +
+ " " + fUnmatchedOut.row(trace).size() + " unmatched outgoing events" + cr);
}
return b.toString();