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=4bb35847b7eb804f33a9a698b2460dc1b7ed7f38;hb=ede59fc8b6e42a13e95961bcecdd8167053d680d;hp=a9ccc2bfa5a8629a5f927e2d766be0957284906e;hpb=288c166d0038a94a36f31783c8d6ddb1d8cef6fe;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 a9ccc2bfa5..4bb35847b7 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,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2013 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 @@ -24,11 +24,10 @@ 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; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -37,18 +36,18 @@ 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.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.trace.StreamInputPacketIndex; +import org.eclipse.linuxtools.internal.ctf.core.event.types.ArrayDefinition; /** * A CTF trace on the file system. @@ -61,50 +60,49 @@ 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 { - @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=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + fMinor + ", uuid=" + fUuid + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } /** * The trace directory on the filesystem. */ - private final File path; + 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 singleClock; + private CTFClock fSingleClock = null; /** * Packet header structure definition @@ -112,43 +110,34 @@ 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 Map streams = new HashMap(); + private final Map fStreams = new HashMap<>(); /** * Collection of environment variables set by the tracer */ - private final Map environment = new HashMap(); + private final Map fEnvironment = new HashMap<>(); /** * Collection of all the clocks in a system. */ - private final Map clocks = new HashMap(); - - /** FileInputStreams to the streams */ - private final List fileInputStreams = new LinkedList(); + private final Map fClocks = new HashMap<>(); /** Handlers for the metadata files */ 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 Map> eventDecs = new HashMap>(); - - /** map of all the indexes */ - private final Map indexes = new HashMap(); - /** Callsite helpers */ - private CTFCallsiteComparator ctfCallsiteComparator = new CTFCallsiteComparator(); + private CTFCallsiteComparator fCtfCallsiteComparator = new CTFCallsiteComparator(); - private Map> callsitesByName = new HashMap>(); + private Map> fCallsitesByName = new HashMap<>(); /** Callsite helpers */ - private TreeSet callsitesByIP = new TreeSet(); + private TreeSet fCallsitesByIP = new TreeSet<>(); // ------------------------------------------------------------------------ // Constructors @@ -176,55 +165,51 @@ public class CTFTrace implements IDefinitionScope { * If no CTF trace was found at the path */ public CTFTrace(File path) throws CTFReaderException { - this.path = path; + fPath = path; final Metadata metadata = new Metadata(this); /* Set up the internal containers for this trace */ - if (!this.path.exists()) { + if (!fPath.exists()) { throw new CTFReaderException("Trace (" + path.getPath() + ") doesn't exist. Deleted or moved?"); //$NON-NLS-1$ //$NON-NLS-2$ } - if (!this.path.isDirectory()) { + 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(); + + init(path); + } + + /** + * Streamed constructor + * + * @since 3.0 + */ + public CTFTrace() { + fPath = null; + } + + private void init(File path) throws CTFReaderException { /* Open all the trace files */ - /* Create the definitions needed to read things from the files */ - if (packetHeaderDecl != null) { - packetHeaderDef = packetHeaderDecl.createDefinition(this, "packet.header"); //$NON-NLS-1$ - } /* List files not called metadata and not hidden. */ 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 (StreamInput s : inputs) { - /* - * 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(); + for (CTFStream stream : getStreams()) { + Set inputs = stream.getStreamInputs(); + for (CTFStreamInput s : inputs) { + addStream(s); } } } @@ -232,20 +217,12 @@ public class CTFTrace implements IDefinitionScope { /** * Dispose the trace * - * @since 2.0 + * FIXME Not needed anymore, class doesn't need to be AutoCloseable. + * + * @since 3.0 */ - public void dispose() { - for (FileInputStream fis : fileInputStreams) { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - // do nothing it's ok, we tried to close it. - } - } - } - // Invoke GC to release MappedByteBuffer objects (Java bug JDK-4724038) - System.gc(); + @Override + public void close() { } // ------------------------------------------------------------------------ @@ -261,36 +238,7 @@ public class CTFTrace implements IDefinitionScope { * @since 2.0 */ public Map getEvents(Long streamId) { - return eventDecs.get(streamId); - } - - /** - * Gets an index for a given StreamInput - * - * @param id - * the StreamInput - * @return The index - */ - StreamInputPacketIndex getIndex(StreamInput id) { - if (!indexes.containsKey(id)) { - indexes.put(id, new StreamInputPacketIndex()); - } - return indexes.get(id); - } - - /** - * 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 getEventDefs(StreamInput id) { - return new HashMap(); + return fStreams.get(streamId).getEvents(); } /** @@ -313,10 +261,10 @@ public class CTFTrace implements IDefinitionScope { * @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) { - return streams.get(id); + public CTFStream getStream(Long id) { + return fStreams.get(id); } /** @@ -325,7 +273,7 @@ public class CTFTrace implements IDefinitionScope { * @return int the number of streams */ public int nbStreams() { - return streams.size(); + return fStreams.size(); } /** @@ -335,7 +283,7 @@ public class CTFTrace implements IDefinitionScope { * long the major version */ public void setMajor(long major) { - this.major = major; + fMajor = major; } /** @@ -345,7 +293,7 @@ public class CTFTrace implements IDefinitionScope { * long the minor version */ public void setMinor(long minor) { - this.minor = minor; + fMinor = minor; } /** @@ -355,7 +303,7 @@ public class CTFTrace implements IDefinitionScope { * UUID */ public void setUUID(UUID uuid) { - this.uuid = uuid; + fUuid = uuid; } /** @@ -365,7 +313,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; } /** @@ -375,16 +323,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; } /** @@ -393,7 +342,7 @@ public class CTFTrace implements IDefinitionScope { * @return boolean is the minor set? */ public boolean minorIsSet() { - return minor != null; + return fMinor != null; } /** @@ -403,7 +352,7 @@ public class CTFTrace implements IDefinitionScope { * @since 2.0 */ public boolean uuidIsSet() { - return uuid != null; + return fUuid != null; } /** @@ -412,7 +361,7 @@ public class CTFTrace implements IDefinitionScope { * @return boolean is the byteorder set? */ public boolean byteOrderIsSet() { - return byteOrder != null; + return fByteOrder != null; } /** @@ -421,7 +370,7 @@ public class CTFTrace implements IDefinitionScope { * @return boolean is the packet header set? */ public boolean packetHeaderIsSet() { - return packetHeaderDecl != null; + return fPacketHeaderDecl != null; } /** @@ -430,7 +379,7 @@ public class CTFTrace implements IDefinitionScope { * @return UUID gets the trace UUID */ public UUID getUUID() { - return uuid; + return fUuid; } /** @@ -439,7 +388,7 @@ public class CTFTrace implements IDefinitionScope { * @return long gets the trace major version */ public long getMajor() { - return major; + return fMajor; } /** @@ -448,7 +397,7 @@ public class CTFTrace implements IDefinitionScope { * @return long gets the trace minor version */ public long getMinor() { - return minor; + return fMinor; } /** @@ -457,7 +406,7 @@ public class CTFTrace implements IDefinitionScope { * @return ByteOrder gets the trace byte order */ public final ByteOrder getByteOrder() { - return byteOrder; + return fByteOrder; } /** @@ -466,7 +415,7 @@ public class CTFTrace implements IDefinitionScope { * @return StructDeclaration gets the trace packet header */ public StructDeclaration getPacketHeader() { - return packetHeaderDecl; + return fPacketHeaderDecl; } /** @@ -475,16 +424,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(); } /** @@ -493,18 +443,38 @@ public class CTFTrace implements IDefinitionScope { * @return String the path of the trace directory, in string format. * @see java.io.File#getPath() */ - @Override public String getPath() { - return path.getPath(); + return (fPath != null) ? fPath.getPath() : ""; //$NON-NLS-1$ } + // ------------------------------------------------------------------------ // Operations // ------------------------------------------------------------------------ + private void addStream(CTFStreamInput 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,26 +482,25 @@ 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 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()); } - try { - /* Open the file and get the FileChannel */ - FileInputStream fis = new FileInputStream(streamFile); - fileInputStreams.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)); + 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); @@ -540,63 +509,68 @@ public class CTFTrace implements IDefinitionScope { /* Create a BitBuffer with this mapping and the trace byte order */ streamBitBuffer = new BitBuffer(byteBuffer, this.getByteOrder()); - if (packetHeaderDef != null) { + if (fPacketHeaderDecl != null) { /* Read the packet header */ - packetHeaderDef.read(streamBitBuffer); + fPacketHeaderDef = fPacketHeaderDecl.createDefinition(this, LexicalScope.PACKET_HEADER, streamBitBuffer); /* Check the magic number */ - IntegerDefinition magicDef = (IntegerDefinition) packetHeaderDef - .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) packetHeaderDef - .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 (!this.uuid.equals(otheruuid)) { + if (!fUuid.equals(otheruuid)) { throw new CTFReaderException("UUID mismatch"); //$NON-NLS-1$ } } /* Read the stream ID */ - Definition streamIDDef = packetHeaderDef.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 long streamID = ((IntegerDefinition) streamIDDef).getValue(); - stream = streams.get(streamID); + stream = fStreams.get(streamID); } else { /* No stream_id in the packet header */ - stream = streams.get(null); + stream = fStreams.get(null); } } 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 */ - StreamInput streamInput = new StreamInput(stream, fc, streamFile); + /* + * Create the stream input and add a reference to the streamInput in the + * stream + */ + stream.addInput(new CTFStreamInput(stream, streamFile)); + + return stream; + } - /* Add a reference to the streamInput in the stream */ - stream.addInput(streamInput); + // ------------------------------------------------------------------------ + // IDefinitionScope + // ------------------------------------------------------------------------ + + /** + * @since 3.0 + */ + @Override + public LexicalScope getScopePath() { + return LexicalScope.TRACE; } /** @@ -605,32 +579,49 @@ public class CTFTrace implements IDefinitionScope { * @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$ - return packetHeaderDef; + if (lookupPath.equals(LexicalScope.TRACE_PACKET_HEADER.toString())) { + return fPacketHeaderDef; } return null; } + // ------------------------------------------------------------------------ + // Live trace reading + // ------------------------------------------------------------------------ + /** - * 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 + * @since 3.0 */ - public void addStream(Stream stream) throws ParseException { - + 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 (streams.get(null) != null) { + if (fStreams.get(null) != null) { throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$ } @@ -638,39 +629,31 @@ public class CTFTrace implements IDefinitionScope { * 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. + */ + CTFStream 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) + * Gets the Environment variables from the trace metadata (See CTF spec) * - * @return the environment variables in a map form (key value) + * @return The environment variables in the form of an unmodifiable map + * (key, value) * @since 2.0 */ public Map 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. - */ - public String lookupEnvironment(String key) { - return environment.get(key); + return Collections.unmodifiableMap(fEnvironment); } /** @@ -682,7 +665,7 @@ public class CTFTrace implements IDefinitionScope { * the value of the variable */ public void addEnvironmentVar(String varName, String varValue) { - environment.put(varName, varValue); + fEnvironment.put(varName, varValue); } /** @@ -694,7 +677,7 @@ public class CTFTrace implements IDefinitionScope { * the clock */ public void addClock(String nameValue, CTFClock ctfClock) { - clocks.put(nameValue, ctfClock); + fClocks.put(nameValue, ctfClock); } /** @@ -705,7 +688,7 @@ public class CTFTrace implements IDefinitionScope { * @return the clock */ public CTFClock getClock(String name) { - return clocks.get(name); + return fClocks.get(name); } /** @@ -715,9 +698,12 @@ public class CTFTrace implements IDefinitionScope { * @return the clock */ public final CTFClock getClock() { - if (clocks.size() == 1) { - singleClock = clocks.get(clocks.keySet().iterator().next()); - return singleClock; + if (fSingleClock != null && fClocks.size() == 1) { + return fSingleClock; + } + if (fClocks.size() == 1) { + fSingleClock = fClocks.get(fClocks.keySet().iterator().next()); + return fSingleClock; } return null; } @@ -731,7 +717,7 @@ public class CTFTrace implements IDefinitionScope { if (getClock() == null) { return 0; } - return singleClock.getClockOffset(); + return fSingleClock.getClockOffset(); } /** @@ -743,7 +729,37 @@ public class CTFTrace implements IDefinitionScope { if (getClock() == null) { return 1.0; } - return singleClock.getClockScale(); + 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); } /** @@ -755,7 +771,7 @@ public class CTFTrace implements IDefinitionScope { if (getClock() == null) { return false; } - return singleClock.isClockScaled(); + return fSingleClock.isClockScaled(); } /** @@ -767,7 +783,7 @@ public class CTFTrace implements IDefinitionScope { if (getClock() == null) { return 1.0; } - return singleClock.getClockAntiScale(); + return fSingleClock.getClockAntiScale(); } /** @@ -808,34 +824,6 @@ public class CTFTrace implements IDefinitionScope { return retVal - getOffset(); } - /** - * Does a given stream contain any events? - * - * @param id - * the stream ID - * @return true if the stream has events. - */ - public boolean hasEvents(Long id) { - return eventDecs.containsKey(id); - } - - /** - * Add an event declaration map to the events map. - * - * @param id - * the id of a stream - * @return the hashmap containing events. - * @since 2.0 - */ - public Map createEvents(Long id) { - HashMap value = eventDecs.get(id); - if (value == null) { - value = new HashMap(); - eventDecs.put(id, value); - } - return value; - } - /** * Adds a callsite * @@ -854,15 +842,15 @@ public class CTFTrace implements IDefinitionScope { String fileName, long lineNumber) { final CTFCallsite cs = new CTFCallsite(eventName, funcName, ip, fileName, lineNumber); - TreeSet csl = callsitesByName.get(eventName); + TreeSet csl = fCallsitesByName.get(eventName); if (csl == null) { - csl = new TreeSet(ctfCallsiteComparator); - callsitesByName.put(eventName, csl); + csl = new TreeSet<>(fCtfCallsiteComparator); + fCallsitesByName.put(eventName, csl); } csl.add(cs); - callsitesByIP.add(cs); + fCallsitesByIP.add(cs); } /** @@ -874,9 +862,9 @@ public class CTFTrace implements IDefinitionScope { * @since 3.0 */ public TreeSet getCallsiteCandidates(String eventName) { - TreeSet retVal = callsitesByName.get(eventName); + TreeSet retVal = fCallsitesByName.get(eventName); if (retVal == null) { - retVal = new TreeSet(ctfCallsiteComparator); + retVal = new TreeSet<>(fCtfCallsiteComparator); } return retVal; } @@ -890,7 +878,7 @@ public class CTFTrace implements IDefinitionScope { * @since 1.2 */ public CTFCallsite getCallsite(String eventName) { - TreeSet callsites = callsitesByName.get(eventName); + TreeSet callsites = fCallsitesByName.get(eventName); if (callsites != null) { return callsites.first(); } @@ -908,7 +896,7 @@ public class CTFTrace implements IDefinitionScope { */ public CTFCallsite getCallsite(long ip) { CTFCallsite cs = new CTFCallsite(null, null, ip, null, 0L); - return callsitesByIP.ceiling(cs); + return fCallsitesByIP.ceiling(cs); } /** @@ -921,7 +909,10 @@ public class CTFTrace implements IDefinitionScope { * @return the closest matching callsite, can be null */ public CTFCallsite getCallsite(String eventName, long ip) { - final TreeSet candidates = callsitesByName.get(eventName); + final TreeSet 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) { @@ -929,6 +920,28 @@ public class CTFTrace implements IDefinitionScope { } 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 {