From 96c1a940cf1c91b389ee39872ec3ab0444252b2d Mon Sep 17 00:00:00 2001
From: "Brian S. O'Neill" <bronee@gmail.com>
Date: Mon, 7 Apr 2008 00:58:24 +0000
Subject: MergeSortBuffer optionally accepts a Storage now.

---
 .../amazon/carbonado/cursor/MergeSortBuffer.java   | 80 ++++++++++++++++++----
 1 file changed, 67 insertions(+), 13 deletions(-)

(limited to 'src/main/java/com/amazon/carbonado')

diff --git a/src/main/java/com/amazon/carbonado/cursor/MergeSortBuffer.java b/src/main/java/com/amazon/carbonado/cursor/MergeSortBuffer.java
index 1057d01..b02f9bf 100644
--- a/src/main/java/com/amazon/carbonado/cursor/MergeSortBuffer.java
+++ b/src/main/java/com/amazon/carbonado/cursor/MergeSortBuffer.java
@@ -120,10 +120,11 @@ public class MergeSortBuffer<S extends Storable> extends AbstractCollection<S>
         TEMP_DIR = tempDir;
     }
 
-    private final Storage<S> mStorage;
     private final String mTempDir;
     private final int mMaxArrayCapacity;
 
+    private Preparer<S> mPreparer;
+
     private S[] mElements;
     private int mSize;
     private int mTotalSize;
@@ -136,14 +137,23 @@ public class MergeSortBuffer<S extends Storable> extends AbstractCollection<S>
     private volatile boolean mStop;
 
     /**
-     * @param storage storage type of elements
+     * @since 1.2
+     */
+    public MergeSortBuffer() {
+        this(null, TEMP_DIR, MAX_ARRAY_CAPACITY);
+    }
+
+    /**
+     * @param storage storage for elements; if null use first Storable to
+     * prepare reloaded Storables
      */
     public MergeSortBuffer(Storage<S> storage) {
         this(storage, TEMP_DIR, MAX_ARRAY_CAPACITY);
     }
 
     /**
-     * @param storage storage type of elements
+     * @param storage storage for elements; if null use first Storable to
+     * prepare reloaded Storables
      * @param tempDir directory to store temp files for merging, or null for default
      */
     public MergeSortBuffer(Storage<S> storage, String tempDir) {
@@ -151,7 +161,8 @@ public class MergeSortBuffer<S extends Storable> extends AbstractCollection<S>
     }
 
     /**
-     * @param storage storage type of elements
+     * @param storage storage for elements; if null use first Storable to
+     * prepare reloaded Storables
      * @param tempDir directory to store temp files for merging, or null for default
      * @param maxArrayCapacity maximum amount of storables to keep in an array
      * before serializing to a file
@@ -159,12 +170,13 @@ public class MergeSortBuffer<S extends Storable> extends AbstractCollection<S>
      */
     @SuppressWarnings("unchecked")
     public MergeSortBuffer(Storage<S> storage, String tempDir, int maxArrayCapacity) {
-        if (storage == null) {
-            throw new IllegalArgumentException();
-        }
-        mStorage = storage;
         mTempDir = tempDir;
         mMaxArrayCapacity = maxArrayCapacity;
+
+        if (storage != null) {
+            mPreparer = new FromStorage(storage);
+        }
+
         int cap = Math.min(MIN_ARRAY_CAPACITY, maxArrayCapacity);
         mElements = (S[]) new Storable[cap];
     }
@@ -178,6 +190,10 @@ public class MergeSortBuffer<S extends Storable> extends AbstractCollection<S>
     }
 
     public boolean add(S storable) {
+        if (mPreparer == null) {
+            mPreparer = new FromStorable(storable);
+        }
+
         Comparator<S> comparator = comparator();
 
         arrayPrep:
@@ -320,13 +336,17 @@ public class MergeSortBuffer<S extends Storable> extends AbstractCollection<S>
 
             InputStream in = new BufferedInputStream(new RAFInputStream(raf));
 
-            pq.add(new InputIter<S>(comparator, mStorage, in));
+            pq.add(new InputIter<S>(comparator, mPreparer, in));
         }
 
         return new Merger<S>(pq);
     }
 
     public void clear() {
+        if (mPreparer instanceof FromStorable) {
+            mPreparer = null;
+        }
+
         if (mTotalSize > 0) {
             mSize = 0;
             mTotalSize = 0;
@@ -369,6 +389,40 @@ public class MergeSortBuffer<S extends Storable> extends AbstractCollection<S>
         }
     }
 
+    private static interface Preparer<S extends Storable> {
+        S prepare();
+    }
+
+    private static class FromStorage<S extends Storable> implements Preparer<S> {
+        private final Storage<S> mStorage;
+
+        FromStorage(Storage<S> storage) {
+            if (storage == null) {
+                throw new IllegalArgumentException();
+            }
+            mStorage = storage;
+        }
+
+        public S prepare() {
+            return mStorage.prepare();
+        }
+    }
+
+    private static class FromStorable<S extends Storable> implements Preparer<S> {
+        private final S mStorable;
+
+        FromStorable(S storable) {
+            if (storable == null) {
+                throw new IllegalArgumentException();
+            }
+            mStorable = (S) storable.prepare();
+        }
+
+        public S prepare() {
+            return (S) mStorable.prepare();
+        }
+    }
+
     /**
      * Simple interator interface that supports peeking at next element.
      */
@@ -443,14 +497,14 @@ public class MergeSortBuffer<S extends Storable> extends AbstractCollection<S>
      * Iterator that reads from an input stream of serialized Storables.
      */
     private static class InputIter<S extends Storable> extends Iter<S> {
-        private Storage<S> mStorage;
+        private final Preparer<S> mPreparer;
         private InputStream mIn;
 
         private S mNext;
 
-        InputIter(Comparator<S> comparator, Storage<S> storage, InputStream in) {
+        InputIter(Comparator<S> comparator, Preparer<S> preparer, InputStream in) {
             super(comparator);
-            mStorage = storage;
+            mPreparer = preparer;
             mIn = in;
         }
 
@@ -460,7 +514,7 @@ public class MergeSortBuffer<S extends Storable> extends AbstractCollection<S>
             }
             if (mIn != null) {
                 try {
-                    S next = mStorage.prepare();
+                    S next = mPreparer.prepare();
                     next.readFrom(mIn);
                     mNext = next;
                 } catch (EOFException e) {
-- 
cgit v1.2.3