From 4a25366df4303bebdbd771dcec202e8368fdb61f Mon Sep 17 00:00:00 2001
From: "Brian S. O'Neill" <bronee@gmail.com>
Date: Sat, 25 Jul 2009 17:47:01 +0000
Subject: Make cursors more resilient against concurrent close, preventing
 NoSuchElementException from being thrown inappropriately.

---
 .../amazon/carbonado/cursor/DifferenceCursor.java  |  2 ++
 .../carbonado/cursor/IntersectionCursor.java       |  2 ++
 .../com/amazon/carbonado/cursor/LimitCursor.java   | 11 +++++++----
 .../carbonado/cursor/MultiTransformedCursor.java   | 22 ++++++++++------------
 .../com/amazon/carbonado/cursor/SkipCursor.java    | 10 ++++++++--
 .../com/amazon/carbonado/cursor/SortedCursor.java  |  1 +
 .../cursor/SymmetricDifferenceCursor.java          |  2 ++
 .../amazon/carbonado/cursor/ThrottledCursor.java   |  4 ++++
 .../com/amazon/carbonado/cursor/UnionCursor.java   |  2 ++
 .../carbonado/repo/indexed/IndexedCursor.java      |  1 +
 10 files changed, 39 insertions(+), 18 deletions(-)

(limited to 'src')

diff --git a/src/main/java/com/amazon/carbonado/cursor/DifferenceCursor.java b/src/main/java/com/amazon/carbonado/cursor/DifferenceCursor.java
index a04aec0..867f2f0 100644
--- a/src/main/java/com/amazon/carbonado/cursor/DifferenceCursor.java
+++ b/src/main/java/com/amazon/carbonado/cursor/DifferenceCursor.java
@@ -108,6 +108,8 @@ public class DifferenceCursor<S> extends AbstractCursor<S> {
                     }
                 }
             }
