Added search cursor for the r tree

git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_indexes@470 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-tests/hyracks-storage-am-rtree-test/pom.xml b/hyracks-tests/hyracks-storage-am-rtree-test/pom.xml
index 36d4988..2090bb2 100644
--- a/hyracks-tests/hyracks-storage-am-rtree-test/pom.xml
+++ b/hyracks-tests/hyracks-storage-am-rtree-test/pom.xml
@@ -2,12 +2,12 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>edu.uci.ics.hyracks</groupId>
   <artifactId>hyracks-storage-am-rtree-test</artifactId>
-  <version>0.1.4</version>
+  <version>0.1.5</version>
 
   <parent>
     <groupId>edu.uci.ics.hyracks</groupId>
     <artifactId>hyracks-tests</artifactId>
-    <version>0.1.4</version>
+    <version>0.1.5</version>
   </parent>
 
   <build>
@@ -40,14 +40,14 @@
   	<dependency>
   		<groupId>edu.uci.ics.hyracks</groupId>
   		<artifactId>hyracks-storage-am-rtree</artifactId>
-  		<version>0.1.4</version>
+  		<version>0.1.5</version>
   		<type>jar</type>
   		<scope>compile</scope>
   	</dependency>
   	<dependency>
   		<groupId>edu.uci.ics.hyracks</groupId>
   		<artifactId>hyracks-test-support</artifactId>
-  		<version>0.1.4</version>
+  		<version>0.1.5</version>
   		<type>jar</type>
   		<scope>test</scope>
   	</dependency>
