import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.linuxtools.ctf.core.event.CTFCallsite;
import org.eclipse.linuxtools.ctf.core.event.CTFClock;
-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.scope.IDefinitionScope;
+import org.eclipse.linuxtools.ctf.core.event.scope.LexicalScope;
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.IDefinition;
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.event.CTFCallsiteComparator;
import org.eclipse.linuxtools.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.linuxtools.internal.ctf.core.event.types.ArrayDefinition;
/**
* A CTF trace on the file system.
*/
public class CTFTrace implements IDefinitionScope, AutoCloseable {
- @SuppressWarnings("nls")
@Override
public String toString() {
/* Only for debugging, shouldn't be externalized */
- return "CTFTrace [path=" + fPath + ", major=" + fMajor + ", minor="
- + fMinor + ", uuid=" + fUuid + "]";
+ return "CTFTrace [path=" + fPath + ", major=" + fMajor + ", minor=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ + fMinor + ", uuid=" + fUuid + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
/**
/**
* The clock of the trace
*/
- private CTFClock fSingleClock;
+ private CTFClock fSingleClock = null;
/**
* Packet header structure definition
/**
* Collection of streams contained in the trace.
*/
- private final Map<Long, Stream> fStreams = new HashMap<>();
+ private final Map<Long, CTFStream> fStreams = new HashMap<>();
/**
* Collection of environment variables set by the tracer
*/
private final Map<String, CTFClock> fClocks = new HashMap<>();
- /** FileInputStreams to the streams */
- private final List<FileInputStream> fFileInputStreams = new LinkedList<>();
-
/** Handlers for the metadata files */
private static final FileFilter METADATA_FILE_FILTER = new MetadataFileFilter();
private static final Comparator<File> METADATA_COMPARATOR = new MetadataComparator();
*/
public CTFTrace() {
fPath = null;
- init();
- }
-
- private void init() {
- /* Create the definitions needed to read things from the files */
- 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. */
}
/* Create their index */
- for (Stream stream : getStreams()) {
- Set<StreamInput> inputs = stream.getStreamInputs();
- for (StreamInput s : inputs) {
+ for (CTFStream stream : getStreams()) {
+ Set<CTFStreamInput> inputs = stream.getStreamInputs();
+ for (CTFStreamInput s : inputs) {
addStream(s);
}
}
/**
* Dispose the trace
*
+ * FIXME Not needed anymore, class doesn't need to be AutoCloseable.
+ *
* @since 3.0
*/
@Override
public void close() {
- for (FileInputStream fis : fFileInputStreams) {
- if (fis != null) {
- try {
- fis.close();
- } catch (IOException e) {
- // do nothing it's ok, we tried to close it.
- }
- }
- }
}
// ------------------------------------------------------------------------
return fStreams.get(streamId).getEvents();
}
- /**
- * Gets an event Declaration hashmap for a given StreamInput
- *
- * @param id
- * the StreamInput
- * @return an empty hashmap, please see deprecated
- * @since 2.0
- * @deprecated You should be using
- * {@link StreamInputReader#getEventDefinitions()} instead.
- */
- @Deprecated
- public Map<Long, EventDefinition> getEventDefs(StreamInput id) {
- return new HashMap<>();
- }
-
/**
* Get an event by it's ID
*
* @param id
* Long the id of the stream
* @return Stream the stream that we need
- * @since 2.0
+ * @since 3.0
*/
- public Stream getStream(Long id) {
+ public CTFStream getStream(Long id) {
return fStreams.get(id);
}
* @return Iterable<Stream> an iterable over streams.
* @since 3.0
*/
- public Iterable<Stream> getStreams() {
+ public Iterable<CTFStream> getStreams() {
return fStreams.values();
}
* @return String the path of the trace directory, in string format.
* @see java.io.File#getPath()
*/
- @Override
public String getPath() {
return (fPath != null) ? fPath.getPath() : ""; //$NON-NLS-1$
}
+
// ------------------------------------------------------------------------
// Operations
// ------------------------------------------------------------------------
- private void addStream(StreamInput s) {
+ private void addStream(CTFStreamInput s) {
/*
* Copy the events
* @throws CTFReaderException
* if there is a file error
*/
- private Stream openStreamInput(File streamFile) throws CTFReaderException {
+ private CTFStream openStreamInput(File streamFile) throws CTFReaderException {
MappedByteBuffer byteBuffer;
BitBuffer streamBitBuffer;
- Stream stream;
- FileChannel fc;
+ CTFStream stream;
if (!streamFile.canRead()) {
throw new CTFReaderException("Unreadable file : " //$NON-NLS-1$
+ streamFile.getPath());
}
- FileInputStream fis = null;
- try {
- /* Open the file and get the FileChannel */
- fis = new FileInputStream(streamFile);
- fFileInputStreams.add(fis);
- fc = fis.getChannel();
-
+ try (FileInputStream fis = new FileInputStream(streamFile);
+ FileChannel fc = fis.getChannel()) {
/* Map one memory page of 4 kiB */
byteBuffer = fc.map(MapMode.READ_ONLY, 0, (int) Math.min(fc.size(), 4096L));
- } catch (IOException e) {
- if (fis != null) {
- fFileInputStreams.remove(fis);
+ if( byteBuffer == null){
+ throw new IllegalStateException("Failed to allocate memory"); //$NON-NLS-1$
}
+ } catch (IOException e) {
/* Shouldn't happen at this stage if every other check passed */
throw new CTFReaderException(e);
}
/* Create a BitBuffer with this mapping and the trace byte order */
streamBitBuffer = new BitBuffer(byteBuffer, this.getByteOrder());
- if (fPacketHeaderDef != null) {
+ if (fPacketHeaderDecl != null) {
/* Read the packet header */
- fPacketHeaderDef.read(streamBitBuffer);
+ fPacketHeaderDef = fPacketHeaderDecl.createDefinition(this, LexicalScope.PACKET_HEADER, streamBitBuffer);
/* Check the magic number */
- IntegerDefinition magicDef = (IntegerDefinition) fPacketHeaderDef
- .lookupDefinition("magic"); //$NON-NLS-1$
+ IntegerDefinition magicDef = (IntegerDefinition) fPacketHeaderDef.lookupDefinition("magic"); //$NON-NLS-1$
int magic = (int) magicDef.getValue();
if (magic != Utils.CTF_MAGIC) {
throw new CTFReaderException("CTF magic mismatch"); //$NON-NLS-1$
}
/* Check UUID */
- ArrayDefinition uuidDef = (ArrayDefinition) fPacketHeaderDef
- .lookupDefinition("uuid"); //$NON-NLS-1$
+ IDefinition lookupDefinition = fPacketHeaderDef.lookupDefinition("uuid"); //$NON-NLS-1$
+ ArrayDefinition uuidDef = (ArrayDefinition) lookupDefinition;
if (uuidDef != null) {
- byte[] uuidArray = new byte[Utils.UUID_LEN];
-
- for (int i = 0; i < Utils.UUID_LEN; i++) {
- IntegerDefinition uuidByteDef = (IntegerDefinition) uuidDef
- .getElem(i);
- uuidArray[i] = (byte) uuidByteDef.getValue();
- }
-
- UUID otheruuid = Utils.makeUUID(uuidArray);
+ UUID otheruuid = Utils.getUUIDfromDefinition(uuidDef);
if (!fUuid.equals(otheruuid)) {
throw new CTFReaderException("UUID mismatch"); //$NON-NLS-1$
}
/* Read the stream ID */
- Definition streamIDDef = fPacketHeaderDef.lookupDefinition("stream_id"); //$NON-NLS-1$
+ IDefinition streamIDDef = fPacketHeaderDef.lookupDefinition("stream_id"); //$NON-NLS-1$
if (streamIDDef instanceof IntegerDefinition) { // this doubles as a
// null check
throw new CTFReaderException("Unexpected end of stream"); //$NON-NLS-1$
}
- /* Create the stream input */
- StreamInput streamInput = new StreamInput(stream, fc, streamFile);
-
- /* Add a reference to the streamInput in the stream */
- stream.addInput(streamInput);
+ /*
+ * Create the stream input and add a reference to the streamInput in the
+ * stream
+ */
+ stream.addInput(new CTFStreamInput(stream, streamFile));
return stream;
}
+ // ------------------------------------------------------------------------
+ // IDefinitionScope
+ // ------------------------------------------------------------------------
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public LexicalScope getScopePath() {
+ return LexicalScope.TRACE;
+ }
+
/**
* Looks up a definition from packet
*
* @param lookupPath
* String
* @return Definition
- * @see org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope#lookupDefinition(String)
+ * @see org.eclipse.linuxtools.ctf.core.event.scope.IDefinitionScope#lookupDefinition(String)
*/
@Override
public Definition lookupDefinition(String lookupPath) {
- if (lookupPath.equals("trace.packet.header")) { //$NON-NLS-1$
+ if (lookupPath.equals(LexicalScope.TRACE_PACKET_HEADER.toString())) {
return fPacketHeaderDef;
}
return null;
}
+ // ------------------------------------------------------------------------
+ // Live trace reading
+ // ------------------------------------------------------------------------
+
/**
* Add a new stream file to support new streams while the trace is being
* read.
* A stream object.
* @throws ParseException
* If there was some problem reading the metadata
- * @since 2.0
+ * @since 3.0
*/
- public void addStream(Stream stream) throws ParseException {
-
- /*
- * Init if not done before
- */
- init();
-
+ public void addStream(CTFStream stream) throws ParseException {
/*
* If there is already a stream without id (the null key), it must be
* the only one
/*
* If a stream with the same ID already exists, it is not valid.
*/
- Stream existingStream = fStreams.get(stream.getId());
+ CTFStream existingStream = fStreams.get(stream.getId());
if (existingStream != null) {
throw new ParseException("Stream id already exists"); //$NON-NLS-1$
}
* @return the clock
*/
public final CTFClock getClock() {
+ if (fSingleClock != null && fClocks.size() == 1) {
+ return fSingleClock;
+ }
if (fClocks.size() == 1) {
fSingleClock = fClocks.get(fClocks.keySet().iterator().next());
return fSingleClock;
return fSingleClock.getClockScale();
}
+ /**
+ * Gets the current first packet start time
+ * @return the current start time
+ * @since 3.0
+ */
+ public long getCurrentStartTime() {
+ long currentStart = Long.MAX_VALUE;
+ for (CTFStream stream : fStreams.values()) {
+ for (CTFStreamInput si : stream.getStreamInputs()) {
+ currentStart = Math.min(currentStart, si.getIndex().getEntries().get(0).getTimestampBegin());
+ }
+ }
+ return timestampCyclesToNanos(currentStart);
+ }
+
+ /**
+ * Gets the current last packet end time
+ * @return the current end time
+ * @since 3.0
+ */
+ public long getCurrentEndTime() {
+ long currentEnd = Long.MIN_VALUE;
+ for (CTFStream stream : fStreams.values()) {
+ for (CTFStreamInput si : stream.getStreamInputs()) {
+ currentEnd = Math.max(currentEnd, si.getTimestampEnd());
+ }
+ }
+ return timestampCyclesToNanos(currentEnd);
+ }
+
/**
* Does the trace need to time scale?
*
*/
public CTFCallsite getCallsite(String eventName, long ip) {
final TreeSet<CTFCallsite> candidates = fCallsitesByName.get(eventName);
+ if (candidates == null) {
+ return null;
+ }
final CTFCallsite dummyCs = new CTFCallsite(null, null, ip, null, -1);
final CTFCallsite callsite = candidates.ceiling(dummyCs);
if (callsite == null) {
}
return callsite;
}
+
+ /**
+ * Add a new stream
+ *
+ * @param id
+ * the ID of the stream
+ * @param streamFile
+ * new file in the stream
+ * @throws CTFReaderException
+ * The file must exist
+ * @since 3.0
+ */
+ public void addStream(long id, File streamFile) throws CTFReaderException {
+ CTFStream stream = null;
+ if (fStreams.containsKey(id)) {
+ stream = fStreams.get(id);
+ } else {
+ stream = new CTFStream(this);
+ fStreams.put(id, stream);
+ }
+ stream.addInput(new CTFStreamInput(stream, streamFile));
+ }
}
class MetadataFileFilter implements FileFilter {