+        } catch (NoSuchElementException e) {
+            return false;
         } catch (FetchException e) {
             try {
                 close();
diff --git a/src/main/java/com/amazon/carbonado/cursor/IntersectionCursor.java b/src/main/java/com/amazon/carbonado/cursor/IntersectionCursor.java
index 6eb3179..4d542e9 100644
--- a/src/main/java/com/amazon/carbonado/cursor/IntersectionCursor.java
+++ b/src/main/java/com/amazon/carbonado/cursor/IntersectionCursor.java
@@ -106,6 +106,8 @@ public class IntersectionCursor<S> extends AbstractCursor<S> {
                     return true;
                 }
             }
+        } catch (NoSuchElementException e) {
+            return false;
         } catch (FetchException e) {
             try {
                 close();
diff --git a/src/main/java/com/amazon/carbonado/cursor/LimitCursor.java b/src/main/java/com/amazon/carbonado/cursor/LimitCursor.java
index 925c582..1dc50be 100644
--- a/src/main/java/com/amazon/carbonado/cursor/LimitCursor.java
+++ b/src/main/java/com/amazon/carbonado/cursor/LimitCursor.java
@@ -50,11 +50,14 @@ public class LimitCursor<S> extends AbstractCursor<S> {
     }
 
     public boolean hasNext() throws FetchException {
-        if (mSource.hasNext()) {
-            if (mRemaining > 0) {
-                return true;
+        try {
+            if (mSource.hasNext()) {
+                if (mRemaining > 0) {
+                    return true;
+                }
+                mSource.close();
             }
-            mSource.close();
+        } catch (NoSuchElementException e) {
         }
         return false;
     }
diff --git a/src/main/java/com/amazon/carbonado/cursor/MultiTransformedCursor.java b/src/main/java/com/amazon/carbonado/cursor/MultiTransformedCursor.java
index fafb55f..fdeb941 100644
--- a/src/main/java/com/amazon/carbonado/cursor/MultiTransformedCursor.java
+++ b/src/main/java/com/amazon/carbonado/cursor/MultiTransformedCursor.java
@@ -72,21 +72,19 @@ public abstract class MultiTransformedCursor<S, T> extends AbstractCursor<T> {
                 mNextCursor.close();
                 mNextCursor = null;
             }
-            try {
-                int count = 0;
-                while (mCursor.hasNext()) {
-                    Cursor<T> nextCursor = transform(mCursor.next());
-                    if (nextCursor != null) {
-                        if (nextCursor.hasNext()) {
-                            mNextCursor = nextCursor;
-                            return true;
-                        }
-                        nextCursor.close();
+            int count = 0;
+            while (mCursor.hasNext()) {
+                Cursor<T> nextCursor = transform(mCursor.next());
+                if (nextCursor != null) {
+                    if (nextCursor.hasNext()) {
+                        mNextCursor = nextCursor;
+                        return true;
                     }
-                    interruptCheck(++count);
+                    nextCursor.close();
                 }
-            } catch (NoSuchElementException e) {
+                interruptCheck(++count);
             }
+        } catch (NoSuchElementException e) {
         } catch (FetchException e) {
             try {
                 close();
diff --git a/src/main/java/com/amazon/carbonado/cursor/SkipCursor.java b/src/main/java/com/amazon/carbonado/cursor/SkipCursor.java
index c991933..c770751 100644
--- a/src/main/java/com/amazon/carbonado/cursor/SkipCursor.java
+++ b/src/main/java/com/amazon/carbonado/cursor/SkipCursor.java
@@ -18,6 +18,8 @@
 
 package com.amazon.carbonado.cursor;
 
+import java.util.NoSuchElementException;
+
 import com.amazon.carbonado.Cursor;
 import com.amazon.carbonado.FetchException;
 
@@ -48,8 +50,12 @@ public class SkipCursor<S> extends AbstractCursor<S> {
     }
 
     public boolean hasNext() throws FetchException {
-        doSkip();
-        return mSource.hasNext();
+        try {
+            doSkip();
+            return mSource.hasNext();
+        } catch (NoSuchElementException e) {
+            return false;
+        }
     }
 
     public S next() throws FetchException {
diff --git a/src/main/java/com/amazon/carbonado/cursor/SortedCursor.java b/src/main/java/com/amazon/carbonado/cursor/SortedCursor.java
index 8de527d..d3bf24b 100644
--- a/src/main/java/com/amazon/carbonado/cursor/SortedCursor.java
+++ b/src/main/java/com/amazon/carbonado/cursor/SortedCursor.java
@@ -306,6 +306,7 @@ public class SortedCursor<S> extends AbstractCursor<S> {
             } catch (UndeclaredThrowableException e) {
                 throw toFetchException(e);
             }
+        } catch (NoSuchElementException e) {
         } catch (FetchException e) {
             try {
                 close();
diff --git a/src/main/java/com/amazon/carbonado/cursor/SymmetricDifferenceCursor.java b/src/main/java/com/amazon/carbonado/cursor/SymmetricDifferenceCursor.java
index b78cf79..4dc8700 100644
--- a/src/main/java/com/amazon/carbonado/cursor/SymmetricDifferenceCursor.java
+++ b/src/main/java/com/amazon/carbonado/cursor/SymmetricDifferenceCursor.java
@@ -113,6 +113,8 @@ public class SymmetricDifferenceCursor<S> extends AbstractCursor<S> {
                     return mCompareResult;
                 }
             }
+        } catch (NoSuchElementException e) {
+            return 0;
         } catch (FetchException e) {
             try {
                 close();
diff --git a/src/main/java/com/amazon/carbonado/cursor/ThrottledCursor.java b/src/main/java/com/amazon/carbonado/cursor/ThrottledCursor.java
index a349782..0a40570 100644
--- a/src/main/java/com/amazon/carbonado/cursor/ThrottledCursor.java
+++ b/src/main/java/com/amazon/carbonado/cursor/ThrottledCursor.java
@@ -18,6 +18,8 @@
 
 package com.amazon.carbonado.cursor;
 
+import java.util.NoSuchElementException;
+
 import com.amazon.carbonado.Cursor;
 import com.amazon.carbonado.FetchException;
 import com.amazon.carbonado.FetchInterruptedException;
@@ -63,6 +65,8 @@ public class ThrottledCursor<S> extends AbstractCursor<S> {
     public boolean hasNext() throws FetchException {
         try {
             return mCursor.hasNext();
+        } catch (NoSuchElementException e) {
+            return false;
         } catch (FetchException e) {
             try {
                 close();
diff --git a/src/main/java/com/amazon/carbonado/cursor/UnionCursor.java b/src/main/java/com/amazon/carbonado/cursor/UnionCursor.java
index c2bdd19..5f0e326 100644
--- a/src/main/java/com/amazon/carbonado/cursor/UnionCursor.java
+++ b/src/main/java/com/amazon/carbonado/cursor/UnionCursor.java
@@ -74,6 +74,8 @@ public class UnionCursor<S> extends AbstractCursor<S> {
             if (mNextRight == null && mRightCursor.hasNext()) {
                 mNextRight = mRightCursor.next();
             }
+        } catch (NoSuchElementException e) {
+            return false;
         } catch (FetchException e) {
             try {
                 close();
diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java
index de105cc..872b5b4 100644
--- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java
+++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedCursor.java
@@ -152,6 +152,7 @@ class IndexedCursor<S extends Storable> extends AbstractCursor<S> {
                     }
                 }
             }
+        } catch (NoSuchElementException e) {
         } catch (FetchException e) {
             try {
                 close();
-- 
cgit v1.2.3