diff --git a/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeFrameTest.java b/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeFrameTest.java
deleted file mode 100644
index f93a6b6..0000000
--- a/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeFrameTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * package edu.uci.ics.hyracks.storage.am.rtree;
- * 
- * import java.io.DataOutput; import java.io.File; import java.nio.ByteBuffer;
- * import java.util.Random;
- * 
- * import org.junit.Test;
- * 
- * import edu.uci.ics.hyracks.api.comm.IFrameTupleAccessor; import
- * edu.uci.ics.hyracks.api.context.IHyracksStageletContext; import
- * edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparator; import
- * edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer; import
- * edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait; import
- * edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor; import
- * edu.uci.ics.hyracks.api.dataflow.value.TypeTrait; import
- * edu.uci.ics.hyracks.api.io.FileReference; import
- * edu.uci.ics.hyracks.dataflow.common.comm.io.ArrayTupleBuilder; import
- * edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAccessor; import
- * edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAppender; import
- * edu.uci.ics.hyracks.dataflow.common.data.accessors.FrameTupleReference;
- * import edu.uci.ics.hyracks.dataflow.common.data.comparators.
- * DoubleBinaryComparatorFactory; import
- * edu.uci.ics.hyracks.dataflow.common.data
- * .marshalling.DoubleSerializerDeserializer; import
- * edu.uci.ics.hyracks.dataflow
- * .common.data.marshalling.IntegerSerializerDeserializer; import
- * edu.uci.ics.hyracks.storage.am.btree.impls.MultiComparator; import
- * edu.uci.ics.hyracks.storage.am.btree.impls.SpaceStatus; import
- * edu.uci.ics.hyracks.storage.am.btree.tuples.TypeAwareTupleWriter; import
- * edu.uci.ics.hyracks.storage.am.rtree.frames.NSMRTreeFrame; import
- * edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache; import
- * edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage; import
- * edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle; import
- * edu.uci.ics.hyracks.storage.common.file.IFileMapProvider; import
- * edu.uci.ics.hyracks.test.support.TestStorageManagerComponentHolder; import
- * edu.uci.ics.hyracks.test.support.TestUtils;
- * 
- * public class RTreeFrameTest extends AbstractRTreeTest {
- * 
- * private static final int PAGE_SIZE = 256; private static final int NUM_PAGES
- * = 10; private static final int HYRACKS_FRAME_SIZE = 128; private
- * IHyracksStageletContext ctx = TestUtils.create(HYRACKS_FRAME_SIZE);
- * 
- * private String tmpDir = System.getProperty("java.io.tmpdir");
- * 
- * @Test public void frameInsertTest() throws Exception {
- * 
- * TestStorageManagerComponentHolder.init(PAGE_SIZE, NUM_PAGES); IBufferCache
- * bufferCache = TestStorageManagerComponentHolder .getBufferCache(ctx);
- * IFileMapProvider fmp = TestStorageManagerComponentHolder
- * .getFileMapProvider(ctx); FileReference file = new FileReference(new
- * File(fileName)); bufferCache.createFile(file); int fileId =
- * fmp.lookupFileId(file); bufferCache.openFile(fileId);
- * 
- * // declare fields int fieldCount = 5; ITypeTrait[] typeTraits = new
- * ITypeTrait[fieldCount]; typeTraits[0] = new TypeTrait(8); typeTraits[1] = new
- * TypeTrait(8); typeTraits[2] = new TypeTrait(8); typeTraits[3] = new
- * TypeTrait(8); typeTraits[4] = new TypeTrait(4);
- * 
- * // declare keys int keyFieldCount = 4; IBinaryComparator[] cmps = new
- * IBinaryComparator[keyFieldCount]; cmps[0] =
- * DoubleBinaryComparatorFactory.INSTANCE.createBinaryComparator(); cmps[1] =
- * cmps[0]; cmps[2] = cmps[0]; cmps[3] = cmps[0];
- * 
- * MultiComparator cmp = new MultiComparator(typeTraits, cmps);
- * 
- * TypeAwareTupleWriter tupleWriter = new TypeAwareTupleWriter(typeTraits);
- * //SimpleTupleWriter tupleWriter = new SimpleTupleWriter(); NSMRTreeFrame
- * rtreeFrame = new NSMRTreeFrame(tupleWriter);
- * 
- * ByteBuffer hyracksFrame = ctx.allocateFrame(); FrameTupleAppender appender =
- * new FrameTupleAppender(ctx.getFrameSize()); ArrayTupleBuilder tb = new
- * ArrayTupleBuilder(cmp.getFieldCount()); DataOutput dos = tb.getDataOutput();
- * 
- * ISerializerDeserializer[] recDescSers = {
- * DoubleSerializerDeserializer.INSTANCE, DoubleSerializerDeserializer.INSTANCE,
- * DoubleSerializerDeserializer.INSTANCE, DoubleSerializerDeserializer.INSTANCE,
- * DoubleSerializerDeserializer.INSTANCE }; RecordDescriptor recDesc = new
- * RecordDescriptor(recDescSers); IFrameTupleAccessor accessor = new
- * FrameTupleAccessor(ctx .getFrameSize(), recDesc); FrameTupleReference tuple =
- * new FrameTupleReference();
- * 
- * ICachedPage page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId,
- * 0), true); try {
- * 
- * rtreeFrame.setPage(page); rtreeFrame.initBuffer((byte)0);
- * 
- * // insert some random stuff...
- * 
- * Random rnd = new Random(50);
- * 
- * int numInserts = 10; for (int i = 0; i < numInserts; i++) { double p1x =
- * rnd.nextDouble(); double p1y = rnd.nextDouble(); double p2x =
- * rnd.nextDouble(); double p2y = rnd.nextDouble();
- * 
- * int pk = rnd.nextInt();
- * 
- * tb.reset(); DoubleSerializerDeserializer.INSTANCE.serialize(p1x, dos);
- * tb.addFieldEndOffset(); DoubleSerializerDeserializer.INSTANCE.serialize(p1y,
- * dos); tb.addFieldEndOffset();
- * DoubleSerializerDeserializer.INSTANCE.serialize(p2x, dos);
- * tb.addFieldEndOffset(); DoubleSerializerDeserializer.INSTANCE.serialize(p2y,
- * dos); tb.addFieldEndOffset();
- * IntegerSerializerDeserializer.INSTANCE.serialize(pk, dos);
- * tb.addFieldEndOffset();
- * 
- * appender.reset(hyracksFrame, true); appender.append(tb.getFieldEndOffsets(),
- * tb.getByteArray(), 0, tb.getSize());
- * 
- * tuple.reset(accessor, 0);
- * 
- * SpaceStatus status = rtreeFrame.hasSpaceInsert(tuple, cmp); switch(status) {
- * case SUFFICIENT_CONTIGUOUS_SPACE: { rtreeFrame.insert(tuple, cmp); break; }
- * 
- * case SUFFICIENT_SPACE: { rtreeFrame.compact(cmp); rtreeFrame.insert(tuple,
- * cmp); break; }
- * 
- * case INSUFFICIENT_SPACE: { // split
- * System.out.println("PLEASE STOP, NO MORE SPACE"); break; } }
- * 
- * 
- * 
- * String contents = rtreeFrame.printKeys(cmp, recDescSers);
- * System.out.println(contents);
- * 
- * } } finally { bufferCache.unpin(page); }
- * 
- * bufferCache.closeFile(fileId); bufferCache.close();
- * 
- * }
- * 
- * }
- */
\ No newline at end of file
diff --git a/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeTest.java b/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeTest.java
index 815ef19..b105588 100644
--- a/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeTest.java
+++ b/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeTest.java
@@ -53,7 +53,7 @@
     private static final int HYRACKS_FRAME_SIZE = 128;
     private IHyracksStageletContext ctx = TestUtils.create(HYRACKS_FRAME_SIZE);
 
