ctf: Fix race condition in ctfiterator
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / ctfadaptor / CtfIterator.java
index d139b4b4a049b1d14c53400abb4f373e0fdb66af..8311e7acb8fc351abd3183feab786cb491110e6f 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Ericsson
+ * Copyright (c) 2012, 2013 Ericsson
  *
  * All rights reserved. This program and the accompanying materials are made
  * available under the terms of the Eclipse Public License v1.0 which
@@ -16,16 +16,24 @@ import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
 import org.eclipse.linuxtools.tmf.core.trace.ITmfLocation;
 
 /**
- * The ctfIterator is the class that will act like a reader for the trace
- * it does not have a file handle, so many iterators can be used without worries
- * of io errors.
+ * The CTF trace reader iterator.
+ *
+ * It doesn't reserve a file handle, so many iterators can be used without worries
+ * of I/O errors or resource exhaustion.
+ *
+ * @version 1.0
+ * @author Matthew Khouzam
  */
-public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparable<CtfIterator>, Cloneable {
+public class CtfIterator extends CTFTraceReader implements ITmfContext,
+        Comparable<CtfIterator> {
 
     private final CtfTmfTrace ctfTmfTrace;
 
-    final public static CtfLocation NULL_LOCATION = new CtfLocation(
-            CtfLocation.INVALID_LOCATION);
+    /**
+     * An invalid location
+     */
+    final public static CtfLocation NULL_LOCATION = new CtfLocation(CtfLocation.INVALID_LOCATION);
+
     private CtfLocation curLocation;
     private long curRank;
 
@@ -33,13 +41,13 @@ public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparab
      * Create a new CTF trace iterator, which initially points at the first
      * event in the trace.
      *
-     * @param trace the trace to iterate over
+     * @param trace
+     *            the trace to iterate over
      */
     public CtfIterator(final CtfTmfTrace trace) {
         super(trace.getCTFTrace());
         this.ctfTmfTrace = trace;
         if (this.hasMoreEvents()) {
-
             this.curLocation = new CtfLocation(trace.getStartTime());
             this.curRank = 0;
         } else {
@@ -47,9 +55,6 @@ public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparab
         }
     }
 
-    /**
-     *
-     */
     private void setUnknownLocation() {
         this.curLocation = NULL_LOCATION;
         this.curRank = UNKNOWN_RANK;
@@ -57,20 +62,24 @@ public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparab
 
     /**
      * Constructor for CtfIterator.
-     * @param trace CtfTmfTrace the trace
-     * @param timestampValue long the timestamp in ns of the trace for positioning
-     * @param rank long the index of the trace for positioning
+     *
+     * @param trace
+     *            CtfTmfTrace the trace
+     * @param ctfLocationData
+     *            long the timestamp in ns of the trace for positioning
+     * @param rank
+     *            long the index of the trace for positioning
+     * @since 2.0
      */
-    public CtfIterator(final CtfTmfTrace trace, final long timestampValue,
-            final long rank) {
+    public CtfIterator(final CtfTmfTrace trace,
+            final CtfLocationInfo ctfLocationData, final long rank) {
         super(trace.getCTFTrace());
 
         this.ctfTmfTrace = trace;
         if (this.hasMoreEvents()) {
-            this.curLocation = (new CtfLocation(this.getCurrentEvent()
-                    .getTimestampValue()));
-            if (this.getCurrentEvent().getTimestampValue() != timestampValue) {
-                this.seek(timestampValue);
+            this.curLocation = new CtfLocation(ctfLocationData);
+            if (this.getCurrentEvent().getTimestamp().getValue() != ctfLocationData.getTimestamp()) {
+                this.seek(ctfLocationData);
                 this.curRank = rank;
             }
         } else {
@@ -92,49 +101,62 @@ public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparab
      * @return CtfTmfEvent
      */
     public CtfTmfEvent getCurrentEvent() {
-        final StreamInputReader top = super.prio.peek();
+        final StreamInputReader top = super.getPrio().peek();
         if (top != null) {
-            return new CtfTmfEvent(top.getCurrentEvent(), top.getFilename(),
-                    ctfTmfTrace);
+            return CtfTmfEventFactory.createEvent(top.getCurrentEvent(),
+                    top.getFilename(), ctfTmfTrace);
         }
         return null;
     }
 
+    @Override
+    public boolean seek(long timestamp) {
+        return seek(new CtfLocationInfo(timestamp, 0));
+    }
+
     /**
-     * Method seek. Seeks to a given timestamp
-     * @param timestamp long the timestamp in ns (utc)
+     * Seek this iterator to a given location.
+     *
+     * @param ctfLocationData
+     *            The LocationData representing the position to seek to
      * @return boolean
+     * @since 2.0
      */
-    @Override
-    public boolean seek(final long timestamp) {
+    public synchronized boolean seek(final CtfLocationInfo ctfLocationData) {
         boolean ret = false;
-        final long offsetTimestamp = timestamp
-                - this.getCtfTmfTrace().getCTFTrace().getOffset();
+
+        /* Adjust the timestamp depending on the trace's offset */
+        long currTimestamp = ctfLocationData.getTimestamp();
+        final long offsetTimestamp = this.getCtfTmfTrace().getCTFTrace().timestampNanoToCycles(currTimestamp);
         if (offsetTimestamp < 0) {
-            ret = super.seek(timestamp);
+            ret = super.seek(0L);
         } else {
             ret = super.seek(offsetTimestamp);
         }
 
-        if (ret) {
-            curLocation.setLocation(getCurrentEvent().getTimestampValue());
+        /*
+         * Check if there is already one or more events for that timestamp, and
+         * assign the location index correctly
+         */
+        long index = 0;
+        final CtfTmfEvent currentEvent = this.getCurrentEvent();
+        if (currentEvent != null) {
+            currTimestamp = currentEvent.getTimestamp().getValue();
+
+            for (long i = 0; i < ctfLocationData.getIndex(); i++) {
+                if (currTimestamp == currentEvent.getTimestamp().getValue()) {
+                    index++;
+                } else {
+                    index = 0;
+                }
+                this.advance();
+            }
         } else {
-            curLocation = NULL_LOCATION;
+            ret= false;
         }
-        return ret;
-    }
-
-    /**
-     * Method seekRank. seeks to a given rank
-     * @param rank long the rank to seek to
-     * @return boolean
-     */
-    public boolean seekRank(final long rank) {
-        boolean ret = false;
-        ret = super.seekIndex(rank);
-
+        /* Seek the current location accordingly */
         if (ret) {
-            curLocation.setLocation(getCurrentEvent().getTimestampValue());
+            curLocation = new CtfLocation(new CtfLocationInfo(getCurrentEvent().getTimestamp().getValue(), index));
         } else {
             curLocation = NULL_LOCATION;
         }
@@ -161,16 +183,10 @@ public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparab
         curRank = rank;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.eclipse.linuxtools.tmf.core.trace.TmfContext#clone()
-     */
     @Override
     public CtfIterator clone() {
         CtfIterator clone = null;
-        clone = new CtfIterator(ctfTmfTrace, this.getCurrentEvent()
-                .getTimestampValue(), curRank);
+        clone = new CtfIterator(ctfTmfTrace, this.getLocation().getLocationInfo(), curRank);
         return clone;
     }
 
@@ -180,20 +196,18 @@ public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparab
      */
     @Override
     public void dispose() {
-        // FIXME add dispose() stuff to CTFTrace and call it here...
-
+        super.dispose();
     }
 
     /**
      * Method setLocation.
      * @param location ITmfLocation<?>
-     * @see org.eclipse.linuxtools.tmf.core.trace.ITmfContext#setLocation(ITmfLocation<?>)
      */
     @Override
-    public void setLocation(final ITmfLocation<?> location) {
+    public void setLocation(final ITmfLocation location) {
         // FIXME alex: isn't there a cleaner way than a cast here?
         this.curLocation = (CtfLocation) location;
-        seek(((CtfLocation) location).getLocation());
+        seek(((CtfLocation) location).getLocationInfo());
     }
 
     /**
@@ -212,7 +226,10 @@ public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparab
      */
     @Override
     public void increaseRank() {
-        curRank++;
+        /* Only increase the rank if it's valid */
+        if(hasValidRank()) {
+            curRank++;
+        }
     }
 
     /**
@@ -230,10 +247,18 @@ public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparab
      * @return boolean successful or not
      */
     @Override
-    public boolean advance() {
+    public synchronized boolean advance() {
+        long index = curLocation.getLocationInfo().getIndex();
+        long timestamp = curLocation.getLocationInfo().getTimestamp();
         boolean ret = super.advance();
+
         if (ret) {
-            curLocation.setLocation(getCurrentEvent().getTimestampValue());
+            final long timestampValue = getCurrentEvent().getTimestamp().getValue();
+            if (timestamp == timestampValue) {
+                curLocation = new CtfLocation(timestampValue, index + 1);
+            } else {
+                curLocation = new CtfLocation(timestampValue, 0L);
+            }
         } else {
             curLocation = NULL_LOCATION;
         }
@@ -254,9 +279,7 @@ public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparab
         }
         return 0;
     }
-    /* (non-Javadoc)
-     * @see java.lang.Object#hashCode()
-     */
+
     @Override
     public int hashCode() {
         final int prime = 31;
@@ -269,9 +292,6 @@ public class CtfIterator extends CTFTraceReader implements ITmfContext, Comparab
         return result;
     }
 
-    /* (non-Javadoc)
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
     @Override
     public boolean equals(Object obj) {
         if (this == obj) {
This page took 0.027505 seconds and 5 git commands to generate.