You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by am...@apache.org on 2018/02/13 00:09:51 UTC

[2/7] asterixdb git commit: [ASTERIXDB-2204][STO] Fix implementations and usages of IIndexCursor

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeSearchCursorTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeSearchCursorTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeSearchCursorTest.java
index 68a3984..ff28470 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeSearchCursorTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeSearchCursorTest.java
@@ -60,48 +60,34 @@ import org.apache.hyracks.storage.common.IIndexCursor;
 import org.apache.hyracks.storage.common.MultiComparator;
 import org.apache.hyracks.storage.common.buffercache.IBufferCache;
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Test;
 
 public class BTreeSearchCursorTest extends AbstractBTreeTest {
-    protected final int fieldCount = 2;
-    protected final ITypeTraits[] typeTraits = new ITypeTraits[fieldCount];
-    protected final BTreeTypeAwareTupleWriterFactory tupleWriterFactory =
-            new BTreeTypeAwareTupleWriterFactory(typeTraits, false);
-    protected final ITreeIndexMetadataFrameFactory metaFrameFactory = new LIFOMetaDataFrameFactory();
-    protected final Random rnd = new Random(50);
-
-    @Override
-    @Before
-    public void setUp() throws HyracksDataException {
-        super.setUp();
-        typeTraits[0] = IntegerPointable.TYPE_TRAITS;
-        typeTraits[1] = IntegerPointable.TYPE_TRAITS;
-    }
+    public static final int FIELD_COUNT = 2;
+    public static final ITypeTraits[] TYPE_TRAITS = { IntegerPointable.TYPE_TRAITS, IntegerPointable.TYPE_TRAITS };
+    public static final BTreeTypeAwareTupleWriterFactory TUPLE_WRITER_FACTORY =
+            new BTreeTypeAwareTupleWriterFactory(TYPE_TRAITS, false);
+    public static final ITreeIndexMetadataFrameFactory META_FRAME_FACTORY = new LIFOMetaDataFrameFactory();
+    public static final int KEY_FIELDS_COUNT = 1;
+    public static final IBinaryComparatorFactory[] CMP_FACTORIES =
+            { PointableBinaryComparatorFactory.of(IntegerPointable.FACTORY) };
+    public static final ITreeIndexFrameFactory LEAF_FRAME_FACTORY = new BTreeNSMLeafFrameFactory(TUPLE_WRITER_FACTORY);
+    public static final ITreeIndexFrameFactory INTERIOR_FRAME_FACTORY =
+            new BTreeNSMInteriorFrameFactory(TUPLE_WRITER_FACTORY);
+    public static final Random RANDOM = new Random(50);
 
     @Test
     public void uniqueIndexTest() throws Exception {
         if (LOGGER.isInfoEnabled()) {
             LOGGER.info("TESTING RANGE SEARCH CURSOR ON UNIQUE INDEX");
         }
-
         IBufferCache bufferCache = harness.getBufferCache();
-
         // declare keys
-        int keyFieldCount = 1;
-        IBinaryComparatorFactory[] cmpFactories = new IBinaryComparatorFactory[keyFieldCount];
-        cmpFactories[0] = PointableBinaryComparatorFactory.of(IntegerPointable.FACTORY);
-
-        ITreeIndexFrameFactory leafFrameFactory = new BTreeNSMLeafFrameFactory(tupleWriterFactory);
-        ITreeIndexFrameFactory interiorFrameFactory = new BTreeNSMInteriorFrameFactory(tupleWriterFactory);
-
-        IBTreeLeafFrame leafFrame = (IBTreeLeafFrame) leafFrameFactory.createFrame();
-        IBTreeInteriorFrame interiorFrame = (IBTreeInteriorFrame) interiorFrameFactory.createFrame();
-
-        IMetadataPageManager freePageManager = new LinkedMetaDataPageManager(bufferCache, metaFrameFactory);
-
-        BTree btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories,
-                fieldCount, harness.getFileReference());
+        IBTreeLeafFrame leafFrame = (IBTreeLeafFrame) LEAF_FRAME_FACTORY.createFrame();
+        IBTreeInteriorFrame interiorFrame = (IBTreeInteriorFrame) INTERIOR_FRAME_FACTORY.createFrame();
+        IMetadataPageManager freePageManager = new LinkedMetaDataPageManager(bufferCache, META_FRAME_FACTORY);
+        BTree btree = new BTree(bufferCache, freePageManager, INTERIOR_FRAME_FACTORY, LEAF_FRAME_FACTORY, CMP_FACTORIES,
+                FIELD_COUNT, harness.getFileReference());
         btree.create();
         btree.activate();
 
@@ -111,7 +97,7 @@ public class BTreeSearchCursorTest extends AbstractBTreeTest {
         TreeSet<Integer> uniqueKeys = new TreeSet<>();
         ArrayList<Integer> keys = new ArrayList<>();
         while (uniqueKeys.size() < numKeys) {
-            int key = rnd.nextInt() % maxKey;
+            int key = RANDOM.nextInt() % maxKey;
             uniqueKeys.add(key);
         }
         for (Integer i : uniqueKeys) {
@@ -151,16 +137,16 @@ public class BTreeSearchCursorTest extends AbstractBTreeTest {
         cmpFactories[0] = PointableBinaryComparatorFactory.of(IntegerPointable.FACTORY);
         cmpFactories[1] = PointableBinaryComparatorFactory.of(IntegerPointable.FACTORY);
 
-        ITreeIndexFrameFactory leafFrameFactory = new BTreeNSMLeafFrameFactory(tupleWriterFactory);
-        ITreeIndexFrameFactory interiorFrameFactory = new BTreeNSMInteriorFrameFactory(tupleWriterFactory);
+        ITreeIndexFrameFactory leafFrameFactory = new BTreeNSMLeafFrameFactory(TUPLE_WRITER_FACTORY);
+        ITreeIndexFrameFactory interiorFrameFactory = new BTreeNSMInteriorFrameFactory(TUPLE_WRITER_FACTORY);
 
         IBTreeLeafFrame leafFrame = (IBTreeLeafFrame) leafFrameFactory.createFrame();
         IBTreeInteriorFrame interiorFrame = (IBTreeInteriorFrame) interiorFrameFactory.createFrame();
 
-        IMetadataPageManager freePageManager = new LinkedMetaDataPageManager(bufferCache, metaFrameFactory);
+        IMetadataPageManager freePageManager = new LinkedMetaDataPageManager(bufferCache, META_FRAME_FACTORY);
 
         BTree btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories,
-                fieldCount, harness.getFileReference());
+                FIELD_COUNT, harness.getFileReference());
         btree.create();
         btree.activate();
 
@@ -169,7 +155,7 @@ public class BTreeSearchCursorTest extends AbstractBTreeTest {
         int maxKey = 10;
         ArrayList<Integer> keys = new ArrayList<>();
         for (int i = 0; i < numKeys; i++) {
-            int k = rnd.nextInt() % maxKey;
+            int k = RANDOM.nextInt() % maxKey;
             keys.add(k);
         }
         Collections.sort(keys);
@@ -207,16 +193,16 @@ public class BTreeSearchCursorTest extends AbstractBTreeTest {
         cmpFactories[0] = PointableBinaryComparatorFactory.of(IntegerPointable.FACTORY);
         cmpFactories[1] = PointableBinaryComparatorFactory.of(IntegerPointable.FACTORY);
 
-        ITreeIndexFrameFactory leafFrameFactory = new BTreeNSMLeafFrameFactory(tupleWriterFactory);
-        ITreeIndexFrameFactory interiorFrameFactory = new BTreeNSMInteriorFrameFactory(tupleWriterFactory);
+        ITreeIndexFrameFactory leafFrameFactory = new BTreeNSMLeafFrameFactory(TUPLE_WRITER_FACTORY);
+        ITreeIndexFrameFactory interiorFrameFactory = new BTreeNSMInteriorFrameFactory(TUPLE_WRITER_FACTORY);
 
         IBTreeLeafFrame leafFrame = (IBTreeLeafFrame) leafFrameFactory.createFrame();
         IBTreeInteriorFrame interiorFrame = (IBTreeInteriorFrame) interiorFrameFactory.createFrame();
 
-        IMetadataPageManager freePageManager = new LinkedMetaDataPageManager(bufferCache, metaFrameFactory);
+        IMetadataPageManager freePageManager = new LinkedMetaDataPageManager(bufferCache, META_FRAME_FACTORY);
 
         BTree btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories,
-                fieldCount, harness.getFileReference());
+                FIELD_COUNT, harness.getFileReference());
         btree.create();
         btree.activate();
         // generate keys
@@ -224,7 +210,7 @@ public class BTreeSearchCursorTest extends AbstractBTreeTest {
         int maxKey = 10;
         ArrayList<Integer> keys = new ArrayList<>();
         for (int i = 0; i < numKeys; i++) {
-            int k = rnd.nextInt() % maxKey;
+            int k = RANDOM.nextInt() % maxKey;
             keys.add(k);
         }
         Collections.sort(keys);
@@ -248,7 +234,7 @@ public class BTreeSearchCursorTest extends AbstractBTreeTest {
         btree.destroy();
     }
 
-    public RangePredicate createRangePredicate(int lk, int hk, boolean lowKeyInclusive, boolean highKeyInclusive)
+    public static RangePredicate createRangePredicate(int lk, int hk, boolean lowKeyInclusive, boolean highKeyInclusive)
             throws HyracksDataException {
         // create tuplereferences for search keys
         ITupleReference lowKey = TupleUtils.createIntegerTuple(false, lk);
@@ -290,43 +276,38 @@ public class BTreeSearchCursorTest extends AbstractBTreeTest {
     public boolean performSearches(ArrayList<Integer> keys, BTree btree, IBTreeLeafFrame leafFrame,
             IBTreeInteriorFrame interiorFrame, int minKey, int maxKey, boolean lowKeyInclusive,
             boolean highKeyInclusive, boolean printExpectedResults) throws Exception {
-
         ArrayList<Integer> results = new ArrayList<>();
         ArrayList<Integer> expectedResults = new ArrayList<>();
-
         for (int i = minKey; i < maxKey; i++) {
             for (int j = minKey; j < maxKey; j++) {
                 results.clear();
                 expectedResults.clear();
-
                 int lowKey = i;
                 int highKey = j;
-
                 RangePredicate rangePred = createRangePredicate(lowKey, highKey, lowKeyInclusive, highKeyInclusive);
                 IndexAccessParameters actx =
                         new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE);
                 ITreeIndexAccessor indexAccessor = btree.createAccessor(actx);
                 IIndexCursor rangeCursor = indexAccessor.createSearchCursor(false);
-                indexAccessor.search(rangeCursor, rangePred);
-
                 try {
-                    while (rangeCursor.hasNext()) {
-                        rangeCursor.next();
-                        ITupleReference frameTuple = rangeCursor.getTuple();
-                        ByteArrayInputStream inStream = new ByteArrayInputStream(frameTuple.getFieldData(0),
-                                frameTuple.getFieldStart(0), frameTuple.getFieldLength(0));
-                        DataInput dataIn = new DataInputStream(inStream);
-                        Integer res = IntegerSerializerDeserializer.INSTANCE.deserialize(dataIn);
-                        results.add(res);
+                    indexAccessor.search(rangeCursor, rangePred);
+                    try {
+                        while (rangeCursor.hasNext()) {
+                            rangeCursor.next();
+                            ITupleReference frameTuple = rangeCursor.getTuple();
+                            ByteArrayInputStream inStream = new ByteArrayInputStream(frameTuple.getFieldData(0),
+                                    frameTuple.getFieldStart(0), frameTuple.getFieldLength(0));
+                            DataInput dataIn = new DataInputStream(inStream);
+                            Integer res = IntegerSerializerDeserializer.INSTANCE.deserialize(dataIn);
+                            results.add(res);
+                        }
+                    } finally {
+                        rangeCursor.close();
                     }
-                } catch (Exception e) {
-                    e.printStackTrace();
                 } finally {
                     rangeCursor.destroy();
                 }
-
                 getExpectedResults(expectedResults, keys, lowKey, highKey, lowKeyInclusive, highKeyInclusive);
-
                 if (printExpectedResults) {
                     if (expectedResults.size() > 0) {
                         char l, u;
@@ -381,10 +362,14 @@ public class BTreeSearchCursorTest extends AbstractBTreeTest {
     }
 
     protected void insertBTree(List<Integer> keys, BTree btree) throws HyracksDataException {
+        staticInsertBTree(keys, btree);
+    }
+
+    public static void staticInsertBTree(List<Integer> keys, BTree btree) throws HyracksDataException {
         IndexAccessParameters actx =
                 new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE);
         BTreeAccessor accessor = btree.createAccessor(actx);
-        ArrayTupleBuilder tupleBuilder = new ArrayTupleBuilder(fieldCount);
+        ArrayTupleBuilder tupleBuilder = new ArrayTupleBuilder(FIELD_COUNT);
         ArrayTupleReference tuple = new ArrayTupleReference();
 
         // insert keys into btree

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeUpdateSearchTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeUpdateSearchTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeUpdateSearchTest.java
index f32bda3..9a1b6bb 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeUpdateSearchTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/BTreeUpdateSearchTest.java
@@ -101,75 +101,81 @@ public class BTreeUpdateSearchTest extends AbstractBTreeTest {
         IndexAccessParameters actx =
                 new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE);
         ITreeIndexAccessor indexAccessor = btree.createAccessor(actx);
+        try {
+            int numInserts = 10000;
+            for (int i = 0; i < numInserts; i++) {
+                int f0 = rnd.nextInt() % 10000;
+                int f1 = 5;
+                TupleUtils.createIntegerTuple(tb, insertTuple, f0, f1);
+                if (LOGGER.isInfoEnabled()) {
+                    if (i % 10000 == 0) {
+                        long end = System.currentTimeMillis();
+                        LOGGER.info("INSERTING " + i + " : " + f0 + " " + f1 + " " + (end - start));
+                    }
+                }
 
-        int numInserts = 10000;
-        for (int i = 0; i < numInserts; i++) {
-            int f0 = rnd.nextInt() % 10000;
-            int f1 = 5;
-            TupleUtils.createIntegerTuple(tb, insertTuple, f0, f1);
-            if (LOGGER.isInfoEnabled()) {
-                if (i % 10000 == 0) {
-                    long end = System.currentTimeMillis();
-                    LOGGER.info("INSERTING " + i + " : " + f0 + " " + f1 + " " + (end - start));
+                try {
+                    indexAccessor.insert(insertTuple);
+                } catch (HyracksDataException hde) {
+                    if (hde.getErrorCode() != ErrorCode.DUPLICATE_KEY) {
+                        hde.printStackTrace();
+                        throw hde;
+                    }
                 }
             }
+            long end = System.currentTimeMillis();
+            long duration = end - start;
+            if (LOGGER.isInfoEnabled()) {
+                LOGGER.info("DURATION: " + duration);
+            }
 
+            // Update scan.
+            if (LOGGER.isInfoEnabled()) {
+                LOGGER.info("UPDATE SCAN:");
+            }
+            // Set the cursor to X latch nodes.
+            RangePredicate nullPred = new RangePredicate(null, null, true, true, null, null);
+            ITreeIndexCursor updateScanCursor = new BTreeRangeSearchCursor(leafFrame, true);
             try {
-                indexAccessor.insert(insertTuple);
-            } catch (HyracksDataException hde) {
-                if (hde.getErrorCode() != ErrorCode.DUPLICATE_KEY) {
-                    hde.printStackTrace();
-                    throw hde;
+                indexAccessor.search(updateScanCursor, nullPred);
+                try {
+                    while (updateScanCursor.hasNext()) {
+                        updateScanCursor.next();
+                        ITupleReference tuple = updateScanCursor.getTuple();
+                        // Change the value field.
+                        IntegerPointable.setInteger(tuple.getFieldData(1), tuple.getFieldStart(1), 10);
+                    }
+                } finally {
+                    updateScanCursor.close();
                 }
+            } finally {
+                updateScanCursor.destroy();
             }
-        }
-        long end = System.currentTimeMillis();
-        long duration = end - start;
-        if (LOGGER.isInfoEnabled()) {
-            LOGGER.info("DURATION: " + duration);
-        }
-
-        // Update scan.
-        if (LOGGER.isInfoEnabled()) {
-            LOGGER.info("UPDATE SCAN:");
-        }
-        // Set the cursor to X latch nodes.
-        ITreeIndexCursor updateScanCursor = new BTreeRangeSearchCursor(leafFrame, true);
-        RangePredicate nullPred = new RangePredicate(null, null, true, true, null, null);
-        indexAccessor.search(updateScanCursor, nullPred);
-        try {
-            while (updateScanCursor.hasNext()) {
-                updateScanCursor.next();
-                ITupleReference tuple = updateScanCursor.getTuple();
-                // Change the value field.
-                IntegerPointable.setInteger(tuple.getFieldData(1), tuple.getFieldStart(1), 10);
+            // Ordered scan to verify the values.
+            if (LOGGER.isInfoEnabled()) {
+                LOGGER.info("ORDERED SCAN:");
             }
-        } catch (Exception e) {
-            e.printStackTrace();
-        } finally {
-            updateScanCursor.destroy();
-        }
-
-        // Ordered scan to verify the values.
-        if (LOGGER.isInfoEnabled()) {
-            LOGGER.info("ORDERED SCAN:");
-        }
-        // Set the cursor to X latch nodes.
-        ITreeIndexCursor scanCursor = new BTreeRangeSearchCursor(leafFrame, true);
-        indexAccessor.search(scanCursor, nullPred);
-        try {
-            while (scanCursor.hasNext()) {
-                scanCursor.next();
-                ITupleReference tuple = scanCursor.getTuple();
-                String rec = TupleUtils.printTuple(tuple, recDescSers);
-                if (LOGGER.isInfoEnabled()) {
-                    LOGGER.info(rec);
+            // Set the cursor to X latch nodes.
+            ITreeIndexCursor scanCursor = new BTreeRangeSearchCursor(leafFrame, true);
+            try {
+                indexAccessor.search(scanCursor, nullPred);
+                try {
+                    while (scanCursor.hasNext()) {
+                        scanCursor.next();
+                        ITupleReference tuple = scanCursor.getTuple();
+                        String rec = TupleUtils.printTuple(tuple, recDescSers);
+                        if (LOGGER.isInfoEnabled()) {
+                            LOGGER.info(rec);
+                        }
+                    }
+                } finally {
+                    scanCursor.close();
                 }
+            } finally {
+                scanCursor.destroy();
             }
-        } catch (Exception e) {
-            e.printStackTrace();
         } finally {
-            scanCursor.destroy();
+            indexAccessor.destroy();
         }
         btree.deactivate();
         btree.destroy();

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeDiskScanCursorTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeDiskScanCursorTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeDiskScanCursorTest.java
new file mode 100644
index 0000000..8a27198
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeDiskScanCursorTest.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.storage.am.btree;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeSet;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.storage.am.btree.impls.BTree.BTreeAccessor;
+import org.apache.hyracks.storage.am.btree.impls.DiskBTree;
+import org.apache.hyracks.storage.am.btree.util.BTreeTestHarness;
+import org.apache.hyracks.storage.am.common.TestOperationCallback;
+import org.apache.hyracks.storage.am.common.api.IMetadataPageManager;
+import org.apache.hyracks.storage.am.common.api.ITreeIndexCursor;
+import org.apache.hyracks.storage.am.common.freepage.LinkedMetaDataPageManager;
+import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters;
+import org.apache.hyracks.storage.am.common.test.IIndexCursorTest;
+import org.apache.hyracks.storage.common.IIndexAccessor;
+import org.apache.hyracks.storage.common.IIndexCursor;
+import org.apache.hyracks.storage.common.ISearchPredicate;
+import org.apache.hyracks.storage.common.buffercache.IBufferCache;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+public class DiskBTreeDiskScanCursorTest extends IIndexCursorTest {
+    private static final BTreeTestHarness harness = new BTreeTestHarness();
+    private static DiskBTree btree;
+
+    @BeforeClass
+    public static void setup() throws HyracksDataException {
+        harness.setUp();
+        IBufferCache bufferCache = harness.getBufferCache();
+        IMetadataPageManager freePageManager =
+                new LinkedMetaDataPageManager(bufferCache, BTreeSearchCursorTest.META_FRAME_FACTORY);
+        btree = new DiskBTree(bufferCache, freePageManager, BTreeSearchCursorTest.INTERIOR_FRAME_FACTORY,
+                BTreeSearchCursorTest.LEAF_FRAME_FACTORY, BTreeSearchCursorTest.CMP_FACTORIES,
+                BTreeSearchCursorTest.FIELD_COUNT, harness.getFileReference());
+        btree.create();
+        btree.activate();
+
+        TreeSet<Integer> uniqueKeys = new TreeSet<>();
+        ArrayList<Integer> keys = new ArrayList<>();
+        // generate keys
+        int numKeys = 50;
+        int maxKey = 1000;
+        while (uniqueKeys.size() < numKeys) {
+            int key = BTreeSearchCursorTest.RANDOM.nextInt() % maxKey;
+            uniqueKeys.add(key);
+        }
+        for (Integer i : uniqueKeys) {
+            keys.add(i);
+        }
+        DiskBTreeSearchCursorTest.bulkLoadBTree(keys, btree);
+    }
+
+    @AfterClass
+    public static void tearDown() throws HyracksDataException {
+        try {
+            btree.deactivate();
+            btree.destroy();
+        } finally {
+            harness.tearDown();
+        }
+    }
+
+    @Override
+    protected List<ISearchPredicate> createSearchPredicates() throws HyracksDataException {
+        List<ISearchPredicate> predicates = new ArrayList<>();
+        int minKey = -10;
+        int maxKey = 10;
+        for (int i = minKey; i < maxKey; i++) {
+            for (int j = minKey; j < maxKey; j++) {
+                int lowKey = i;
+                int highKey = j;
+                predicates.add(BTreeSearchCursorTest.createRangePredicate(lowKey, highKey, true, true));
+            }
+        }
+        return predicates;
+    }
+
+    @Override
+    protected IIndexAccessor createAccessor() throws Exception {
+        IndexAccessParameters actx =
+                new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE);
+        return btree.createAccessor(actx);
+    }
+
+    @Override
+    protected void open(IIndexAccessor accessor, IIndexCursor cursor, ISearchPredicate predicate)
+            throws HyracksDataException {
+        ((BTreeAccessor) accessor).diskOrderScan((ITreeIndexCursor) cursor);
+    }
+
+    @Override
+    protected IIndexCursor createCursor(IIndexAccessor accessor) {
+        return ((BTreeAccessor) accessor).createDiskOrderScanCursor();
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreePointSearchCursorTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreePointSearchCursorTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreePointSearchCursorTest.java
new file mode 100644
index 0000000..c2a69e1
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreePointSearchCursorTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.storage.am.btree;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeSet;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.storage.am.btree.impls.BTree.BTreeAccessor;
+import org.apache.hyracks.storage.am.btree.impls.DiskBTree;
+import org.apache.hyracks.storage.am.btree.util.BTreeTestHarness;
+import org.apache.hyracks.storage.am.common.TestOperationCallback;
+import org.apache.hyracks.storage.am.common.api.IMetadataPageManager;
+import org.apache.hyracks.storage.am.common.freepage.LinkedMetaDataPageManager;
+import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters;
+import org.apache.hyracks.storage.am.common.test.IIndexCursorTest;
+import org.apache.hyracks.storage.common.IIndexAccessor;
+import org.apache.hyracks.storage.common.IIndexCursor;
+import org.apache.hyracks.storage.common.ISearchPredicate;
+import org.apache.hyracks.storage.common.buffercache.IBufferCache;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+public class DiskBTreePointSearchCursorTest extends IIndexCursorTest {
+    private static final BTreeTestHarness harness = new BTreeTestHarness();
+    private static DiskBTree btree;
+
+    @BeforeClass
+    public static void setup() throws HyracksDataException {
+        harness.setUp();
+        IBufferCache bufferCache = harness.getBufferCache();
+        IMetadataPageManager freePageManager =
+                new LinkedMetaDataPageManager(bufferCache, BTreeSearchCursorTest.META_FRAME_FACTORY);
+        btree = new DiskBTree(bufferCache, freePageManager, BTreeSearchCursorTest.INTERIOR_FRAME_FACTORY,
+                BTreeSearchCursorTest.LEAF_FRAME_FACTORY, BTreeSearchCursorTest.CMP_FACTORIES,
+                BTreeSearchCursorTest.FIELD_COUNT, harness.getFileReference());
+        btree.create();
+        btree.activate();
+
+        TreeSet<Integer> uniqueKeys = new TreeSet<>();
+        ArrayList<Integer> keys = new ArrayList<>();
+        // generate keys
+        int numKeys = 50;
+        int maxKey = 1000;
+        while (uniqueKeys.size() < numKeys) {
+            int key = BTreeSearchCursorTest.RANDOM.nextInt() % maxKey;
+            uniqueKeys.add(key);
+        }
+        for (Integer i : uniqueKeys) {
+            keys.add(i);
+        }
+        DiskBTreeSearchCursorTest.bulkLoadBTree(keys, btree);
+    }
+
+    @AfterClass
+    public static void tearDown() throws HyracksDataException {
+        try {
+            btree.deactivate();
+            btree.destroy();
+        } finally {
+            harness.tearDown();
+        }
+    }
+
+    @Override
+    protected List<ISearchPredicate> createSearchPredicates() throws HyracksDataException {
+        List<ISearchPredicate> predicates = new ArrayList<>();
+        int minKey = -10;
+        int maxKey = 10;
+        for (int i = minKey; i < maxKey; i++) {
+            int lowKey = i;
+            int highKey = i;
+            predicates.add(BTreeSearchCursorTest.createRangePredicate(lowKey, highKey, true, true));
+        }
+        return predicates;
+    }
+
+    @Override
+    protected IIndexAccessor createAccessor() throws Exception {
+        IndexAccessParameters actx =
+                new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE);
+        return btree.createAccessor(actx);
+    }
+
+    @Override
+    protected IIndexCursor createCursor(IIndexAccessor accessor) {
+        return ((BTreeAccessor) accessor).createPointCursor(false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeRangeSearchCursorTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeRangeSearchCursorTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeRangeSearchCursorTest.java
new file mode 100644
index 0000000..6c1c1bf
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeRangeSearchCursorTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.storage.am.btree;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeSet;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.storage.am.btree.impls.DiskBTree;
+import org.apache.hyracks.storage.am.btree.util.BTreeTestHarness;
+import org.apache.hyracks.storage.am.common.TestOperationCallback;
+import org.apache.hyracks.storage.am.common.api.IMetadataPageManager;
+import org.apache.hyracks.storage.am.common.freepage.LinkedMetaDataPageManager;
+import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters;
+import org.apache.hyracks.storage.am.common.test.IIndexCursorTest;
+import org.apache.hyracks.storage.common.IIndexAccessor;
+import org.apache.hyracks.storage.common.ISearchPredicate;
+import org.apache.hyracks.storage.common.buffercache.IBufferCache;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+public class DiskBTreeRangeSearchCursorTest extends IIndexCursorTest {
+    private static final BTreeTestHarness harness = new BTreeTestHarness();
+    private static DiskBTree btree;
+
+    @BeforeClass
+    public static void setup() throws HyracksDataException {
+        harness.setUp();
+        IBufferCache bufferCache = harness.getBufferCache();
+        IMetadataPageManager freePageManager =
+                new LinkedMetaDataPageManager(bufferCache, BTreeSearchCursorTest.META_FRAME_FACTORY);
+        btree = new DiskBTree(bufferCache, freePageManager, BTreeSearchCursorTest.INTERIOR_FRAME_FACTORY,
+                BTreeSearchCursorTest.LEAF_FRAME_FACTORY, BTreeSearchCursorTest.CMP_FACTORIES,
+                BTreeSearchCursorTest.FIELD_COUNT, harness.getFileReference());
+        btree.create();
+        btree.activate();
+
+        TreeSet<Integer> uniqueKeys = new TreeSet<>();
+        ArrayList<Integer> keys = new ArrayList<>();
+        // generate keys
+        int numKeys = 50;
+        int maxKey = 1000;
+        while (uniqueKeys.size() < numKeys) {
+            int key = BTreeSearchCursorTest.RANDOM.nextInt() % maxKey;
+            uniqueKeys.add(key);
+        }
+        for (Integer i : uniqueKeys) {
+            keys.add(i);
+        }
+        DiskBTreeSearchCursorTest.bulkLoadBTree(keys, btree);
+    }
+
+    @AfterClass
+    public static void tearDown() throws HyracksDataException {
+        try {
+            btree.deactivate();
+            btree.destroy();
+        } finally {
+            harness.tearDown();
+        }
+    }
+
+    @Override
+    protected List<ISearchPredicate> createSearchPredicates() throws HyracksDataException {
+        List<ISearchPredicate> predicates = new ArrayList<>();
+        int minKey = -10;
+        int maxKey = 10;
+        for (int i = minKey; i < maxKey; i++) {
+            for (int j = minKey; j < maxKey; j++) {
+                int lowKey = i;
+                int highKey = j;
+                predicates.add(BTreeSearchCursorTest.createRangePredicate(lowKey, highKey, true, true));
+            }
+        }
+        return predicates;
+    }
+
+    @Override
+    protected IIndexAccessor createAccessor() throws Exception {
+        IndexAccessParameters actx =
+                new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE);
+        return btree.createAccessor(actx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeSearchCursorTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeSearchCursorTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeSearchCursorTest.java
index c7f0425..c77bea0 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeSearchCursorTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskBTreeSearchCursorTest.java
@@ -26,10 +26,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.TreeSet;
 
-import org.apache.hyracks.api.dataflow.value.IBinaryComparatorFactory;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
-import org.apache.hyracks.data.std.accessors.PointableBinaryComparatorFactory;
-import org.apache.hyracks.data.std.primitive.IntegerPointable;
 import org.apache.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
 import org.apache.hyracks.dataflow.common.comm.io.ArrayTupleReference;
 import org.apache.hyracks.dataflow.common.data.accessors.ITupleReference;
@@ -37,15 +34,12 @@ import org.apache.hyracks.dataflow.common.data.marshalling.IntegerSerializerDese
 import org.apache.hyracks.dataflow.common.utils.TupleUtils;
 import org.apache.hyracks.storage.am.btree.api.IBTreeInteriorFrame;
 import org.apache.hyracks.storage.am.btree.api.IBTreeLeafFrame;
-import org.apache.hyracks.storage.am.btree.frames.BTreeNSMInteriorFrameFactory;
-import org.apache.hyracks.storage.am.btree.frames.BTreeNSMLeafFrameFactory;
 import org.apache.hyracks.storage.am.btree.impls.BTree;
 import org.apache.hyracks.storage.am.btree.impls.BTree.BTreeAccessor;
 import org.apache.hyracks.storage.am.btree.impls.DiskBTree;
 import org.apache.hyracks.storage.am.btree.impls.RangePredicate;
 import org.apache.hyracks.storage.am.common.TestOperationCallback;
 import org.apache.hyracks.storage.am.common.api.IMetadataPageManager;
-import org.apache.hyracks.storage.am.common.api.ITreeIndexFrameFactory;
 import org.apache.hyracks.storage.am.common.freepage.LinkedMetaDataPageManager;
 import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters;
 import org.apache.hyracks.storage.common.IIndexBulkLoader;
@@ -89,29 +83,18 @@ public class DiskBTreeSearchCursorTest extends BTreeSearchCursorTest {
     private void batchPointLookupTest(int numKeys, int maxKey, int minSearchKey, int maxSearchKey) throws Exception {
 
         IBufferCache bufferCache = harness.getBufferCache();
-
-        // declare keys
-        int keyFieldCount = 1;
-        IBinaryComparatorFactory[] cmpFactories = new IBinaryComparatorFactory[keyFieldCount];
-        cmpFactories[0] = PointableBinaryComparatorFactory.of(IntegerPointable.FACTORY);
-
-        ITreeIndexFrameFactory leafFrameFactory = new BTreeNSMLeafFrameFactory(tupleWriterFactory);
-        ITreeIndexFrameFactory interiorFrameFactory = new BTreeNSMInteriorFrameFactory(tupleWriterFactory);
-
-        IBTreeLeafFrame leafFrame = (IBTreeLeafFrame) leafFrameFactory.createFrame();
-        IBTreeInteriorFrame interiorFrame = (IBTreeInteriorFrame) interiorFrameFactory.createFrame();
-
-        IMetadataPageManager freePageManager = new LinkedMetaDataPageManager(bufferCache, metaFrameFactory);
-
-        DiskBTree btree = new DiskBTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory,
-                cmpFactories, fieldCount, harness.getFileReference());
+        IBTreeLeafFrame leafFrame = (IBTreeLeafFrame) LEAF_FRAME_FACTORY.createFrame();
+        IBTreeInteriorFrame interiorFrame = (IBTreeInteriorFrame) INTERIOR_FRAME_FACTORY.createFrame();
+        IMetadataPageManager freePageManager = new LinkedMetaDataPageManager(bufferCache, META_FRAME_FACTORY);
+        DiskBTree btree = new DiskBTree(bufferCache, freePageManager, INTERIOR_FRAME_FACTORY, LEAF_FRAME_FACTORY,
+                CMP_FACTORIES, FIELD_COUNT, harness.getFileReference());
         btree.create();
         btree.activate();
 
         TreeSet<Integer> uniqueKeys = new TreeSet<>();
         ArrayList<Integer> keys = new ArrayList<>();
         while (uniqueKeys.size() < numKeys) {
-            int key = rnd.nextInt() % maxKey;
+            int key = RANDOM.nextInt() % maxKey;
             uniqueKeys.add(key);
         }
         for (Integer i : uniqueKeys) {
@@ -135,58 +118,60 @@ public class DiskBTreeSearchCursorTest extends BTreeSearchCursorTest {
         BTreeAccessor indexAccessor = btree.createAccessor(
                 new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE));
         IIndexCursor pointCursor = indexAccessor.createPointCursor(false);
-        for (int i = minKey; i < maxKey; i++) {
-            results.clear();
-            expectedResults.clear();
-
-            int lowKey = i;
-            int highKey = i;
-            RangePredicate rangePred = createRangePredicate(lowKey, highKey, true, true);
-            indexAccessor.search(pointCursor, rangePred);
-            try {
-                while (pointCursor.hasNext()) {
-                    pointCursor.next();
-                    ITupleReference frameTuple = pointCursor.getTuple();
-                    ByteArrayInputStream inStream = new ByteArrayInputStream(frameTuple.getFieldData(0),
-                            frameTuple.getFieldStart(0), frameTuple.getFieldLength(0));
-                    DataInput dataIn = new DataInputStream(inStream);
-                    Integer res = IntegerSerializerDeserializer.INSTANCE.deserialize(dataIn);
-                    results.add(res);
+        try {
+            for (int i = minKey; i < maxKey; i++) {
+                results.clear();
+                expectedResults.clear();
+                int lowKey = i;
+                int highKey = i;
+                RangePredicate rangePred = createRangePredicate(lowKey, highKey, true, true);
+                indexAccessor.search(pointCursor, rangePred);
+                try {
+                    while (pointCursor.hasNext()) {
+                        pointCursor.next();
+                        ITupleReference frameTuple = pointCursor.getTuple();
+                        ByteArrayInputStream inStream = new ByteArrayInputStream(frameTuple.getFieldData(0),
+                                frameTuple.getFieldStart(0), frameTuple.getFieldLength(0));
+                        DataInput dataIn = new DataInputStream(inStream);
+                        Integer res = IntegerSerializerDeserializer.INSTANCE.deserialize(dataIn);
+                        results.add(res);
+                    }
+                } finally {
+                    pointCursor.close();
                 }
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-
-            getExpectedResults(expectedResults, keys, lowKey, highKey, true, true);
-
-            if (results.size() == expectedResults.size()) {
-                for (int k = 0; k < results.size(); k++) {
-                    if (!results.get(k).equals(expectedResults.get(k))) {
-                        if (LOGGER.isInfoEnabled()) {
-                            LOGGER.info("DIFFERENT RESULTS AT: i=" + i + " k=" + k);
-                            LOGGER.info(results.get(k) + " " + expectedResults.get(k));
+                getExpectedResults(expectedResults, keys, lowKey, highKey, true, true);
+                if (results.size() == expectedResults.size()) {
+                    for (int k = 0; k < results.size(); k++) {
+                        if (!results.get(k).equals(expectedResults.get(k))) {
+                            if (LOGGER.isInfoEnabled()) {
+                                LOGGER.info("DIFFERENT RESULTS AT: i=" + i + " k=" + k);
+                                LOGGER.info(results.get(k) + " " + expectedResults.get(k));
+                            }
+                            return false;
                         }
-                        return false;
                     }
+                } else {
+                    if (LOGGER.isInfoEnabled()) {
+                        LOGGER.info("UNEQUAL NUMBER OF RESULTS AT: i=" + i);
+                        LOGGER.info("RESULTS: " + results.size());
+                        LOGGER.info("EXPECTED RESULTS: " + expectedResults.size());
+                    }
+                    return false;
                 }
-            } else {
-                if (LOGGER.isInfoEnabled()) {
-                    LOGGER.info("UNEQUAL NUMBER OF RESULTS AT: i=" + i);
-                    LOGGER.info("RESULTS: " + results.size());
-                    LOGGER.info("EXPECTED RESULTS: " + expectedResults.size());
-                }
-                return false;
             }
+        } finally {
+            pointCursor.destroy();;
         }
-
-        pointCursor.close();
-
         return true;
     }
 
     @Override
     protected void insertBTree(List<Integer> keys, BTree btree) throws HyracksDataException {
-        ArrayTupleBuilder tupleBuilder = new ArrayTupleBuilder(fieldCount);
+        bulkLoadBTree(keys, btree);
+    }
+
+    public static void bulkLoadBTree(List<Integer> keys, BTree btree) throws HyracksDataException {
+        ArrayTupleBuilder tupleBuilder = new ArrayTupleBuilder(FIELD_COUNT);
         ArrayTupleReference tuple = new ArrayTupleReference();
 
         IIndexBulkLoader bulkloader = btree.createBulkLoader(1, true, 0, true);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskOrderScanCursorTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskOrderScanCursorTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskOrderScanCursorTest.java
new file mode 100644
index 0000000..7cfd0fe
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/DiskOrderScanCursorTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.storage.am.btree;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeSet;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.storage.am.btree.impls.BTree;
+import org.apache.hyracks.storage.am.btree.impls.BTree.BTreeAccessor;
+import org.apache.hyracks.storage.am.btree.util.BTreeTestHarness;
+import org.apache.hyracks.storage.am.common.TestOperationCallback;
+import org.apache.hyracks.storage.am.common.api.IMetadataPageManager;
+import org.apache.hyracks.storage.am.common.api.ITreeIndexCursor;
+import org.apache.hyracks.storage.am.common.freepage.LinkedMetaDataPageManager;
+import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters;
+import org.apache.hyracks.storage.am.common.test.IIndexCursorTest;
+import org.apache.hyracks.storage.common.IIndexAccessor;
+import org.apache.hyracks.storage.common.IIndexCursor;
+import org.apache.hyracks.storage.common.ISearchPredicate;
+import org.apache.hyracks.storage.common.buffercache.IBufferCache;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+public class DiskOrderScanCursorTest extends IIndexCursorTest {
+    private static final BTreeTestHarness harness = new BTreeTestHarness();
+    private static BTree btree;
+
+    @BeforeClass
+    public static void setup() throws HyracksDataException {
+        harness.setUp();
+        IBufferCache bufferCache = harness.getBufferCache();
+        IMetadataPageManager freePageManager =
+                new LinkedMetaDataPageManager(bufferCache, BTreeSearchCursorTest.META_FRAME_FACTORY);
+        btree = new BTree(bufferCache, freePageManager, BTreeSearchCursorTest.INTERIOR_FRAME_FACTORY,
+                BTreeSearchCursorTest.LEAF_FRAME_FACTORY, BTreeSearchCursorTest.CMP_FACTORIES,
+                BTreeSearchCursorTest.FIELD_COUNT, harness.getFileReference());
+        btree.create();
+        btree.activate();
+        // generate keys
+        int numKeys = 50;
+        int maxKey = 1000;
+        TreeSet<Integer> uniqueKeys = new TreeSet<>();
+        ArrayList<Integer> keys = new ArrayList<>();
+        while (uniqueKeys.size() < numKeys) {
+            int key = BTreeSearchCursorTest.RANDOM.nextInt() % maxKey;
+            uniqueKeys.add(key);
+        }
+        for (Integer i : uniqueKeys) {
+            keys.add(i);
+        }
+        BTreeSearchCursorTest.staticInsertBTree(keys, btree);
+    }
+
+    @AfterClass
+    public static void tearDown() throws HyracksDataException {
+        try {
+            btree.deactivate();
+            btree.destroy();
+        } finally {
+            harness.tearDown();
+        }
+    }
+
+    @Override
+    protected List<ISearchPredicate> createSearchPredicates() throws HyracksDataException {
+        List<ISearchPredicate> predicates = new ArrayList<>();
+        int minKey = -10;
+        int maxKey = 10;
+        for (int i = minKey; i < maxKey; i++) {
+            for (int j = minKey; j < maxKey; j++) {
+                int lowKey = i;
+                int highKey = j;
+                predicates.add(BTreeSearchCursorTest.createRangePredicate(lowKey, highKey, true, true));
+            }
+        }
+        return predicates;
+    }
+
+    @Override
+    protected IIndexAccessor createAccessor() throws Exception {
+        return btree.createAccessor(
+                new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE));
+    }
+
+    @Override
+    protected void open(IIndexAccessor accessor, IIndexCursor cursor, ISearchPredicate predicate)
+            throws HyracksDataException {
+        ((BTreeAccessor) accessor).diskOrderScan((ITreeIndexCursor) cursor);
+    }
+
+    @Override
+    protected IIndexCursor createCursor(IIndexAccessor accessor) {
+        return ((BTreeAccessor) accessor).createDiskOrderScanCursor();
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/multithread/BTreeTestWorker.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/multithread/BTreeTestWorker.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/multithread/BTreeTestWorker.java
index 06a00e0..a67450b 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/multithread/BTreeTestWorker.java
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/org/apache/hyracks/storage/am/btree/multithread/BTreeTestWorker.java
@@ -56,90 +56,100 @@ public class BTreeTestWorker extends AbstractIndexTestWorker {
         ITreeIndexCursor diskOrderScanCursor = accessor.createDiskOrderScanCursor();
         MultiComparator cmp = accessor.getOpContext().getCmp();
         RangePredicate rangePred = new RangePredicate(tuple, tuple, true, true, cmp, cmp);
-
-        switch (op) {
-            case INSERT:
-                try {
-                    accessor.insert(tuple);
-                } catch (HyracksDataException e) {
-                    if (e.getErrorCode() != ErrorCode.DUPLICATE_KEY) {
-                        // Ignore duplicate keys, since we get random tuples.
-                        throw e;
+        try {
+            switch (op) {
+                case INSERT:
+                    try {
+                        accessor.insert(tuple);
+                    } catch (HyracksDataException e) {
+                        if (e.getErrorCode() != ErrorCode.DUPLICATE_KEY) {
+                            // Ignore duplicate keys, since we get random tuples.
+                            throw e;
+                        }
                     }
-                }
-                break;
+                    break;
 
-            case DELETE:
-                // Create a tuple reference with only key fields.
-                deleteTb.reset();
-                for (int i = 0; i < numKeyFields; i++) {
-                    deleteTb.addField(tuple.getFieldData(i), tuple.getFieldStart(i), tuple.getFieldLength(i));
-                }
-                deleteTuple.reset(deleteTb.getFieldEndOffsets(), deleteTb.getByteArray());
-                try {
-                    accessor.delete(deleteTuple);
-                } catch (HyracksDataException e) {
-                    if (e.getErrorCode() != ErrorCode.UPDATE_OR_DELETE_NON_EXISTENT_KEY) {
-                        // Ignore non-existant keys, since we get random tuples.
-                        throw e;
+                case DELETE:
+                    // Create a tuple reference with only key fields.
+                    deleteTb.reset();
+                    for (int i = 0; i < numKeyFields; i++) {
+                        deleteTb.addField(tuple.getFieldData(i), tuple.getFieldStart(i), tuple.getFieldLength(i));
+                    }
+                    deleteTuple.reset(deleteTb.getFieldEndOffsets(), deleteTb.getByteArray());
+                    try {
+                        accessor.delete(deleteTuple);
+                    } catch (HyracksDataException e) {
+                        if (e.getErrorCode() != ErrorCode.UPDATE_OR_DELETE_NON_EXISTENT_KEY) {
+                            // Ignore non-existant keys, since we get random tuples.
+                            throw e;
+                        }
                     }
-                }
-                break;
+                    break;
 
-            case UPDATE:
-                try {
-                    accessor.update(tuple);
-                } catch (HyracksDataException e) {
-                    // Ignore non-existant keys, since we get random tuples.
-                    if (e.getErrorCode() != ErrorCode.UPDATE_OR_DELETE_NON_EXISTENT_KEY
-                            && e.getErrorCode() != ErrorCode.INDEX_NOT_UPDATABLE) {
+                case UPDATE:
+                    try {
+                        accessor.update(tuple);
+                    } catch (HyracksDataException e) {
                         // Ignore non-existant keys, since we get random tuples.
-                        // Ignore not updateable exception due to numKeys == numFields.
-                        throw e;
+                        if (e.getErrorCode() != ErrorCode.UPDATE_OR_DELETE_NON_EXISTENT_KEY
+                                && e.getErrorCode() != ErrorCode.INDEX_NOT_UPDATABLE) {
+                            // Ignore non-existant keys, since we get random tuples.
+                            // Ignore not updateable exception due to numKeys == numFields.
+                            throw e;
+                        }
                     }
-                }
-                break;
+                    break;
 
-            case UPSERT:
-                accessor.upsert(tuple);
-                // Upsert should not throw. If it does, there's
-                // a bigger problem and the test should fail.
-                break;
+                case UPSERT:
+                    accessor.upsert(tuple);
+                    // Upsert should not throw. If it does, there's
+                    // a bigger problem and the test should fail.
+                    break;
 
-            case POINT_SEARCH:
-                searchCursor.close();
-                rangePred.setLowKey(tuple, true);
-                rangePred.setHighKey(tuple, true);
-                accessor.search(searchCursor, rangePred);
-                consumeCursorTuples(searchCursor);
-                break;
-
-            case SCAN:
-                searchCursor.close();
-                rangePred.setLowKey(null, true);
-                rangePred.setHighKey(null, true);
-                accessor.search(searchCursor, rangePred);
-                consumeCursorTuples(searchCursor);
-                break;
+                case POINT_SEARCH:
+                    searchCursor.close();
+                    rangePred.setLowKey(tuple, true);
+                    rangePred.setHighKey(tuple, true);
+                    accessor.search(searchCursor, rangePred);
+                    try {
+                        consumeCursorTuples(searchCursor);
+                    } finally {
+                        searchCursor.close();
+                    }
+                    break;
 
-            case DISKORDER_SCAN:
-                diskOrderScanCursor.close();
-                accessor.diskOrderScan(diskOrderScanCursor);
-                consumeCursorTuples(diskOrderScanCursor);
-                break;
+                case SCAN:
+                    searchCursor.close();
+                    rangePred.setLowKey(null, true);
+                    rangePred.setHighKey(null, true);
+                    accessor.search(searchCursor, rangePred);
+                    try {
+                        consumeCursorTuples(searchCursor);
+                    } finally {
+                        searchCursor.close();
+                    }
+                    break;
 
-            default:
-                throw new HyracksDataException("Op " + op.toString() + " not supported.");
+                case DISKORDER_SCAN:
+                    accessor.diskOrderScan(diskOrderScanCursor);
+                    try {
+                        consumeCursorTuples(diskOrderScanCursor);
+                    } finally {
+                        diskOrderScanCursor.close();
+                    }
+                    break;
+                default:
+                    throw new HyracksDataException("Op " + op.toString() + " not supported.");
+            }
+        } finally {
+            searchCursor.destroy();
+            diskOrderScanCursor.destroy();
         }
     }
 
     private void consumeCursorTuples(ITreeIndexCursor cursor) throws HyracksDataException {
-        try {
-            while (cursor.hasNext()) {
-                cursor.next();
-            }
-        } finally {
-            cursor.destroy();
+        while (cursor.hasNext()) {
+            cursor.next();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/pom.xml
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/pom.xml b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/pom.xml
index e5cbab2..46a8347 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/pom.xml
@@ -77,6 +77,13 @@
     </dependency>
     <dependency>
       <groupId>org.apache.hyracks</groupId>
+      <artifactId>hyracks-storage-am-common</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hyracks</groupId>
       <artifactId>hyracks-test-support</artifactId>
       <version>${project.version}</version>
     </dependency>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeExamplesTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeExamplesTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeExamplesTest.java
index 0c7eed8..aee7e90 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeExamplesTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeExamplesTest.java
@@ -19,8 +19,6 @@
 
 package org.apache.hyracks.storage.am.lsm.btree;
 
-import java.util.logging.Level;
-
 import org.apache.hyracks.api.dataflow.value.IBinaryComparatorFactory;
 import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.dataflow.value.ITypeTraits;
@@ -35,6 +33,7 @@ import org.apache.hyracks.storage.am.btree.OrderedIndexExamplesTest;
 import org.apache.hyracks.storage.am.common.TestOperationCallback;
 import org.apache.hyracks.storage.am.common.api.ITreeIndex;
 import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters;
+import org.apache.hyracks.storage.am.lsm.btree.impls.LSMBTree;
 import org.apache.hyracks.storage.am.lsm.btree.util.LSMBTreeTestHarness;
 import org.apache.hyracks.storage.am.lsm.btree.utils.LSMBTreeUtil;
 import org.apache.hyracks.storage.common.IIndexAccessor;
@@ -50,6 +49,14 @@ public class LSMBTreeExamplesTest extends OrderedIndexExamplesTest {
     protected ITreeIndex createTreeIndex(ITypeTraits[] typeTraits, IBinaryComparatorFactory[] cmpFactories,
             int[] bloomFilterKeyFields, ITypeTraits[] filterTypeTraits, IBinaryComparatorFactory[] filterCmpFactories,
             int[] btreeFields, int[] filterFields) throws HyracksDataException {
+        return createTreeIndex(harness, typeTraits, cmpFactories, bloomFilterKeyFields, filterTypeTraits,
+                filterCmpFactories, btreeFields, filterFields);
+    }
+
+    public static LSMBTree createTreeIndex(LSMBTreeTestHarness harness, ITypeTraits[] typeTraits,
+            IBinaryComparatorFactory[] cmpFactories, int[] bloomFilterKeyFields, ITypeTraits[] filterTypeTraits,
+            IBinaryComparatorFactory[] filterCmpFactories, int[] btreeFields, int[] filterFields)
+            throws HyracksDataException {
         return LSMBTreeUtil.createLSMTree(harness.getIOManager(), harness.getVirtualBufferCaches(),
                 harness.getFileReference(), harness.getDiskBufferCache(), typeTraits, cmpFactories,
                 bloomFilterKeyFields, harness.getBoomFilterFalsePositiveRate(), harness.getMergePolicy(),

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeMergeFailTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeMergeFailTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeMergeFailTest.java
index 4c325c0..475ab9c 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeMergeFailTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeMergeFailTest.java
@@ -150,7 +150,7 @@ public class LSMBTreeMergeFailTest {
         }
 
         @Override
-        public boolean hasNext() throws HyracksDataException {
+        public boolean doHasNext() throws HyracksDataException {
             throw new UnsupportedOperationException();
         }
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeSearchOperationCallbackTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeSearchOperationCallbackTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeSearchOperationCallbackTest.java
index 77d52bb..3dfb369 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeSearchOperationCallbackTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeSearchOperationCallbackTest.java
@@ -126,25 +126,30 @@ public class LSMBTreeSearchOperationCallbackTest extends AbstractSearchOperation
                 if (!insertTaskStarted) {
                     condition.await();
                 }
-
                 // begin a search on [50, +inf), blocking on 75
                 TupleUtils.createIntegerTuple(builder, tuple, 50);
                 predicate.setLowKey(tuple, true);
                 predicate.setHighKey(null, true);
                 accessor.search(cursor, predicate);
-                expectedTupleToBeLockedValue = 50;
-                TupleUtils.createIntegerTuple(builder, expectedTupleToBeLocked, expectedTupleToBeLockedValue);
-                consumeIntTupleRange(50, 75, true, 76);
-
-                // consume tuples [77, 150], blocking on 151
-                consumeIntTupleRange(77, 150, true, 150);
-
-                // consume tuples [152, 300]
-                consumeIntTupleRange(152, 300, false, -1);
-
-                cursor.destroy();
+                try {
+                    expectedTupleToBeLockedValue = 50;
+                    TupleUtils.createIntegerTuple(builder, expectedTupleToBeLocked, expectedTupleToBeLockedValue);
+                    consumeIntTupleRange(50, 75, true, 76);
+
+                    // consume tuples [77, 150], blocking on 151
+                    consumeIntTupleRange(77, 150, true, 150);
+
+                    // consume tuples [152, 300]
+                    consumeIntTupleRange(152, 300, false, -1);
+                } finally {
+                    cursor.close();
+                }
             } finally {
-                lock.unlock();
+                try {
+                    cursor.destroy();
+                } finally {
+                    lock.unlock();
+                }
             }
 
             return true;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeUpdateInPlaceScanDiskComponentsTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeUpdateInPlaceScanDiskComponentsTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeUpdateInPlaceScanDiskComponentsTest.java
index 035ef98..3a48160 100644
--- a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeUpdateInPlaceScanDiskComponentsTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/LSMBTreeUpdateInPlaceScanDiskComponentsTest.java
@@ -27,7 +27,6 @@ import java.io.DataInputStream;
 import java.util.Random;
 import java.util.SortedSet;
 import java.util.TreeSet;
-import java.util.logging.Level;
 
 import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.exceptions.ErrorCode;
@@ -369,13 +368,17 @@ public class LSMBTreeUpdateInPlaceScanDiskComponentsTest extends OrderedIndexTes
         ITreeIndexCursor cursor = btreeAccessor.createDiskOrderScanCursor();
         try {
             btreeAccessor.diskOrderScan(cursor);
-            for (UpdatedCheckTuple t : checkTuples) {
-                if (!t.isUpdated() || !hasOnlyKeys) {
-                    checkReturnedTuple((LSMBTreeTupleReference) getNext(cursor), ctx.getFieldSerdes(), t,
-                            ctx.getKeyFieldCount());
+            try {
+                for (UpdatedCheckTuple t : checkTuples) {
+                    if (!t.isUpdated() || !hasOnlyKeys) {
+                        checkReturnedTuple((LSMBTreeTupleReference) getNext(cursor), ctx.getFieldSerdes(), t,
+                                ctx.getKeyFieldCount());
+                    }
                 }
+                Assert.assertFalse(cursor.hasNext());
+            } finally {
+                cursor.close();
             }
-            Assert.assertFalse(cursor.hasNext());
         } finally {
             cursor.destroy();
         }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/cursor/LSMBTreePointSearchCursorTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/cursor/LSMBTreePointSearchCursorTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/cursor/LSMBTreePointSearchCursorTest.java
new file mode 100644
index 0000000..18d89ca
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/cursor/LSMBTreePointSearchCursorTest.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.storage.am.lsm.btree.cursor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.hyracks.api.dataflow.value.IBinaryComparatorFactory;
+import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.dataflow.value.ITypeTraits;
+import org.apache.hyracks.api.exceptions.ErrorCode;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.accessors.PointableBinaryComparatorFactory;
+import org.apache.hyracks.data.std.primitive.IntegerPointable;
+import org.apache.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
+import org.apache.hyracks.dataflow.common.comm.io.ArrayTupleReference;
+import org.apache.hyracks.dataflow.common.data.marshalling.IntegerSerializerDeserializer;
+import org.apache.hyracks.dataflow.common.utils.TupleUtils;
+import org.apache.hyracks.storage.am.btree.impls.RangePredicate;
+import org.apache.hyracks.storage.am.btree.util.BTreeUtils;
+import org.apache.hyracks.storage.am.common.TestOperationCallback;
+import org.apache.hyracks.storage.am.common.api.ITreeIndex;
+import org.apache.hyracks.storage.am.common.impls.IndexAccessParameters;
+import org.apache.hyracks.storage.am.common.impls.NoOpIndexAccessParameters;
+import org.apache.hyracks.storage.am.common.impls.NoOpOperationCallback;
+import org.apache.hyracks.storage.am.common.ophelpers.IndexOperation;
+import org.apache.hyracks.storage.am.common.test.IIndexCursorTest;
+import org.apache.hyracks.storage.am.lsm.btree.LSMBTreeExamplesTest;
+import org.apache.hyracks.storage.am.lsm.btree.impls.LSMBTree;
+import org.apache.hyracks.storage.am.lsm.btree.impls.LSMBTreeOpContext;
+import org.apache.hyracks.storage.am.lsm.btree.impls.LSMBTreePointSearchCursor;
+import org.apache.hyracks.storage.am.lsm.btree.util.LSMBTreeTestHarness;
+import org.apache.hyracks.storage.common.IIndexAccessor;
+import org.apache.hyracks.storage.common.IIndexCursor;
+import org.apache.hyracks.storage.common.ISearchPredicate;
+import org.apache.hyracks.storage.common.MultiComparator;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+public class LSMBTreePointSearchCursorTest extends IIndexCursorTest {
+    public static final int FIELD_COUNT = 2;
+    public static final ITypeTraits[] TYPE_TRAITS = { IntegerPointable.TYPE_TRAITS, IntegerPointable.TYPE_TRAITS };
+    @SuppressWarnings("rawtypes")
+    public static final ISerializerDeserializer[] FIELD_SERDES =
+            { IntegerSerializerDeserializer.INSTANCE, IntegerSerializerDeserializer.INSTANCE };
+    public static final int KEY_FIELD_COUNT = 1;
+    public static final IBinaryComparatorFactory[] CMP_FACTORIES =
+            { PointableBinaryComparatorFactory.of(IntegerPointable.FACTORY) };
+    public static final int[] BLOOM_FILTER_KEY_FIELDS = { 0 };
+    public static final Random RND = new Random(50);
+
+    private static final LSMBTreeTestHarness harness = new LSMBTreeTestHarness();
+    private static LSMBTree lsmBtree;
+    private static LSMBTreeOpContext opCtx;
+
+    @BeforeClass
+    public static void setup() throws HyracksDataException {
+        harness.setUp();
+        lsmBtree = LSMBTreeExamplesTest.createTreeIndex(harness, TYPE_TRAITS, CMP_FACTORIES, BLOOM_FILTER_KEY_FIELDS,
+                null, null, null, null);
+        lsmBtree.create();
+        lsmBtree.activate();
+        insertData(lsmBtree);
+    }
+
+    @AfterClass
+    public static void teardown() throws HyracksDataException {
+        try {
+            lsmBtree.deactivate();
+            lsmBtree.destroy();
+        } finally {
+            harness.tearDown();
+        }
+    }
+
+    @Override
+    protected List<ISearchPredicate> createSearchPredicates() throws Exception {
+        List<ISearchPredicate> predicates = new ArrayList<>();
+        for (int i = 0; i < 10; i++) {
+            // Build low key.
+            ArrayTupleBuilder lowKeyTb = new ArrayTupleBuilder(KEY_FIELD_COUNT);
+            ArrayTupleReference lowKey = new ArrayTupleReference();
+            TupleUtils.createIntegerTuple(lowKeyTb, lowKey, -100 + (i * 50));
+
+            // Build high key.
+            ArrayTupleBuilder highKeyTb = new ArrayTupleBuilder(KEY_FIELD_COUNT);
+            ArrayTupleReference highKey = new ArrayTupleReference();
+            TupleUtils.createIntegerTuple(highKeyTb, highKey, -100 + (i * 50));
+
+            MultiComparator lowKeySearchCmp = BTreeUtils.getSearchMultiComparator(CMP_FACTORIES, lowKey);
+            MultiComparator highKeySearchCmp = BTreeUtils.getSearchMultiComparator(CMP_FACTORIES, highKey);
+            predicates.add(new RangePredicate(lowKey, highKey, true, true, lowKeySearchCmp, highKeySearchCmp));
+        }
+        return predicates;
+    }
+
+    @Override
+    protected IIndexCursor createCursor(IIndexAccessor accessor) {
+        opCtx = lsmBtree.createOpContext(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        return new LSMBTreePointSearchCursor(opCtx);
+    }
+
+    @Override
+    protected void open(IIndexAccessor accessor, IIndexCursor cursor, ISearchPredicate predicate)
+            throws HyracksDataException {
+        opCtx.reset();
+        opCtx.setOperation(IndexOperation.SEARCH);
+        lsmBtree.getOperationalComponents(opCtx);
+        opCtx.getSearchInitialState().reset(predicate, opCtx.getComponentHolder());
+        cursor.open(opCtx.getSearchInitialState(), predicate);
+    }
+
+    @Override
+    protected IIndexAccessor createAccessor() throws Exception {
+        return lsmBtree.createAccessor(NoOpIndexAccessParameters.INSTANCE);
+    }
+
+    public static void insertData(ITreeIndex lsmBtree) throws HyracksDataException {
+        ArrayTupleBuilder tb = new ArrayTupleBuilder(FIELD_COUNT);
+        ArrayTupleReference tuple = new ArrayTupleReference();
+        IndexAccessParameters actx =
+                new IndexAccessParameters(TestOperationCallback.INSTANCE, TestOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = lsmBtree.createAccessor(actx);
+        try {
+            int numInserts = 10000;
+            for (int i = 0; i < numInserts; i++) {
+                int f0 = RND.nextInt() % numInserts;
+                int f1 = 5;
+                TupleUtils.createIntegerTuple(tb, tuple, f0, f1);
+                try {
+                    indexAccessor.insert(tuple);
+                } catch (HyracksDataException e) {
+                    if (e.getErrorCode() != ErrorCode.DUPLICATE_KEY) {
+                        e.printStackTrace();
+                        throw e;
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    throw e;
+                }
+            }
+        } finally {
+            indexAccessor.destroy();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/4ff6a36d/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/cursor/LSMBTreeRangeSearchCursorTest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/cursor/LSMBTreeRangeSearchCursorTest.java b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/cursor/LSMBTreeRangeSearchCursorTest.java
new file mode 100644
index 0000000..e436596
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/org/apache/hyracks/storage/am/lsm/btree/cursor/LSMBTreeRangeSearchCursorTest.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.storage.am.lsm.btree.cursor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
+import org.apache.hyracks.dataflow.common.comm.io.ArrayTupleReference;
+import org.apache.hyracks.dataflow.common.utils.TupleUtils;
+import org.apache.hyracks.storage.am.btree.impls.RangePredicate;
+import org.apache.hyracks.storage.am.btree.util.BTreeUtils;
+import org.apache.hyracks.storage.am.common.impls.NoOpIndexAccessParameters;
+import org.apache.hyracks.storage.am.common.impls.NoOpOperationCallback;
+import org.apache.hyracks.storage.am.common.ophelpers.IndexOperation;
+import org.apache.hyracks.storage.am.common.test.IIndexCursorTest;
+import org.apache.hyracks.storage.am.lsm.btree.LSMBTreeExamplesTest;
+import org.apache.hyracks.storage.am.lsm.btree.impls.LSMBTree;
+import org.apache.hyracks.storage.am.lsm.btree.impls.LSMBTreeOpContext;
+import org.apache.hyracks.storage.am.lsm.btree.impls.LSMBTreeRangeSearchCursor;
+import org.apache.hyracks.storage.am.lsm.btree.util.LSMBTreeTestHarness;
+import org.apache.hyracks.storage.common.IIndexAccessor;
+import org.apache.hyracks.storage.common.IIndexCursor;
+import org.apache.hyracks.storage.common.ISearchPredicate;
+import org.apache.hyracks.storage.common.MultiComparator;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+public class LSMBTreeRangeSearchCursorTest extends IIndexCursorTest {
+
+    private static final LSMBTreeTestHarness harness = new LSMBTreeTestHarness();
+    private static LSMBTree lsmBtree;
+    private static LSMBTreeOpContext opCtx;
+
+    @BeforeClass
+    public static void setup() throws HyracksDataException {
+        harness.setUp();
+        lsmBtree = LSMBTreeExamplesTest.createTreeIndex(harness, LSMBTreePointSearchCursorTest.TYPE_TRAITS,
+                LSMBTreePointSearchCursorTest.CMP_FACTORIES, LSMBTreePointSearchCursorTest.BLOOM_FILTER_KEY_FIELDS,
+                null, null, null, null);
+        lsmBtree.create();
+        lsmBtree.activate();
+        LSMBTreePointSearchCursorTest.insertData(lsmBtree);
+    }
+
+    @AfterClass
+    public static void teardown() throws HyracksDataException {
+        try {
+            lsmBtree.deactivate();
+            lsmBtree.destroy();
+        } finally {
+            harness.tearDown();
+        }
+    }
+
+    @Override
+    protected List<ISearchPredicate> createSearchPredicates() throws Exception {
+        // windows of length = 50
+        List<ISearchPredicate> predicates = new ArrayList<>();
+        for (int i = 0; i < 10; i++) {
+            // Build low key.
+            ArrayTupleBuilder lowKeyTb = new ArrayTupleBuilder(LSMBTreePointSearchCursorTest.KEY_FIELD_COUNT);
+            ArrayTupleReference lowKey = new ArrayTupleReference();
+            TupleUtils.createIntegerTuple(lowKeyTb, lowKey, -100 + (i * 50));
+            // Build high key.
+            ArrayTupleBuilder highKeyTb = new ArrayTupleBuilder(LSMBTreePointSearchCursorTest.KEY_FIELD_COUNT);
+            ArrayTupleReference highKey = new ArrayTupleReference();
+            TupleUtils.createIntegerTuple(highKeyTb, highKey, -100 + (i * 50) + 50);
+            MultiComparator lowKeySearchCmp =
+                    BTreeUtils.getSearchMultiComparator(LSMBTreePointSearchCursorTest.CMP_FACTORIES, lowKey);
+            MultiComparator highKeySearchCmp =
+                    BTreeUtils.getSearchMultiComparator(LSMBTreePointSearchCursorTest.CMP_FACTORIES, highKey);
+            predicates.add(new RangePredicate(lowKey, highKey, true, true, lowKeySearchCmp, highKeySearchCmp));
+        }
+        return predicates;
+    }
+
+    @Override
+    protected IIndexCursor createCursor(IIndexAccessor accessor) {
+        opCtx = lsmBtree.createOpContext(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        return new LSMBTreeRangeSearchCursor(opCtx);
+    }
+
+    @Override
+    protected void open(IIndexAccessor accessor, IIndexCursor cursor, ISearchPredicate predicate)
+            throws HyracksDataException {
+        opCtx.reset();
+        opCtx.setOperation(IndexOperation.SEARCH);
+        lsmBtree.getOperationalComponents(opCtx);
+        opCtx.getSearchInitialState().reset(predicate, opCtx.getComponentHolder());
+        cursor.open(opCtx.getSearchInitialState(), predicate);
+    }
+
+    @Override
+    protected IIndexAccessor createAccessor() throws Exception {
+        return lsmBtree.createAccessor(NoOpIndexAccessParameters.INSTANCE);
+    }
+
+}