-     @Test
+    @Test
     public void test01() throws Exception {
 
         TestStorageManagerComponentHolder.init(PAGE_SIZE, NUM_PAGES);
@@ -97,8 +97,8 @@
                 interiorTypeTraits);
         RTreeTypeAwareTupleWriterFactory leafTupleWriterFactory = new RTreeTypeAwareTupleWriterFactory(leafTypeTraits);
 
-        IRTreeFrameFactory interiorFrameFactory = new NSMRTreeFrameFactory(interiorTupleWriterFactory);
-        IRTreeFrameFactory leafFrameFactory = new NSMRTreeFrameFactory(leafTupleWriterFactory);
+        IRTreeFrameFactory interiorFrameFactory = new NSMRTreeFrameFactory(interiorTupleWriterFactory, keyFieldCount);
+        IRTreeFrameFactory leafFrameFactory = new NSMRTreeFrameFactory(leafTupleWriterFactory, keyFieldCount);
         ITreeIndexMetaDataFrameFactory metaFrameFactory = new LIFOMetaDataFrameFactory();
         ITreeIndexMetaDataFrame metaFrame = metaFrameFactory.getFrame();
 
@@ -106,9 +106,8 @@
         IRTreeFrame leafFrame = leafFrameFactory.getFrame();
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
 
-        int dim = 2;
         RTree rtree = new RTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, interiorCmp,
-                leafCmp, dim);
+                leafCmp);
         rtree.create(fileId, leafFrame, metaFrame);
         rtree.open(fileId);
 
@@ -126,7 +125,8 @@
         accessor.reset(hyracksFrame);
         FrameTupleReference tuple = new FrameTupleReference();
 
-        RTreeOpContext insertOpCtx = rtree.createOpContext(TreeIndexOp.TI_INSERT, interiorFrame, leafFrame, metaFrame, "unittest");
+        RTreeOpContext insertOpCtx = rtree.createOpContext(TreeIndexOp.TI_INSERT, interiorFrame, leafFrame, metaFrame,
+                "unittest");
 
         Random rnd = new Random();
         rnd.setSeed(50);
@@ -172,7 +172,8 @@
         // rtree.printTree(leafFrame, interiorFrame, recDescSers);
         // System.out.println();
 
-        RTreeOpContext searchOpCtx = rtree.createOpContext(TreeIndexOp.TI_SEARCH, interiorFrame, leafFrame, metaFrame, "unittest");
+        RTreeOpContext searchOpCtx = rtree.createOpContext(TreeIndexOp.TI_SEARCH, interiorFrame, leafFrame, metaFrame,
+                "unittest");
         ArrayList<Rectangle> results = new ArrayList<Rectangle>();
         rtree.search(s, tuple, searchOpCtx, results);
 
