CTF: Do not recalculate the single clock each time in CTFTrace#getClock()
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / CTFTrace.java
index 7bb19730fe8c4cce8279e57f40084e4d402a2337..4bb35847b7eb804f33a9a698b2460dc1b7ed7f38 100644 (file)
@@ -28,8 +28,6 @@ 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;
@@ -38,17 +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.event.types.ArrayDefinition;
 
 /**
  * A CTF trace on the file system.
@@ -63,12 +62,11 @@ import org.eclipse.linuxtools.internal.ctf.core.event.metadata.exceptions.ParseE
  */
 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$
     }
 
     /**
@@ -104,7 +102,7 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
     /**
      * The clock of the trace
      */
-    private CTFClock fSingleClock;
+    private CTFClock fSingleClock = null;
 
     /**
      * Packet header structure definition
@@ -117,7 +115,7 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
     /**
      * 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
@@ -129,9 +127,6 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      */
     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();
@@ -195,20 +190,10 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      */
     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. */
@@ -221,9 +206,9 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
         }
 
         /* 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);
             }
         }
@@ -232,19 +217,12 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
     /**
      * 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.
-                }
-            }
-        }
     }
 
     // ------------------------------------------------------------------------
@@ -263,21 +241,6 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
         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
      *
@@ -298,9 +261,9 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      * @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);
     }
 
@@ -470,7 +433,7 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      * @return Iterable&lt;Stream&gt; an iterable over streams.
      * @since 3.0
      */
-    public Iterable<Stream> getStreams() {
+    public Iterable<CTFStream> getStreams() {
         return fStreams.values();
     }
 
@@ -480,16 +443,16 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      * @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
@@ -521,30 +484,24 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      * @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);
         }
@@ -552,31 +509,22 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
         /* 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$
@@ -584,7 +532,7 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
             }
 
             /* 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
@@ -604,31 +552,47 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
             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.
@@ -650,15 +614,9 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      *            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
@@ -678,7 +636,7 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
         /*
          * 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$
         }
@@ -740,6 +698,9 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      * @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;
@@ -771,6 +732,36 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
         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?
      *
@@ -919,6 +910,9 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
      */
     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) {
@@ -926,6 +920,28 @@ public class CTFTrace implements IDefinitionScope, AutoCloseable {
         }
         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 {
This page took 0.029427 seconds and 5 git commands to generate.