X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=org.eclipse.linuxtools.ctf.core%2Fsrc%2Forg%2Feclipse%2Flinuxtools%2Fctf%2Fcore%2Ftrace%2FCTFTrace.java;h=7bb19730fe8c4cce8279e57f40084e4d402a2337;hb=ab04fc6bc48d6ebda9c00071b8e4f3077421e01e;hp=91fcd596ecb2e3ff7865a22a1b281487134b0718;hpb=be6df2d87acd929898f722acd76a5d2b79079959;p=deliverable%2Ftracecompass.git
diff --git a/org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/trace/CTFTrace.java b/org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/trace/CTFTrace.java
index 91fcd596ec..7bb19730fe 100644
--- a/org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/trace/CTFTrace.java
+++ b/org.eclipse.linuxtools.ctf.core/src/org/eclipse/linuxtools/ctf/core/trace/CTFTrace.java
@@ -1,13 +1,15 @@
/*******************************************************************************
- * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
+ * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
*
* 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: Matthew Khouzam - Initial API and implementation
- * Contributors: Alexandre Montplaisir - Initial API and implementation
+ * Contributors:
+ * Matthew Khouzam - Initial API and implementation
+ * Alexandre Montplaisir - Initial API and implementation
+ * Simon Delisle - Replace LinkedList by TreeSet in callsitesByName attribute
*******************************************************************************/
package org.eclipse.linuxtools.ctf.core.trace;
@@ -22,6 +24,7 @@ import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
@@ -30,27 +33,26 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.TreeSet;
import java.util.UUID;
+import org.eclipse.linuxtools.ctf.core.event.CTFCallsite;
import org.eclipse.linuxtools.ctf.core.event.CTFClock;
-import org.eclipse.linuxtools.ctf.core.event.EventDeclaration;
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
+import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
+import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
-import org.eclipse.linuxtools.internal.ctf.core.Activator;
-import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.event.CTFCallsiteComparator;
import org.eclipse.linuxtools.internal.ctf.core.event.metadata.exceptions.ParseException;
-import org.eclipse.linuxtools.internal.ctf.core.trace.Stream;
-import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInput;
-import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndex;
/**
- * CTFTrace
- *
+ * A CTF trace on the file system.
+ *
* Represents a trace on the filesystem. It is responsible of parsing the
* metadata, creating declarations data structures, indexing the event packets
* (in other words, all the work that can be shared between readers), but the
@@ -59,59 +61,50 @@ import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndex;
* @author Matthew Khouzam
* @version $Revision: 1.0 $
*/
-public class CTFTrace implements IDefinitionScope {
+public class CTFTrace implements IDefinitionScope, AutoCloseable {
- // ------------------------------------------------------------------------
- // Attributes
- // ------------------------------------------------------------------------
-
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#toString()
- */
@SuppressWarnings("nls")
@Override
public String toString() {
/* Only for debugging, shouldn't be externalized */
- return "CTFTrace [path=" + path + ", major=" + major + ", minor="
- + minor + ", uuid=" + uuid + "]";
+ return "CTFTrace [path=" + fPath + ", major=" + fMajor + ", minor="
+ + fMinor + ", uuid=" + fUuid + "]";
}
/**
* The trace directory on the filesystem.
*/
- private final File path;
-
- /**
- * The metadata parsing object.
- */
- private final Metadata metadata;
+ private final File fPath;
/**
* Major CTF version number
*/
- private Long major;
+ private Long fMajor;
/**
* Minor CTF version number
*/
- private Long minor;
+ private Long fMinor;
/**
* Trace UUID
*/
- private UUID uuid;
+ private UUID fUuid;
/**
* Trace byte order
*/
- private ByteOrder byteOrder;
+ private ByteOrder fByteOrder;
/**
* Packet header structure declaration
*/
- private StructDeclaration packetHeaderDecl = null;
+ private StructDeclaration fPacketHeaderDecl = null;
+
+ /**
+ * The clock of the trace
+ */
+ private CTFClock fSingleClock;
/**
* Packet header structure definition
@@ -119,39 +112,37 @@ public class CTFTrace implements IDefinitionScope {
* This is only used when opening the trace files, to read the first packet
* header and see if they are valid trace files.
*/
- private StructDefinition packetHeaderDef;
+ private StructDefinition fPacketHeaderDef;
/**
* Collection of streams contained in the trace.
*/
- private final HashMap streams;
+ private final Map fStreams = new HashMap<>();
/**
* Collection of environment variables set by the tracer
*/
- private final HashMap environment;
+ private final Map fEnvironment = new HashMap<>();
/**
* Collection of all the clocks in a system.
*/
- private final HashMap clocks;
+ private final Map fClocks = new HashMap<>();
- /** FileChannels to the streams */
- private final List streamFileChannels;
+ /** FileInputStreams to the streams */
+ private final List fFileInputStreams = new LinkedList<>();
/** Handlers for the metadata files */
- private final static FileFilter metadataFileFilter = new MetadataFileFilter();
- private final static Comparator metadataComparator = new MetadataComparator(); // $codepro.audit.disable
- // fieldJavadoc
+ private static final FileFilter METADATA_FILE_FILTER = new MetadataFileFilter();
+ private static final Comparator METADATA_COMPARATOR = new MetadataComparator();
- /** map of all the event types */
- private final HashMap> eventDecs;
- /** map of all the event types */
- private final HashMap> eventDefs;
- /** map of all the indexes */
- private final HashMap indexes;
+ /** Callsite helpers */
+ private CTFCallsiteComparator fCtfCallsiteComparator = new CTFCallsiteComparator();
+ private Map> fCallsitesByName = new HashMap<>();
+ /** Callsite helpers */
+ private TreeSet fCallsitesByIP = new TreeSet<>();
// ------------------------------------------------------------------------
// Constructors
@@ -179,82 +170,81 @@ public class CTFTrace implements IDefinitionScope {
* If no CTF trace was found at the path
*/
public CTFTrace(File path) throws CTFReaderException {
- this.path = path;
- this.metadata = new Metadata(this);
+ fPath = path;
+ final Metadata metadata = new Metadata(this);
/* Set up the internal containers for this trace */
- streams = new HashMap();
- environment = new HashMap();
- clocks = new HashMap();
- streamFileChannels = new LinkedList();
- eventDecs = new HashMap>();
- eventDefs = new HashMap>();
-
- if (!this.path.isDirectory()) {
+ if (!fPath.exists()) {
+ throw new CTFReaderException("Trace (" + path.getPath() + ") doesn't exist. Deleted or moved?"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (!fPath.isDirectory()) {
throw new CTFReaderException("Path must be a valid directory"); //$NON-NLS-1$
}
/* Open and parse the metadata file */
- metadata.parse();
+ metadata.parseFile();
- if (Activator.getDefault() != null) {
- Activator.getDefault().log(metadata.toString());
- }
+ init(path);
+ }
- /* Open all the trace files */
+ /**
+ * Streamed constructor
+ *
+ * @since 3.0
+ */
+ public CTFTrace() {
+ fPath = null;
+ init();
+ }
+
+ private void init() {
/* Create the definitions needed to read things from the files */
- if (packetHeaderDecl != null) {
- packetHeaderDef = packetHeaderDecl.createDefinition(this,
- "packet.header"); //$NON-NLS-1$
+ if (fPacketHeaderDecl != null) {
+ fPacketHeaderDef = fPacketHeaderDecl.createDefinition(this, "packet.header"); //$NON-NLS-1$
}
+ }
+
+ private void init(File path) throws CTFReaderException {
+
+ init();
+
+ /* Open all the trace files */
/* List files not called metadata and not hidden. */
- File[] files = path.listFiles(metadataFileFilter);
- Arrays.sort(files, metadataComparator);
- indexes = new HashMap();
+ File[] files = path.listFiles(METADATA_FILE_FILTER);
+ Arrays.sort(files, METADATA_COMPARATOR);
+
/* Try to open each file */
for (File streamFile : files) {
openStreamInput(streamFile);
}
/* Create their index */
- for (Map.Entry stream : streams.entrySet()) {
- Set inputs = stream.getValue().getStreamInputs();
+ for (Stream stream : getStreams()) {
+ Set inputs = stream.getStreamInputs();
for (StreamInput s : inputs) {
- /*
- * Copy the events
- */
- Iterator> it = s.getStream()
- .getEvents().entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry pairs = it.next();
- Long eventNum = pairs.getKey();
- EventDeclaration eventDec = pairs.getValue();
- getEvents(s.getStream().getId()).put(eventNum, eventDec);
- }
-
- /*
- * index the trace
- */
- s.setupIndex();
+ addStream(s);
}
}
}
+ /**
+ * Dispose the trace
+ *
+ * @since 3.0
+ */
@Override
- protected void finalize() throws Throwable {
- /* If this trace gets closed, release the descriptors to the streams */
- for (FileChannel fc : streamFileChannels) {
- if (fc != null) {
+ public void close() {
+ for (FileInputStream fis : fFileInputStreams) {
+ if (fis != null) {
try {
- fc.close();
+ fis.close();
} catch (IOException e) {
// do nothing it's ok, we tried to close it.
}
}
}
- super.finalize();
-
}
// ------------------------------------------------------------------------
@@ -267,33 +257,25 @@ public class CTFTrace implements IDefinitionScope {
* @param streamId
* The ID of the stream from which to read
* @return The Hash map with the event declarations
+ * @since 2.0
*/
- public HashMap getEvents(Long streamId) {
- return eventDecs.get(streamId);
- }
-
- /**
- * Gets an index for a given StreamInput
- * @param id the StreamInput
- * @return The index
- */
- public StreamInputPacketIndex getIndex(StreamInput id){
- if(! indexes.containsKey(id)){
- indexes.put(id, new StreamInputPacketIndex());
- }
- return indexes.get(id);
+ public Map getEvents(Long streamId) {
+ return fStreams.get(streamId).getEvents();
}
/**
* Gets an event Declaration hashmap for a given StreamInput
- * @param id the StreamInput
- * @return the hashmap with the event definitions
+ *
+ * @param id
+ * the StreamInput
+ * @return an empty hashmap, please see deprecated
+ * @since 2.0
+ * @deprecated You should be using
+ * {@link StreamInputReader#getEventDefinitions()} instead.
*/
- public HashMap getEventDefs(StreamInput id) {
- if(! eventDefs.containsKey(id)){
- eventDefs.put(id, new HashMap());
- }
- return eventDefs.get(id);
+ @Deprecated
+ public Map getEventDefs(StreamInput id) {
+ return new HashMap<>();
}
/**
@@ -304,8 +286,9 @@ public class CTFTrace implements IDefinitionScope {
* @param id
* the ID of the event
* @return the event declaration
+ * @since 2.0
*/
- public EventDeclaration getEventType(long streamId, long id) {
+ public IEventDeclaration getEventType(long streamId, long id) {
return getEvents(streamId).get(id);
}
@@ -315,9 +298,10 @@ public class CTFTrace implements IDefinitionScope {
* @param id
* Long the id of the stream
* @return Stream the stream that we need
+ * @since 2.0
*/
public Stream getStream(Long id) {
- return streams.get(id);
+ return fStreams.get(id);
}
/**
@@ -326,7 +310,7 @@ public class CTFTrace implements IDefinitionScope {
* @return int the number of streams
*/
public int nbStreams() {
- return streams.size();
+ return fStreams.size();
}
/**
@@ -336,7 +320,7 @@ public class CTFTrace implements IDefinitionScope {
* long the major version
*/
public void setMajor(long major) {
- this.major = major;
+ fMajor = major;
}
/**
@@ -346,7 +330,7 @@ public class CTFTrace implements IDefinitionScope {
* long the minor version
*/
public void setMinor(long minor) {
- this.minor = minor;
+ fMinor = minor;
}
/**
@@ -356,7 +340,7 @@ public class CTFTrace implements IDefinitionScope {
* UUID
*/
public void setUUID(UUID uuid) {
- this.uuid = uuid;
+ fUuid = uuid;
}
/**
@@ -366,7 +350,7 @@ public class CTFTrace implements IDefinitionScope {
* ByteOrder of the trace, can be little-endian or big-endian
*/
public void setByteOrder(ByteOrder byteOrder) {
- this.byteOrder = byteOrder;
+ fByteOrder = byteOrder;
}
/**
@@ -376,16 +360,17 @@ public class CTFTrace implements IDefinitionScope {
* StructDeclaration the header in structdeclaration form
*/
public void setPacketHeader(StructDeclaration packetHeader) {
- this.packetHeaderDecl = packetHeader;
+ fPacketHeaderDecl = packetHeader;
}
/**
- * Method majortIsSet is the major version number set?
+ * Method majorIsSet is the major version number set?
*
* @return boolean is the major set?
+ * @since 3.0
*/
- public boolean majortIsSet() {
- return major != null;
+ public boolean majorIsSet() {
+ return fMajor != null;
}
/**
@@ -394,16 +379,17 @@ public class CTFTrace implements IDefinitionScope {
* @return boolean is the minor set?
*/
public boolean minorIsSet() {
- return minor != null;
+ return fMinor != null;
}
/**
* Method UUIDIsSet is the UUID set?
*
* @return boolean is the UUID set?
+ * @since 2.0
*/
- public boolean UUIDIsSet() {
- return uuid != null;
+ public boolean uuidIsSet() {
+ return fUuid != null;
}
/**
@@ -412,7 +398,7 @@ public class CTFTrace implements IDefinitionScope {
* @return boolean is the byteorder set?
*/
public boolean byteOrderIsSet() {
- return byteOrder != null;
+ return fByteOrder != null;
}
/**
@@ -421,7 +407,7 @@ public class CTFTrace implements IDefinitionScope {
* @return boolean is the packet header set?
*/
public boolean packetHeaderIsSet() {
- return packetHeaderDecl != null;
+ return fPacketHeaderDecl != null;
}
/**
@@ -430,7 +416,7 @@ public class CTFTrace implements IDefinitionScope {
* @return UUID gets the trace UUID
*/
public UUID getUUID() {
- return uuid;
+ return fUuid;
}
/**
@@ -439,7 +425,7 @@ public class CTFTrace implements IDefinitionScope {
* @return long gets the trace major version
*/
public long getMajor() {
- return major;
+ return fMajor;
}
/**
@@ -448,7 +434,7 @@ public class CTFTrace implements IDefinitionScope {
* @return long gets the trace minor version
*/
public long getMinor() {
- return minor;
+ return fMinor;
}
/**
@@ -456,8 +442,8 @@ public class CTFTrace implements IDefinitionScope {
*
* @return ByteOrder gets the trace byte order
*/
- public ByteOrder getByteOrder() {
- return byteOrder;
+ public final ByteOrder getByteOrder() {
+ return fByteOrder;
}
/**
@@ -466,7 +452,7 @@ public class CTFTrace implements IDefinitionScope {
* @return StructDeclaration gets the trace packet header
*/
public StructDeclaration getPacketHeader() {
- return packetHeaderDecl;
+ return fPacketHeaderDecl;
}
/**
@@ -475,16 +461,17 @@ public class CTFTrace implements IDefinitionScope {
* @return File the path in "File" format.
*/
public File getTraceDirectory() {
- return path;
+ return fPath;
}
/**
- * Method getStreams get all the streams in a map format.
+ * Get all the streams as an iterable.
*
- * @return Map a map of all the streams.
+ * @return Iterable<Stream> an iterable over streams.
+ * @since 3.0
*/
- public Map getStreams() {
- return streams;
+ public Iterable getStreams() {
+ return fStreams.values();
}
/**
@@ -495,16 +482,36 @@ public class CTFTrace implements IDefinitionScope {
*/
@Override
public String getPath() {
- return path.getPath();
+ return (fPath != null) ? fPath.getPath() : ""; //$NON-NLS-1$
}
// ------------------------------------------------------------------------
// Operations
// ------------------------------------------------------------------------
+ private void addStream(StreamInput s) {
+
+ /*
+ * Copy the events
+ */
+ Iterator> it = s.getStream()
+ .getEvents().entrySet().iterator();
+ while (it.hasNext()) {
+ Entry pairs = it.next();
+ Long eventNum = pairs.getKey();
+ IEventDeclaration eventDec = pairs.getValue();
+ getEvents(s.getStream().getId()).put(eventNum, eventDec);
+ }
+
+ /*
+ * index the trace
+ */
+ s.setupIndex();
+ }
+
/**
* Tries to open the given file, reads the first packet header of the file
- * and check its validity.
+ * and check its validity. This will add a file to a stream as a streaminput
*
* @param streamFile
* A trace file in the trace directory.
@@ -512,8 +519,9 @@ public class CTFTrace implements IDefinitionScope {
* Which index in the class' streamFileChannel array this file
* must use
* @throws CTFReaderException
+ * if there is a file error
*/
- private void openStreamInput(File streamFile) throws CTFReaderException {
+ private Stream openStreamInput(File streamFile) throws CTFReaderException {
MappedByteBuffer byteBuffer;
BitBuffer streamBitBuffer;
Stream stream;
@@ -524,27 +532,32 @@ public class CTFTrace implements IDefinitionScope {
+ streamFile.getPath());
}
+ FileInputStream fis = null;
try {
/* Open the file and get the FileChannel */
- fc = new FileInputStream(streamFile).getChannel();
- streamFileChannels.add(fc);
+ fis = new FileInputStream(streamFile);
+ fFileInputStreams.add(fis);
+ fc = fis.getChannel();
/* Map one memory page of 4 kiB */
- byteBuffer = fc.map(MapMode.READ_ONLY, 0, 4096);
+ byteBuffer = fc.map(MapMode.READ_ONLY, 0, (int) Math.min(fc.size(), 4096L));
} catch (IOException e) {
+ if (fis != null) {
+ fFileInputStreams.remove(fis);
+ }
/* Shouldn't happen at this stage if every other check passed */
- throw new CTFReaderException();
+ throw new CTFReaderException(e);
}
/* Create a BitBuffer with this mapping and the trace byte order */
streamBitBuffer = new BitBuffer(byteBuffer, this.getByteOrder());
- if (packetHeaderDef != null) {
+ if (fPacketHeaderDef != null) {
/* Read the packet header */
- packetHeaderDef.read(streamBitBuffer);
+ fPacketHeaderDef.read(streamBitBuffer);
/* Check the magic number */
- IntegerDefinition magicDef = (IntegerDefinition) packetHeaderDef
+ IntegerDefinition magicDef = (IntegerDefinition) fPacketHeaderDef
.lookupDefinition("magic"); //$NON-NLS-1$
int magic = (int) magicDef.getValue();
if (magic != Utils.CTF_MAGIC) {
@@ -552,7 +565,7 @@ public class CTFTrace implements IDefinitionScope {
}
/* Check UUID */
- ArrayDefinition uuidDef = (ArrayDefinition) packetHeaderDef
+ ArrayDefinition uuidDef = (ArrayDefinition) fPacketHeaderDef
.lookupDefinition("uuid"); //$NON-NLS-1$
if (uuidDef != null) {
byte[] uuidArray = new byte[Utils.UUID_LEN];
@@ -565,26 +578,30 @@ public class CTFTrace implements IDefinitionScope {
UUID otheruuid = Utils.makeUUID(uuidArray);
- if (!this.uuid.equals(otheruuid)) {
+ if (!fUuid.equals(otheruuid)) {
throw new CTFReaderException("UUID mismatch"); //$NON-NLS-1$
}
}
- /* Read stream ID */
- // TODO: it hasn't been checked that the stream_id field exists and
- // is an unsigned
- // integer
- IntegerDefinition streamIDDef = (IntegerDefinition) packetHeaderDef
- .lookupDefinition("stream_id"); //$NON-NLS-1$
- assert (streamIDDef != null);
+ /* Read the stream ID */
+ Definition streamIDDef = fPacketHeaderDef.lookupDefinition("stream_id"); //$NON-NLS-1$
- long streamID = streamIDDef.getValue();
+ if (streamIDDef instanceof IntegerDefinition) { // this doubles as a
+ // null check
+ long streamID = ((IntegerDefinition) streamIDDef).getValue();
+ stream = fStreams.get(streamID);
+ } else {
+ /* No stream_id in the packet header */
+ stream = fStreams.get(null);
+ }
- /* Get the stream to which this trace file belongs to */
- stream = streams.get(streamID);
} else {
/* No packet header, we suppose there is only one stream */
- stream = streams.get(null);
+ stream = fStreams.get(null);
+ }
+
+ if (stream == null) {
+ throw new CTFReaderException("Unexpected end of stream"); //$NON-NLS-1$
}
/* Create the stream input */
@@ -592,6 +609,8 @@ public class CTFTrace implements IDefinitionScope {
/* Add a reference to the streamInput in the stream */
stream.addInput(streamInput);
+
+ return stream;
}
/**
@@ -605,142 +624,308 @@ public class CTFTrace implements IDefinitionScope {
@Override
public Definition lookupDefinition(String lookupPath) {
if (lookupPath.equals("trace.packet.header")) { //$NON-NLS-1$
- return packetHeaderDef;
+ return fPacketHeaderDef;
}
return null;
}
/**
- * Adds a new stream to the trace.
+ * Add a new stream file to support new streams while the trace is being
+ * read.
+ *
+ * @param streamFile
+ * the file of the stream
+ * @throws CTFReaderException
+ * A stream had an issue being read
+ * @since 3.0
+ */
+ public void addStreamFile(File streamFile) throws CTFReaderException {
+ openStreamInput(streamFile);
+ }
+
+ /**
+ * Registers a new stream to the trace.
*
* @param stream
* A stream object.
* @throws ParseException
* If there was some problem reading the metadata
+ * @since 2.0
*/
public void addStream(Stream stream) throws ParseException {
+ /*
+ * Init if not done before
+ */
+ init();
+
/*
* If there is already a stream without id (the null key), it must be
* the only one
*/
- if (streams.get(null) != null) {
+ if (fStreams.get(null) != null) {
throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$
}
/*
- * If the stream we try to add has the null key, it must be the onl * one. Thus, if the streams container is not empty, it is not valid.
+ * If the stream we try to add has the null key, it must be the only
+ * one. Thus, if the streams container is not empty, it is not valid.
*/
- if ((stream.getId() == null) && (streams.size() != 0)) {
+ if ((stream.getId() == null) && (fStreams.size() != 0)) {
throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$
}
- /* If a stream with the same ID already exists, it is not valid. */
- if (streams.get(stream.getId()) != null) {
+ /*
+ * If a stream with the same ID already exists, it is not valid.
+ */
+ Stream existingStream = fStreams.get(stream.getId());
+ if (existingStream != null) {
throw new ParseException("Stream id already exists"); //$NON-NLS-1$
}
- /* It should be ok now. */
- streams.put(stream.getId(), stream);
- eventDecs.put(stream.getId(), new HashMap());
+ /* This stream is valid and has a unique id. */
+ fStreams.put(stream.getId(), stream);
}
/**
- * gets the Environment variables from the trace metadata (See CTF spec)
- * @return the environment variables in a hashmap form (key value)
- */
- public HashMap getEnvironment() {
- return environment;
- }
-
- /**
- * Look up a specific environment variable
- * @param key the key to look for
- * @return the value of the variable, can be null.
+ * Gets the Environment variables from the trace metadata (See CTF spec)
+ *
+ * @return The environment variables in the form of an unmodifiable map
+ * (key, value)
+ * @since 2.0
*/
- public String lookupEnvironment(String key) {
- return environment.get(key);
+ public Map getEnvironment() {
+ return Collections.unmodifiableMap(fEnvironment);
}
/**
* Add a variable to the environment variables
- * @param varName the name of the variable
- * @param varValue the value of the variable
+ *
+ * @param varName
+ * the name of the variable
+ * @param varValue
+ * the value of the variable
*/
public void addEnvironmentVar(String varName, String varValue) {
- environment.put(varName, varValue);
+ fEnvironment.put(varName, varValue);
}
/**
* Add a clock to the clock list
- * @param nameValue the name of the clock (full name with scope)
- * @param ctfClock the clock
+ *
+ * @param nameValue
+ * the name of the clock (full name with scope)
+ * @param ctfClock
+ * the clock
*/
public void addClock(String nameValue, CTFClock ctfClock) {
- clocks.put(nameValue, ctfClock);
+ fClocks.put(nameValue, ctfClock);
}
/**
* gets the clock with a specific name
- * @param name the name of the clock.
+ *
+ * @param name
+ * the name of the clock.
* @return the clock
*/
public CTFClock getClock(String name) {
- return clocks.get(name);
+ return fClocks.get(name);
}
- private CTFClock singleClock;
- private long singleOffset;
-
/**
- * gets the clock if there is only one. (this is 100% of the use cases as of June 2012)
+ * gets the clock if there is only one. (this is 100% of the use cases as of
+ * June 2012)
+ *
* @return the clock
*/
public final CTFClock getClock() {
- if (clocks.size() == 1) {
- if (singleClock == null) {
- singleClock = clocks.get(clocks.keySet().toArray()[0]);
- singleOffset = (Long) getClock().getProperty("offset"); //$NON-NLS-1$
- }
- return singleClock;
+ if (fClocks.size() == 1) {
+ fSingleClock = fClocks.get(fClocks.keySet().iterator().next());
+ return fSingleClock;
}
return null;
}
/**
* gets the time offset of a clock with respect to UTC in nanoseconds
+ *
* @return the time offset of a clock with respect to UTC in nanoseconds
*/
public final long getOffset() {
if (getClock() == null) {
return 0;
}
- return singleOffset;
+ return fSingleClock.getClockOffset();
+ }
+
+ /**
+ * gets the time offset of a clock with respect to UTC in nanoseconds
+ *
+ * @return the time offset of a clock with respect to UTC in nanoseconds
+ */
+ private double getTimeScale() {
+ if (getClock() == null) {
+ return 1.0;
+ }
+ return fSingleClock.getClockScale();
+ }
+
+ /**
+ * Does the trace need to time scale?
+ *
+ * @return if the trace is in ns or cycles.
+ */
+ private boolean clockNeedsScale() {
+ if (getClock() == null) {
+ return false;
+ }
+ return fSingleClock.isClockScaled();
+ }
+
+ /**
+ * the inverse clock for returning to a scale.
+ *
+ * @return 1.0 / scale
+ */
+ private double getInverseTimeScale() {
+ if (getClock() == null) {
+ return 1.0;
+ }
+ return fSingleClock.getClockAntiScale();
}
/**
- * Does a given stream contain any events?
- * @param id the stream ID
- * @return true if the stream has events.
+ * @param cycles
+ * clock cycles since boot
+ * @return time in nanoseconds UTC offset
+ * @since 2.0
*/
- public boolean hasEvents(Long id){
- return eventDecs.containsKey(id);
+ public long timestampCyclesToNanos(long cycles) {
+ long retVal = cycles + getOffset();
+ /*
+ * this fix is since quite often the offset will be > than 53 bits and
+ * therefore the conversion will be lossy
+ */
+ if (clockNeedsScale()) {
+ retVal = (long) (retVal * getTimeScale());
+ }
+ return retVal;
}
/**
- * Add an event declaration map to the events map.
- * @param id the id of a stream
- * @return the hashmap containing events.
+ * @param nanos
+ * time in nanoseconds UTC offset
+ * @return clock cycles since boot.
+ * @since 2.0
*/
- public HashMap createEvents(Long id){
- HashMap value = eventDecs.get(id);
- if( value == null ) {
- value = new HashMap();
- eventDecs.put(id, value);
+ public long timestampNanoToCycles(long nanos) {
+ long retVal;
+ /*
+ * this fix is since quite often the offset will be > than 53 bits and
+ * therefore the conversion will be lossy
+ */
+ if (clockNeedsScale()) {
+ retVal = (long) (nanos * getInverseTimeScale());
+ } else {
+ retVal = nanos;
+ }
+ return retVal - getOffset();
+ }
+
+ /**
+ * Adds a callsite
+ *
+ * @param eventName
+ * the event name of the callsite
+ * @param funcName
+ * the name of the callsite function
+ * @param ip
+ * the ip of the callsite
+ * @param fileName
+ * the filename of the callsite
+ * @param lineNumber
+ * the line number of the callsite
+ */
+ public void addCallsite(String eventName, String funcName, long ip,
+ String fileName, long lineNumber) {
+ final CTFCallsite cs = new CTFCallsite(eventName, funcName, ip,
+ fileName, lineNumber);
+ TreeSet csl = fCallsitesByName.get(eventName);
+ if (csl == null) {
+ csl = new TreeSet<>(fCtfCallsiteComparator);
+ fCallsitesByName.put(eventName, csl);
+ }
+
+ csl.add(cs);
+
+ fCallsitesByIP.add(cs);
+ }
+
+ /**
+ * Gets the set of callsites associated to an event name. O(1)
+ *
+ * @param eventName
+ * the event name
+ * @return the callsite set can be empty
+ * @since 3.0
+ */
+ public TreeSet getCallsiteCandidates(String eventName) {
+ TreeSet retVal = fCallsitesByName.get(eventName);
+ if (retVal == null) {
+ retVal = new TreeSet<>(fCtfCallsiteComparator);
}
- return value;
+ return retVal;
}
+ /**
+ * The I'm feeling lucky of getCallsiteCandidates O(1)
+ *
+ * @param eventName
+ * the event name
+ * @return the first callsite that has that event name, can be null
+ * @since 1.2
+ */
+ public CTFCallsite getCallsite(String eventName) {
+ TreeSet callsites = fCallsitesByName.get(eventName);
+ if (callsites != null) {
+ return callsites.first();
+ }
+ return null;
+ }
+
+ /**
+ * Gets a callsite from the instruction pointer O(log(n))
+ *
+ * @param ip
+ * the instruction pointer to lookup
+ * @return the callsite just before that IP in the list remember the IP is
+ * backwards on X86, can be null if no callsite is before the IP.
+ * @since 1.2
+ */
+ public CTFCallsite getCallsite(long ip) {
+ CTFCallsite cs = new CTFCallsite(null, null, ip, null, 0L);
+ return fCallsitesByIP.ceiling(cs);
+ }
+
+ /**
+ * Gets a callsite using the event name and instruction pointer O(log(n))
+ *
+ * @param eventName
+ * the name of the event
+ * @param ip
+ * the instruction pointer
+ * @return the closest matching callsite, can be null
+ */
+ public CTFCallsite getCallsite(String eventName, long ip) {
+ final TreeSet candidates = fCallsitesByName.get(eventName);
+ final CTFCallsite dummyCs = new CTFCallsite(null, null, ip, null, -1);
+ final CTFCallsite callsite = candidates.ceiling(dummyCs);
+ if (callsite == null) {
+ return candidates.floor(dummyCs);
+ }
+ return callsite;
+ }
}
class MetadataFileFilter implements FileFilter {