@@ -194,7 +195,7 @@
 
     }
 
-    //@Test
+    // @Test
     public void test02() throws Exception {
 
         TestStorageManagerComponentHolder.init(PAGE_SIZE, NUM_PAGES);
@@ -238,8 +239,8 @@
                 interiorTypeTraits);
         RTreeTypeAwareTupleWriterFactory leafTupleWriterFactory = new RTreeTypeAwareTupleWriterFactory(leafTypeTraits);
 
-        IRTreeFrameFactory interiorFrameFactory = new NSMRTreeFrameFactory(interiorTupleWriterFactory);
-        IRTreeFrameFactory leafFrameFactory = new NSMRTreeFrameFactory(leafTupleWriterFactory);
+        IRTreeFrameFactory interiorFrameFactory = new NSMRTreeFrameFactory(interiorTupleWriterFactory, keyFieldCount);
+        IRTreeFrameFactory leafFrameFactory = new NSMRTreeFrameFactory(leafTupleWriterFactory, keyFieldCount);
         ITreeIndexMetaDataFrameFactory metaFrameFactory = new LIFOMetaDataFrameFactory();
         ITreeIndexMetaDataFrame metaFrame = metaFrameFactory.getFrame();
 
@@ -247,9 +248,8 @@
         IRTreeFrame leafFrame = leafFrameFactory.getFrame();
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
 
-        int dim = 2;
         RTree rtree = new RTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, interiorCmp,
-                leafCmp, dim);
+                leafCmp);
         rtree.create(fileId, leafFrame, metaFrame);
         rtree.open(fileId);
 
@@ -267,7 +267,8 @@
         accessor.reset(hyracksFrame);
         FrameTupleReference tuple = new FrameTupleReference();
 
-        RTreeOpContext insertOpCtx = rtree.createOpContext(TreeIndexOp.TI_INSERT, interiorFrame, leafFrame, metaFrame, "unittest");
+        RTreeOpContext insertOpCtx = rtree.createOpContext(TreeIndexOp.TI_INSERT, interiorFrame, leafFrame, metaFrame,
+                "unittest");
 
         File datasetFile = new File("/home/salsubaiee/dataset.txt");
         BufferedReader reader = new BufferedReader(new FileReader(datasetFile));
@@ -284,7 +285,7 @@
 
             double p1x = 0;
             double p1y = 0;
-            
+
             try {
                 p1x = Double.valueOf(splittedLine2[1].trim()).doubleValue();
                 p1y = Double.valueOf(splittedLine2[2].trim()).doubleValue();
@@ -294,7 +295,6 @@
             }
             double p2x = p1x;
             double p2y = p1y;
-            
 
             int pk = rnd.nextInt();
 
@@ -325,21 +325,22 @@
             } catch (Exception e) {
                 e.printStackTrace();
             }
-            
+
             if (index == 1000) {
                 break;
             }
             inputLine = reader.readLine();
             index++;
 
-//            rtree.printTree(leafFrame, interiorFrame, recDescSers);
-//            System.out.println();
+            // rtree.printTree(leafFrame, interiorFrame, recDescSers);
+            // System.out.println();
         }
 
-        //rtree.printTree(leafFrame, interiorFrame, recDescSers);
-        //System.out.println();
+        // rtree.printTree(leafFrame, interiorFrame, recDescSers);
+        // System.out.println();
 
-        RTreeOpContext searchOpCtx = rtree.createOpContext(TreeIndexOp.TI_SEARCH, interiorFrame, leafFrame, metaFrame, "unittest");
+        RTreeOpContext searchOpCtx = rtree.createOpContext(TreeIndexOp.TI_SEARCH, interiorFrame, leafFrame, metaFrame,
+                "unittest");
 
         File querysetFile = new File("/home/salsubaiee/queryset.txt");
         BufferedReader reader2 = new BufferedReader(new FileReader(querysetFile));
@@ -353,7 +354,6 @@
             String[] splittedLine1 = inputLine.split(",");
             String[] splittedLine2 = splittedLine1[0].split("\\s");
 
-            
             double p1x;
             double p1y;
             double p2x;
