Improve performance of seeks by a factor of approximately 8000.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / StreamInputReader.java
index 7c4bf08676dcc0ff9d676d68bb40c3c0213f424a..816524285474b40b7ab7d81df60ec4b8304e8ecf 100644 (file)
@@ -13,7 +13,6 @@
 package org.eclipse.linuxtools.ctf.core.trace;
 
 import java.nio.ByteOrder;
-import java.util.ListIterator;
 
 import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
 import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
@@ -44,7 +43,7 @@ public class StreamInputReader {
     /**
      * Iterator on the packet index
      */
-    private ListIterator<StreamInputPacketIndexEntry> packetIndexIt;
+    private int packetIndex;
 
     /**
      * Reference to the current event of this trace file (iow, the last on that
@@ -54,6 +53,10 @@ public class StreamInputReader {
 
     private int name;
 
+    private CTFTraceReader parent;
+
+    private final long prevIndex;
+
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
@@ -67,12 +70,12 @@ public class StreamInputReader {
     public StreamInputReader(StreamInput streamInput) {
         this.streamInput = streamInput;
         this.packetReader = new StreamInputPacketReader(this);
-
         /*
          * Get the iterator on the packet index.
          */
-        this.packetIndexIt = streamInput.getIndex().listIterator();
+        this.packetIndex = 0;
 
+        this.prevIndex = 0;
         /*
          * Make first packet the current one.
          */
@@ -127,11 +130,18 @@ public class StreamInputReader {
      * @return If an event has been successfully read.
      */
     public boolean readNextEvent() {
+
         /*
          * Change packet if needed
          */
         if (!this.packetReader.hasMoreEvents()) {
-            goToNextPacket();
+            final StreamInputPacketIndexEntry prevPacket = this.packetReader
+                    .getCurrentPacket();
+            if (prevPacket != null) {
+                goToNextPacket();
+                final StreamInputPacketIndexEntry currentPacket = this.packetReader
+                        .getCurrentPacket();
+            }
         }
 
         /*
@@ -141,7 +151,10 @@ public class StreamInputReader {
             try {
                 this.setCurrentEvent(this.packetReader.readNextEvent());
             } catch (CTFReaderException e) {
-                /* Some problem happened, we'll assume there is no more events */
+                /*
+                 * Some problem happened, we'll assume that there are no more
+                 * events
+                 */
                 return false;
             }
             return true;
@@ -154,14 +167,32 @@ public class StreamInputReader {
      * Change the current packet of the packet reader to the next one.
      */
     private void goToNextPacket() {
-        if (getPacketIndexIt().hasNext()) {
-            StreamInputPacketIndexEntry nextPacket = getPacketIndexIt().next();
-            this.packetReader.setCurrentPacket(nextPacket);
+        packetIndex++;
+        if (getPacketSize() >= (packetIndex + 1)) {
+            this.packetReader.setCurrentPacket(getPacket());
         } else {
-            this.packetReader.setCurrentPacket(null);
+            try {
+                if (this.streamInput.addPacketHeaderIndex()) {
+                    packetIndex = getPacketSize() - 1;
+                    this.packetReader.setCurrentPacket(getPacket());
+
+                } else {
+                    this.packetReader.setCurrentPacket(null);
+                }
+
+            } catch (CTFReaderException e) {
+                this.packetReader.setCurrentPacket(null);
+            }
         }
     }
 
+    /**
+     * @return
+     */
+    private int getPacketSize() {
+        return streamInput.getIndex().getEntries().size();
+    }
+
     /**
      * Changes the location of the trace file reader so that the current event
      * is the first event with a timestamp greater than the given timestamp.
@@ -174,13 +205,27 @@ public class StreamInputReader {
         /*
          * Search in the index for the packet to search in.
          */
-        this.packetIndexIt = this.streamInput.getIndex().search(timestamp);
+        this.packetIndex = this.streamInput.getIndex().search(timestamp)
+                .previousIndex();
 
         /*
          * Switch to this packet.
          */
         goToNextPacket();
 
+        /*
+         * index up to the desired timestamp.
+         */
+        while ((this.packetReader.getCurrentPacket() != null)
+                && (this.packetReader.getCurrentPacket().getTimestampEnd() < timestamp)) {
+            try {
+                this.streamInput.addPacketHeaderIndex();
+                goToNextPacket();
+            } catch (CTFReaderException e) {
+                // do nothing here
+            }
+        }
+
         /*
          * Advance until A. we reached the end of the trace file (which means
          * the given timestamp is after the last event), or B. we found the
@@ -188,7 +233,7 @@ public class StreamInputReader {
          */
         readNextEvent();
         boolean done = (this.getCurrentEvent() == null);
-        while (!done && (this.getCurrentEvent().timestamp < timestamp)) {
+        while (!done && (this.getCurrentEvent().getTimestamp() < timestamp)) {
             readNextEvent();
             done = (this.getCurrentEvent() == null);
             offset++;
@@ -196,58 +241,64 @@ public class StreamInputReader {
         return offset;
     }
 
-    public long seekIndex(long index) throws CTFReaderException {
+    public void goToLastEvent() {
         /*
          * Search in the index for the packet to search in.
          */
-        this.packetIndexIt = this.streamInput.getIndex().searchIndex(index);
+        final int len = this.streamInput.getIndex().getEntries().size();
+
+        StreamInputPacketIndexEntry entry = null;
         /*
-         * Switch to this packet.
+         * Go to beginning of trace.
          */
-        goToNextPacket();
+        seek(0);
         /*
-         * Read the first packet
+         * if the trace is empty.
          */
-        readNextEvent();
+        if ((len == 0) || (this.packetReader.hasMoreEvents() == false)) {
+            /*
+             * This means the trace is empty. abort.
+             */
+            return;
+        }
         /*
-         * get the current index
+         * Go to the last packet that contains events.
          */
-        if (this.packetReader.getCurrentPacket() == null) {
-            throw new CTFReaderException(
-                    "Current packet null in index seek, did you index your trace yet?");
+        for (int pos = len - 1; pos > 0; pos--) {
+            packetIndex = pos;
+            this.packetReader.setCurrentPacket(getPacket());
+            if (this.packetReader.hasMoreEvents()) {
+                break;
+            }
         }
-        return this.packetReader.getCurrentPacket().getIndexBegin();
 
-    }
-
-    public void goToLastEvent() throws CTFReaderException {
         /*
-         * Search in the index for the packet to search in.
+         * Go until the end of that packet
          */
-        int len = this.streamInput.getIndex().getEntries().size();
-        int back = 0;
-        long desired_timestamp = -1;
-        do {
-            back++;
-            StreamInputPacketIndexEntry entry = this.streamInput.getIndex()
-                    .getEntries().get(len - back);
-            desired_timestamp = entry.getTimestampBegin() + 1;
-            seek(desired_timestamp);
-
-        } while (!this.packetReader.hasMoreEvents());
+        EventDefinition prevEvent = null;
+        while (this.currentEvent != null) {
+            prevEvent = this.currentEvent;
+            this.readNextEvent();
+        }
         /*
-         * Go until the end of that packet
+         * Go back to the previous event
          */
+        this.setCurrentEvent(prevEvent);
+    }
 
-        int packet_size = 0;
-        while (this.packetReader.hasMoreEvents()) {
-            this.packetReader.readNextEvent();
-            packet_size++;
-        }
-        seek(desired_timestamp);
-        for (int i = 0; i < (packet_size - 1); i++) {
-            this.packetReader.readNextEvent();
-        }
+    /**
+     * @return the parent
+     */
+    public CTFTraceReader getParent() {
+        return parent;
+    }
+
+    /**
+     * @param parent
+     *            the parent to set
+     */
+    public void setParent(CTFTraceReader parent) {
+        this.parent = parent;
     }
 
     public void setCurrentEvent(EventDefinition currentEvent) {
@@ -257,8 +308,12 @@ public class StreamInputReader {
     /**
      * @return the packetIndexIt
      */
-    private ListIterator<StreamInputPacketIndexEntry> getPacketIndexIt() {
-        return packetIndexIt;
+    private int getPacketIndex() {
+        return packetIndex;
+    }
+
+    private StreamInputPacketIndexEntry getPacket() {
+        return streamInput.getIndex().getEntries().get(getPacketIndex());
     }
 
     /**
@@ -268,4 +323,49 @@ public class StreamInputReader {
         return packetReader;
     }
 
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = (prime * result) + name;
+        result = (prime * result)
+                + ((streamInput == null) ? 0 : streamInput.hashCode());
+        return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof StreamInputReader)) {
+            return false;
+        }
+        StreamInputReader other = (StreamInputReader) obj;
+        if (name != other.name) {
+            return false;
+        }
+        if (streamInput == null) {
+            if (other.streamInput != null) {
+                return false;
+            }
+        } else if (!streamInput.equals(other.streamInput)) {
+            return false;
+        }
+        return true;
+    }
+
 }
This page took 0.028454 seconds and 5 git commands to generate.