@@ -368,7 +368,7 @@
                 inputLine = reader2.readLine();
                 continue;
             }
-            
+
             int pk = rnd.nextInt();
 
             tb.reset();
@@ -408,16 +408,12 @@
 
         System.out.println("Number of Results: " + totalResults);
 
-//        String stats = rtree.printStats();
-//        print(stats);
-        
-        
-        
-        
-        
-        RTreeOpContext deleteOpCtx = rtree.createOpContext(TreeIndexOp.TI_DELETE, interiorFrame, leafFrame, metaFrame, "unittest");
+        // String stats = rtree.printStats();
+        // print(stats);
 
-        
+        RTreeOpContext deleteOpCtx = rtree.createOpContext(TreeIndexOp.TI_DELETE, interiorFrame, leafFrame, metaFrame,
+                "unittest");
+
         BufferedReader reader3 = new BufferedReader(new FileReader(datasetFile));
         inputLine = reader3.readLine();
         index = 0;
@@ -429,7 +425,7 @@
 
             double p1x = 0;
             double p1y = 0;
-            
+
             try {
                 p1x = Double.valueOf(splittedLine2[1].trim()).doubleValue();
                 p1y = Double.valueOf(splittedLine2[2].trim()).doubleValue();
@@ -468,22 +464,17 @@
             } catch (Exception e) {
                 e.printStackTrace();
             }
-            
+
             if (index == 1000) {
                 break;
             }
             inputLine = reader3.readLine();
             index++;
 
-//            rtree.printTree(leafFrame, interiorFrame, recDescSers);
-//            System.out.println();
+            // rtree.printTree(leafFrame, interiorFrame, recDescSers);
+            // System.out.println();
         }
-        
-        
-        
-        
-        
-        
+
         BufferedReader reader4 = new BufferedReader(new FileReader(querysetFile));
 
         inputLine = reader4.readLine();
@@ -538,19 +529,12 @@
 
         System.out.println("Number of Results: " + totalResults);
 
-//        stats = rtree.printStats();
-//        print(stats);
-        
-        
-        
-        
-        
+        // stats = rtree.printStats();
+        // print(stats);
+
         rtree.printTree(leafFrame, interiorFrame, recDescSers);
         System.out.println();
 
-
-        
-
         rtree.close();
         bufferCache.closeFile(fileId);
         bufferCache.close();
diff --git a/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/SearchCursorTest.java b/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/SearchCursorTest.java
new file mode 100644
index 0000000..a5f0594
--- /dev/null
+++ b/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/SearchCursorTest.java
@@ -0,0 +1,198 @@
+package edu.uci.ics.hyracks.storage.am.rtree;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Random;
+
+import org.junit.Test;
+
+import edu.uci.ics.hyracks.api.comm.IFrameTupleAccessor;
+import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparator;
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
+import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
+import edu.uci.ics.hyracks.api.dataflow.value.TypeTrait;
+import edu.uci.ics.hyracks.api.io.FileReference;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAccessor;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAppender;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.FrameTupleReference;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+import edu.uci.ics.hyracks.dataflow.common.data.comparators.DoubleBinaryComparatorFactory;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.DoubleSerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.IntegerSerializerDeserializer;
+import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrameFactory;
+import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
+import edu.uci.ics.hyracks.storage.am.common.frames.LIFOMetaDataFrameFactory;
+import edu.uci.ics.hyracks.storage.am.common.freepage.LinkedListFreePageManager;
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.TreeIndexOp;
+import edu.uci.ics.hyracks.storage.am.rtree.api.IRTreeCursor;
+import edu.uci.ics.hyracks.storage.am.rtree.api.IRTreeFrame;
+import edu.uci.ics.hyracks.storage.am.rtree.api.IRTreeFrameFactory;
+import edu.uci.ics.hyracks.storage.am.rtree.frames.NSMRTreeFrameFactory;
+import edu.uci.ics.hyracks.storage.am.rtree.impls.RTree;
+import edu.uci.ics.hyracks.storage.am.rtree.impls.RTreeOpContext;
+import edu.uci.ics.hyracks.storage.am.rtree.impls.SearchCursor;
+import edu.uci.ics.hyracks.storage.am.rtree.tuples.RTreeTypeAwareTupleWriterFactory;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
+import edu.uci.ics.hyracks.test.support.TestStorageManagerComponentHolder;
+import edu.uci.ics.hyracks.test.support.TestUtils;
+
+public class SearchCursorTest extends AbstractRTreeTest {
+    private static final int PAGE_SIZE = 256;
+    private static final int NUM_PAGES = 10;
+    private static final int HYRACKS_FRAME_SIZE = 128;
+    private IHyracksStageletContext ctx = TestUtils.create(HYRACKS_FRAME_SIZE);
+
+    @Test
+    public void searchCursorTest() throws Exception {
+
+        TestStorageManagerComponentHolder.init(PAGE_SIZE, NUM_PAGES);
+        IBufferCache bufferCache = TestStorageManagerComponentHolder.getBufferCache(ctx);
+        IFileMapProvider fmp = TestStorageManagerComponentHolder.getFileMapProvider(ctx);
+        FileReference file = new FileReference(new File(fileName));
+        bufferCache.createFile(file);
+        int fileId = fmp.lookupFileId(file);
+        bufferCache.openFile(fileId);
+
+        // declare interior-frame-tuple fields
+        int interiorFieldCount = 5;
+        ITypeTrait[] interiorTypeTraits = new ITypeTrait[interiorFieldCount];
+        interiorTypeTraits[0] = new TypeTrait(8);
+        interiorTypeTraits[1] = new TypeTrait(8);
+        interiorTypeTraits[2] = new TypeTrait(8);
+        interiorTypeTraits[3] = new TypeTrait(8);
+        interiorTypeTraits[4] = new TypeTrait(4);
+
+        // declare keys
+        int keyFieldCount = 4;
+        IBinaryComparator[] cmps = new IBinaryComparator[keyFieldCount];
+        cmps[0] = DoubleBinaryComparatorFactory.INSTANCE.createBinaryComparator();
+        cmps[1] = cmps[0];
+        cmps[2] = cmps[0];
+        cmps[3] = cmps[0];
+
+        // declare leaf-frame-tuple fields
+        int leafFieldCount = 5;
+        ITypeTrait[] leafTypeTraits = new ITypeTrait[leafFieldCount];
+        leafTypeTraits[0] = new TypeTrait(8);
+        leafTypeTraits[1] = new TypeTrait(8);
+        leafTypeTraits[2] = new TypeTrait(8);
+        leafTypeTraits[3] = new TypeTrait(8);
+        leafTypeTraits[4] = new TypeTrait(4);
+
+        MultiComparator interiorCmp = new MultiComparator(interiorTypeTraits, cmps);
+        MultiComparator leafCmp = new MultiComparator(leafTypeTraits, cmps);
+
+        RTreeTypeAwareTupleWriterFactory interiorTupleWriterFactory = new RTreeTypeAwareTupleWriterFactory(
+                interiorTypeTraits);
+        RTreeTypeAwareTupleWriterFactory leafTupleWriterFactory = new RTreeTypeAwareTupleWriterFactory(leafTypeTraits);
+
+        IRTreeFrameFactory interiorFrameFactory = new NSMRTreeFrameFactory(interiorTupleWriterFactory, keyFieldCount);
+        IRTreeFrameFactory leafFrameFactory = new NSMRTreeFrameFactory(leafTupleWriterFactory, keyFieldCount);
+        ITreeIndexMetaDataFrameFactory metaFrameFactory = new LIFOMetaDataFrameFactory();
+        ITreeIndexMetaDataFrame metaFrame = metaFrameFactory.getFrame();
+
+        IRTreeFrame interiorFrame = interiorFrameFactory.getFrame();
+        IRTreeFrame leafFrame = leafFrameFactory.getFrame();
+        IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
+
+        RTree rtree = new RTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, interiorCmp,
+                leafCmp);
+        rtree.create(fileId, leafFrame, metaFrame);
+        rtree.open(fileId);
+
+        ByteBuffer hyracksFrame = ctx.allocateFrame();
+        FrameTupleAppender appender = new FrameTupleAppender(ctx.getFrameSize());
+        ArrayTupleBuilder tb = new ArrayTupleBuilder(leafCmp.getFieldCount());
+        DataOutput dos = tb.getDataOutput();
+
+        @SuppressWarnings("rawtypes")
+        ISerializerDeserializer[] recDescSers = { DoubleSerializerDeserializer.INSTANCE,
+                DoubleSerializerDeserializer.INSTANCE, DoubleSerializerDeserializer.INSTANCE,
+                DoubleSerializerDeserializer.INSTANCE, IntegerSerializerDeserializer.INSTANCE };
+        RecordDescriptor recDesc = new RecordDescriptor(recDescSers);
+        IFrameTupleAccessor accessor = new FrameTupleAccessor(ctx.getFrameSize(), recDesc);
+        accessor.reset(hyracksFrame);
+        FrameTupleReference tuple = new FrameTupleReference();
+
+        RTreeOpContext insertOpCtx = rtree.createOpContext(TreeIndexOp.TI_INSERT, interiorFrame, leafFrame, metaFrame,
+                "unittest");
+
+        Random rnd = new Random();
+        rnd.setSeed(50);
+        for (int i = 0; i < 10000; i++) {
+
+            double p1x = rnd.nextDouble();
+            double p1y = rnd.nextDouble();
+            double p2x = rnd.nextDouble();
+            double p2y = rnd.nextDouble();
+
+            int pk = rnd.nextInt();
+
+            tb.reset();
+            DoubleSerializerDeserializer.INSTANCE.serialize(Math.min(p1x, p2x), dos);
+            tb.addFieldEndOffset();
+            DoubleSerializerDeserializer.INSTANCE.serialize(Math.min(p1y, p2y), dos);
+            tb.addFieldEndOffset();
+            DoubleSerializerDeserializer.INSTANCE.serialize(Math.max(p1x, p2x), dos);
+            tb.addFieldEndOffset();
+            DoubleSerializerDeserializer.INSTANCE.serialize(Math.max(p1y, p2y), dos);
+            tb.addFieldEndOffset();
+            IntegerSerializerDeserializer.INSTANCE.serialize(pk, dos);
+            tb.addFieldEndOffset();
+
+            appender.reset(hyracksFrame, true);
+            appender.append(tb.getFieldEndOffsets(), tb.getByteArray(), 0, tb.getSize());
+
+            tuple.reset(accessor, 0);
+
+            print("INSERTING " + i + " " + Math.min(p1x, p2x) + " " + Math.min(p1y, p2y) + " " + Math.max(p1x, p2x)
+                    + " " + Math.max(p1y, p2y) + "\n");
+
+            try {
+                rtree.insert(tuple, insertOpCtx);
+            } catch (TreeIndexException e) {
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+        }
+
+        IRTreeCursor searchCursor = new SearchCursor(interiorFrame, leafFrame);
+        RTreeOpContext searchOpCtx = rtree.createOpContext(TreeIndexOp.TI_SEARCH, interiorFrame, leafFrame, metaFrame,
+                "cursortest");
+        rtree.search(searchCursor, tuple, searchOpCtx);
+
+        ArrayList<Integer> results = new ArrayList<Integer>();
+        try {
+            while (searchCursor.hasNext()) {
+                searchCursor.next();
+                ITupleReference frameTuple = searchCursor.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);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            searchCursor.close();
+        }
+
+        rtree.close();
+        bufferCache.closeFile(fileId);
+        bufferCache.close();
+    }
+}
diff --git a/hyracks-tests/pom.xml b/hyracks-tests/pom.xml
index 64b150f..a4d2c04 100644
--- a/hyracks-tests/pom.xml
+++ b/hyracks-tests/pom.xml
@@ -14,5 +14,6 @@
   <modules>
     <module>hyracks-storage-am-btree-test</module>
     <module>hyracks-storage-am-invertedindex-test</module>
+    <module>hyracks-storage-am-rtree-test</module>
   </modules>
 </project>