Removed leafFrame, interiorFrame, and metaFrame parameters from methods that can internally create frames using factories, e.g., create(), createOpContext(), etc.

git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_btree_updates_next@667 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorNodePushable.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorNodePushable.java
index a6c9fd8..8cfd5d6 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorNodePushable.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorNodePushable.java
@@ -135,8 +135,7 @@
             appender = new FrameTupleAppender(treeIndexOpHelper.getHyracksTaskContext().getFrameSize());
             appender.reset(writeBuffer, true);
 
-            opCtx = btree.createOpContext(IndexOp.SEARCH, treeIndexOpHelper.getLeafFrame(),
-                    treeIndexOpHelper.getInteriorFrame(), null);
+            opCtx = btree.createOpContext(IndexOp.SEARCH);
 
         } catch (Exception e) {
             treeIndexOpHelper.deinit();
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMInteriorFrame.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMInteriorFrame.java
index 87ba3ac..6173440 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMInteriorFrame.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/BTreeNSMInteriorFrame.java
@@ -124,7 +124,7 @@
         } else {
             tupleOff = slotManager.getTupleOff(slotOff);
             frameTuple.resetByTupleOffset(buf, tupleOff);
-            keySize = tupleWriter.bytesRequired(frameTuple, 0, tuple.getFieldCount());
+            keySize = frameTuple.getTupleSize();
             // Perform deletion (we just do a memcpy to overwrite the slot).
             int slotStartOff = slotManager.getSlotEndOff();
             int length = slotOff - slotStartOff;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
index 9ce7544..3952f5d 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
@@ -81,12 +81,14 @@
     }
 
     @Override
-    public void create(int fileId, ITreeIndexFrame leafFrame, ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
+    public void create(int fileId) throws HyracksDataException {
         treeLatch.writeLock().lock();
         try {
             if (created) {
                 return;
             }
+            ITreeIndexFrame leafFrame = leafFrameFactory.createFrame();
+            ITreeIndexMetaDataFrame metaFrame = freePageManager.getMetaDataFrameFactory().createFrame();
             this.fileId = fileId;
             freePageManager.init(metaFrame, rootPage);
             initRoot(leafFrame, true);
@@ -117,14 +119,13 @@
     }
     
     @Override
-    public void diskOrderScan(ITreeIndexCursor icursor, ITreeIndexFrame leafFrame, ITreeIndexMetaDataFrame metaFrame,
-            IIndexOpContext ictx) throws HyracksDataException {
+    public void diskOrderScan(ITreeIndexCursor icursor, IIndexOpContext ictx) throws HyracksDataException {
         TreeDiskOrderScanCursor cursor = (TreeDiskOrderScanCursor) icursor;
         BTreeOpContext ctx = (BTreeOpContext) ictx;
         ctx.reset();
 
         int currentPageId = rootPage;
-        int maxPageId = freePageManager.getMaxPage(metaFrame);
+        int maxPageId = freePageManager.getMaxPage(ctx.metaFrame);
 
         ICachedPage page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, currentPageId), false);
         page.acquireReadLatch();
@@ -916,15 +917,14 @@
 
     // assumes btree has been created and opened
     @Override
-    public IIndexBulkLoadContext beginBulkLoad(float fillFactor, ITreeIndexFrame leafFrame,
-            ITreeIndexFrame interiorFrame, ITreeIndexMetaDataFrame metaFrame) throws TreeIndexException, HyracksDataException {
-        
-    	if (!isEmptyTree((IBTreeLeafFrame)leafFrame)) {
+    public IIndexBulkLoadContext beginBulkLoad(float fillFactor) throws TreeIndexException, HyracksDataException {
+        IBTreeLeafFrame leafFrame = (IBTreeLeafFrame)leafFrameFactory.createFrame();
+    	if (!isEmptyTree(leafFrame)) {
     		throw new BTreeException("Trying to Bulk-load a non-empty BTree.");
     	}
     	
-        BulkLoadContext ctx = new BulkLoadContext(fillFactor, (IBTreeLeafFrame)leafFrame,
-                (IBTreeInteriorFrame)interiorFrame, metaFrame, cmp);
+        BulkLoadContext ctx = new BulkLoadContext(fillFactor, leafFrame,
+                (IBTreeInteriorFrame)interiorFrameFactory.createFrame(), freePageManager.getMetaDataFrameFactory().createFrame(), cmp);
         ctx.nodeFrontiers.get(0).lastTuple.setFieldCount(fieldCount);
         ctx.splitKey.getTuple().setFieldCount(cmp.getKeyFieldCount());
         return ctx;
@@ -1007,11 +1007,12 @@
     }
 
     @Override
-    public BTreeOpContext createOpContext(IndexOp op, ITreeIndexFrame leafFrame, ITreeIndexFrame interiorFrame,
-            ITreeIndexMetaDataFrame metaFrame) {
-        return new BTreeOpContext(op, (IBTreeLeafFrame) leafFrame, (IBTreeInteriorFrame) interiorFrame, metaFrame, 6, cmp);
+    public BTreeOpContext createOpContext(IndexOp op) {
+        return new BTreeOpContext(op, (IBTreeLeafFrame) leafFrameFactory.createFrame(),
+                (IBTreeInteriorFrame) interiorFrameFactory.createFrame(), freePageManager.getMetaDataFrameFactory()
+                        .createFrame(), cmp);
     }
-
+    
     public ITreeIndexFrameFactory getInteriorFrameFactory() {
         return interiorFrameFactory;
     }
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTreeOpContext.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTreeOpContext.java
index 7dc51de..82c747c 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTreeOpContext.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTreeOpContext.java
@@ -26,22 +26,22 @@
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
 
 public final class BTreeOpContext implements IIndexOpContext {
-    public final IndexOp op;
+    private final int INIT_ARRAYLIST_SIZE = 6;    
     public final IBTreeLeafFrame leafFrame;
     public final IBTreeInteriorFrame interiorFrame;
     public final ITreeIndexMetaDataFrame metaFrame;
+    public IndexOp op;
     public ITreeIndexCursor cursor;
     public BTreeCursorInitialState cursorInitialState;
     public RangePredicate pred;
-    public final BTreeSplitKey splitKey;
+    public BTreeSplitKey splitKey;
     public int opRestarts = 0;
-    public final LongArrayList pageLsns; // used like a stack
-    public final IntArrayList smPages;
-    public final IntArrayList freePages;
+    public LongArrayList pageLsns;
+    public IntArrayList smPages;
+    public IntArrayList freePages;
 
     public BTreeOpContext(IndexOp op, IBTreeLeafFrame leafFrame, IBTreeInteriorFrame interiorFrame,
-            ITreeIndexMetaDataFrame metaFrame, int treeHeightHint, MultiComparator cmp) {
-        this.op = op;
+            ITreeIndexMetaDataFrame metaFrame, MultiComparator cmp) {        
         if (leafFrame != null) {
         	leafFrame.setMultiComparator(cmp);
         }
@@ -51,19 +51,8 @@
         }
         this.interiorFrame = interiorFrame;
         this.metaFrame = metaFrame;
-        this.pageLsns = new LongArrayList(treeHeightHint, treeHeightHint);
-        if (op == IndexOp.SEARCH || op == IndexOp.DISKORDERSCAN) {
-            smPages = null;
-            freePages = null;
-            splitKey = null;
-            cursorInitialState = new BTreeCursorInitialState(null);            
-        } else {
-            // Insert, update or delete operation.
-            smPages = new IntArrayList(treeHeightHint, treeHeightHint);
-            freePages = new IntArrayList(treeHeightHint, treeHeightHint);
-            pred = new RangePredicate(true, null, null, true, true, null, null);
-            splitKey = new BTreeSplitKey(leafFrame.getTupleWriter().createTupleReference());
-        }
+        this.pageLsns = new LongArrayList(INIT_ARRAYLIST_SIZE, INIT_ARRAYLIST_SIZE);
+        reset(op);
     }
 
     public void reset() {
@@ -75,4 +64,28 @@
             smPages.clear();
         opRestarts = 0;
     }
+
+    @Override
+    public void reset(IndexOp newOp) {
+        if (newOp == IndexOp.SEARCH || newOp == IndexOp.DISKORDERSCAN) {
+            if (cursorInitialState == null) {
+                cursorInitialState = new BTreeCursorInitialState(null);
+            }
+        } else {
+            // Insert, update or delete operation.
+            if (smPages == null) {
+                smPages = new IntArrayList(INIT_ARRAYLIST_SIZE, INIT_ARRAYLIST_SIZE);
+            }
+            if (freePages == null) {
+                freePages = new IntArrayList(INIT_ARRAYLIST_SIZE, INIT_ARRAYLIST_SIZE);
+            }
+            if (pred == null) {
+                pred = new RangePredicate(true, null, null, true, true, null, null);
+            }
+            if (splitKey == null) {
+                splitKey = new BTreeSplitKey(leafFrame.getTupleWriter().createTupleReference());
+            }
+        }
+        this.op = newOp;
+    }
 }
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexOpContext.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexOpContext.java
index 280ef38..7153f78 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexOpContext.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexOpContext.java
@@ -1,5 +1,8 @@
 package edu.uci.ics.hyracks.storage.am.common.api;
 
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
+
 public interface IIndexOpContext {
 	void reset();
+	void reset(IndexOp newOp);
 }
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java
index 1db33c1..83d0639 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java
@@ -32,15 +32,10 @@
 	 * 
 	 * @param indexFileId
 	 *            The file id to use for this index.
-	 * @param leafFrame
-	 *            Leaf frame to use for initializing the root.
-	 * @param metaFrame
-	 *            Metadata frame to use for initializing metadata information.
 	 * @throws HyracksDataException
 	 *             If the BufferCache throws while un/pinning or un/latching.
 	 */
-	public void create(int indexFileId, ITreeIndexFrame leafFrame,
-			ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException;
+	public void create(int indexFileId) throws HyracksDataException;
 
 	/**
 	 * Opens the tree index backed by the given file id.
@@ -60,22 +55,16 @@
 	 * (insert/delete/update/search/diskorderscan). An operation context
 	 * maintains a cache of objects used during the traversal of the tree index.
 	 * The context is intended to be reused for multiple subsequent operations
-	 * by the same user/thread.
+	 * by the same user/thread. An index operation context is stateful, and
+	 * therefore, should not be shared among two threads.
 	 * 
 	 * @param indexOp
 	 *            Intended index operation.
-	 * @param leafFrame
-	 *            Leaf frame for interpreting leaf pages.
-	 * @param interiorFrame
-	 *            Interior frame for interpreting interior pages.
-	 * @param metaFrame
-	 *            Metadata frame for interpreting metadata pages.
+	 * 
 	 * @returns IITreeIndexOpContext Operation context for the desired index
 	 *          operation.
 	 */
-	public IIndexOpContext createOpContext(IndexOp op,
-			ITreeIndexFrame leafFrame, ITreeIndexFrame interiorFrame,
-			ITreeIndexMetaDataFrame metaFrame);
+	public IIndexOpContext createOpContext(IndexOp op);
 	
 	/**
 	 * Inserts the given tuple into the index using an existing operation
@@ -132,21 +121,13 @@
 	 * 
 	 * @param fillFactor
 	 *            Desired fill factor in [0, 1.0].
-	 * @param leafFrame
-	 *            Leaf frame for filling leaf pages.
-	 * @param interiorFrame
-	 *            Interior frame for filling interior pages.
-	 * @param metaFrame
-	 *            Metadata frame for accessing metadata pages.
 	 * @throws HyracksDataException
 	 *             If the BufferCache throws while un/pinning or un/latching.
 	 * @throws TreeIndexException
 	 *             If the tree is not empty.
 	 * @returns A new context for bulk loading, required for appending tuples.
 	 */
-	public IIndexBulkLoadContext beginBulkLoad(float fillFactor,
-			ITreeIndexFrame leafFrame, ITreeIndexFrame interiorFrame,
-			ITreeIndexMetaDataFrame metaFrame) throws TreeIndexException,
+	public IIndexBulkLoadContext beginBulkLoad(float fillFactor) throws TreeIndexException,
 			HyracksDataException;
 
 	/**
@@ -177,18 +158,14 @@
 	 * Open the given cursor for a disk-order scan, positioning the cursor to
 	 * the first leaf tuple.
 	 * 
-	 * @param leafFrame
-	 *            Leaf frame for interpreting leaf pages.
-	 * @param metaFrame
-	 *            Metadata frame for interpreting metadata pages.
+	 * @param icursor
+	 *            Cursor to be opened for disk-order scanning.
 	 * @param ictx
 	 *            Existing operation context.
 	 * @throws HyracksDataException
 	 *             If the BufferCache throws while un/pinning or un/latching.
 	 */
-	public void diskOrderScan(ITreeIndexCursor icursor,
-			ITreeIndexFrame leafFrame, ITreeIndexMetaDataFrame metaFrame,
-			IIndexOpContext ictx) throws HyracksDataException;
+	public void diskOrderScan(ITreeIndexCursor icursor, IIndexOpContext ictx) throws HyracksDataException;
 	
 	/**
 	 * @return The index's leaf frame factory.
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java
index a5d5e85..63edc06 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java
@@ -23,8 +23,6 @@
 import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAccessor;
 import edu.uci.ics.hyracks.dataflow.std.base.AbstractUnaryInputSinkOperatorNodePushable;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
-import edu.uci.ics.hyracks.storage.am.common.frames.LIFOMetaDataFrame;
 
 public class TreeIndexBulkLoadOperatorNodePushable extends
 		AbstractUnaryInputSinkOperatorNodePushable {
@@ -57,14 +55,11 @@
 				opDesc.getOperatorId(), 0);
 		accessor = new FrameTupleAccessor(treeIndexOpHelper
 				.getHyracksTaskContext().getFrameSize(), recDesc);
-		ITreeIndexMetaDataFrame metaFrame = new LIFOMetaDataFrame();
 		try {
 			treeIndexOpHelper.init();
 			treeIndexOpHelper.getTreeIndex().open(
 					treeIndexOpHelper.getIndexFileId());
-			bulkLoadCtx = treeIndexOpHelper.getTreeIndex().beginBulkLoad(
-					fillFactor, treeIndexOpHelper.getLeafFrame(),
-					treeIndexOpHelper.getInteriorFrame(), metaFrame);
+			bulkLoadCtx = treeIndexOpHelper.getTreeIndex().beginBulkLoad(fillFactor);
 		} catch (Exception e) {
 			// cleanup in case of failure
 			treeIndexOpHelper.deinit();
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java
index 61250d9..ab7b335 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java
@@ -24,11 +24,9 @@
 import edu.uci.ics.hyracks.dataflow.common.comm.util.FrameUtils;
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
 import edu.uci.ics.hyracks.dataflow.std.base.AbstractUnaryOutputSourceOperatorNodePushable;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexOpContext;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexOpContext;
-import edu.uci.ics.hyracks.storage.am.common.frames.LIFOMetaDataFrame;
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
 
 public class TreeIndexDiskOrderScanOperatorNodePushable extends
@@ -50,18 +48,14 @@
 				.getTreeIndexLeafFactory().createFrame();
 		ITreeIndexCursor cursor = treeIndexOpHelper
 				.createDiskOrderScanCursor(cursorFrame);
-		ITreeIndexMetaDataFrame metaFrame = new LIFOMetaDataFrame();
-
-		IIndexOpContext diskOrderScanOpCtx = treeIndexOpHelper
-				.getTreeIndex()
-				.createOpContext(IndexOp.DISKORDERSCAN, cursorFrame, null, null);
+		IIndexOpContext diskOrderScanOpCtx = treeIndexOpHelper.getTreeIndex()
+				.createOpContext(IndexOp.DISKORDERSCAN);
 		try {
 
 			treeIndexOpHelper.init();
 			writer.open();
 			try {
-				treeIndexOpHelper.getTreeIndex().diskOrderScan(cursor,
-						cursorFrame, metaFrame, diskOrderScanOpCtx);
+				treeIndexOpHelper.getTreeIndex().diskOrderScan(cursor, diskOrderScanOpCtx);
 
 				int fieldCount = treeIndexOpHelper.getTreeIndex()
 						.getFieldCount();
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java
index 5716371..34951bf 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java
@@ -23,9 +23,8 @@
 import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAccessor;
 import edu.uci.ics.hyracks.dataflow.common.comm.util.FrameUtils;
 import edu.uci.ics.hyracks.dataflow.std.base.AbstractUnaryInputUnaryOutputOperatorNodePushable;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexOpContext;
-import edu.uci.ics.hyracks.storage.am.common.frames.LIFOMetaDataFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
 
 public class TreeIndexInsertUpdateDeleteOperatorNodePushable extends
@@ -64,10 +63,7 @@
 			treeIndexOpHelper.init();
 			treeIndexOpHelper.getTreeIndex().open(
 					treeIndexOpHelper.getIndexFileId());
-			opCtx = treeIndexOpHelper.getTreeIndex().createOpContext(op,
-					treeIndexOpHelper.getLeafFrame(),
-					treeIndexOpHelper.getInteriorFrame(),
-					new LIFOMetaDataFrame());
+			opCtx = treeIndexOpHelper.getTreeIndex().createOpContext(op);
 		} catch (Exception e) {
 			// cleanup in case of failure
 			treeIndexOpHelper.deinit();
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexOpHelper.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexOpHelper.java
index 797ae1e..6fea7e5 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexOpHelper.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexOpHelper.java
@@ -22,7 +22,6 @@
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
 import edu.uci.ics.hyracks.storage.am.common.impls.TreeDiskOrderScanCursor;
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
@@ -76,9 +75,6 @@
         // otherwise deinit() will try to close the file that failed to open
         indexFileId = fileId;
 
-        interiorFrame = opDesc.getTreeIndexInteriorFactory().createFrame();
-        leafFrame = opDesc.getTreeIndexLeafFactory().createFrame();
-
         IndexRegistry<ITreeIndex> treeIndexRegistry = opDesc.getTreeIndexRegistryProvider().getRegistry(ctx);
         // Create new tree and register it.
         treeIndexRegistry.lock();
@@ -95,10 +91,8 @@
             cmp = new MultiComparator(comparators);
             treeIndex = createTreeIndex();
             if (mode == IndexHelperOpenMode.CREATE) {
-                ITreeIndexMetaDataFrame metaFrame = treeIndex.getFreePageManager().getMetaDataFrameFactory()
-                        .createFrame();
                 try {
-                    treeIndex.create(indexFileId, leafFrame, metaFrame);
+                    treeIndex.create(indexFileId);
                 } catch (Exception e) {
                 	e.printStackTrace();
                     throw new HyracksDataException(e);
@@ -144,14 +138,6 @@
         return opDesc;
     }
 
-    public ITreeIndexFrame getLeafFrame() {
-        return leafFrame;
-    }
-
-    public ITreeIndexFrame getInteriorFrame() {
-        return interiorFrame;
-    }
-
     public int getIndexFileId() {
         return indexFileId;
     }
diff --git a/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/impls/InvertedIndex.java b/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/impls/InvertedIndex.java
index 29dd930..75fdf2a 100644
--- a/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/impls/InvertedIndex.java
+++ b/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/impls/InvertedIndex.java
@@ -268,9 +268,7 @@
         }
 
         public void init(int startPageId, int fileId) throws HyracksDataException, TreeIndexException {
-            btreeBulkLoadCtx = btree.beginBulkLoad(BTree.DEFAULT_FILL_FACTOR,
-                    btree.getLeafFrameFactory().createFrame(), btree.getInteriorFrameFactory().createFrame(), btree
-                            .getFreePageManager().getMetaDataFrameFactory().createFrame());
+            btreeBulkLoadCtx = btree.beginBulkLoad(BTree.DEFAULT_FILL_FACTOR);
             currentPageId = startPageId;
             currentPage = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, currentPageId), true);
             currentPage.acquireWriteLatch();
diff --git a/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/impls/TOccurrenceSearcher.java b/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/impls/TOccurrenceSearcher.java
index 56acc3e..0f88c0b 100644
--- a/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/impls/TOccurrenceSearcher.java
+++ b/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/impls/TOccurrenceSearcher.java
@@ -107,7 +107,7 @@
         invListFieldsWithCount[invListFields.length] = new TypeTrait(4);
         invListKeyLength = tmp;
 
-        btreeOpCtx = invIndex.getBTree().createOpContext(IndexOp.SEARCH, leafFrame, interiorFrame, null);
+        btreeOpCtx = invIndex.getBTree().createOpContext(IndexOp.SEARCH);
 
         resultFrameTupleApp = new FixedSizeFrameTupleAppender(ctx.getFrameSize(), invListFieldsWithCount);
         resultFrameTupleAcc = new FixedSizeFrameTupleAccessor(ctx.getFrameSize(), invListFieldsWithCount);
diff --git a/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/dataflow/RTreeSearchOperatorNodePushable.java b/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/dataflow/RTreeSearchOperatorNodePushable.java
index 54c99fa..4142ebf 100644
--- a/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/dataflow/RTreeSearchOperatorNodePushable.java
+++ b/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/dataflow/RTreeSearchOperatorNodePushable.java
@@ -110,8 +110,7 @@
                 appender = new FrameTupleAppender(treeIndexOpHelper.getHyracksTaskContext().getFrameSize());
                 appender.reset(writeBuffer, true);
 
-                opCtx = rtree.createOpContext(IndexOp.SEARCH, treeIndexOpHelper.getLeafFrame(),
-                        treeIndexOpHelper.getInteriorFrame(), null);
+                opCtx = rtree.createOpContext(IndexOp.SEARCH);
             } catch (Exception e) {
                 writer.fail();
                 throw e;
diff --git a/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/impls/RTree.java b/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/impls/RTree.java
index e7fa260..cb553f7 100644
--- a/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/impls/RTree.java
+++ b/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/impls/RTree.java
@@ -200,16 +200,15 @@
     }
 
     @Override
-    public void create(int fileId, ITreeIndexFrame leafFrame, ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
-        if (created)
-            return;
-
+    public void create(int fileId) throws HyracksDataException {
         treeLatch.writeLock().lock();
         try {
-            // check if another thread beat us to it
-            if (created)
+            if (created) {
                 return;
+            }
 
+            ITreeIndexFrame leafFrame = leafFrameFactory.createFrame();
+            ITreeIndexMetaDataFrame metaFrame = freePageManager.getMetaDataFrameFactory().createFrame();
             freePageManager.init(metaFrame, rootPage);
 
             // initialize root page
@@ -243,11 +242,13 @@
         fileId = -1;
     }
 
-    @Override
-    public RTreeOpContext createOpContext(IndexOp op, ITreeIndexFrame leafFrame, ITreeIndexFrame interiorFrame,
-            ITreeIndexMetaDataFrame metaFrame) {
-        return new RTreeOpContext(op, (IRTreeLeafFrame) leafFrame, (IRTreeInteriorFrame) interiorFrame, metaFrame, 8);
-    }
+	@Override
+	public RTreeOpContext createOpContext(IndexOp op) {
+		return new RTreeOpContext(op,
+				(IRTreeLeafFrame) leafFrameFactory.createFrame(),
+				(IRTreeInteriorFrame) interiorFrameFactory.createFrame(),
+				freePageManager.getMetaDataFrameFactory().createFrame(), 8);
+	}
 
     @Override
     public void insert(ITupleReference tuple, IIndexOpContext ictx) throws HyracksDataException, TreeIndexException {
@@ -874,19 +875,18 @@
 
         public BulkLoadContext(float fillFactor, IRTreeFrame leafFrame, IRTreeFrame interiorFrame,
                 ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
-
-            insertOpCtx = createOpContext(IndexOp.INSERT, leafFrame, interiorFrame, metaFrame);
+            insertOpCtx = createOpContext(IndexOp.INSERT);
         }
     }
 
     @Override
-    public IIndexBulkLoadContext beginBulkLoad(float fillFactor, ITreeIndexFrame leafFrame,
-            ITreeIndexFrame interiorFrame, ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
-        if (loaded)
+    public IIndexBulkLoadContext beginBulkLoad(float fillFactor) throws HyracksDataException {
+        if (loaded) {
             throw new HyracksDataException("Trying to bulk-load RTree but RTree has already been loaded.");
+        }
 
-        BulkLoadContext ctx = new BulkLoadContext(fillFactor, (IRTreeFrame) leafFrame, (IRTreeFrame) interiorFrame,
-                metaFrame);
+        BulkLoadContext ctx = new BulkLoadContext(fillFactor, (IRTreeFrame) leafFrameFactory.createFrame(), (IRTreeFrame) interiorFrameFactory.createFrame(),
+                freePageManager.getMetaDataFrameFactory().createFrame());
         return ctx;
     }
 
@@ -905,14 +905,13 @@
     }
 
     @Override
-    public void diskOrderScan(ITreeIndexCursor icursor, ITreeIndexFrame leafFrame, ITreeIndexMetaDataFrame metaFrame,
-            IIndexOpContext ictx) throws HyracksDataException {
+    public void diskOrderScan(ITreeIndexCursor icursor, IIndexOpContext ictx) throws HyracksDataException {
         TreeDiskOrderScanCursor cursor = (TreeDiskOrderScanCursor) icursor;
         RTreeOpContext ctx = (RTreeOpContext) ictx;
         ctx.reset();
 
         int currentPageId = rootPage + 1;
-        int maxPageId = freePageManager.getMaxPage(metaFrame);
+        int maxPageId = freePageManager.getMaxPage(ctx.metaFrame);
 
         ICachedPage page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, currentPageId), false);
         page.acquireReadLatch();
diff --git a/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/impls/RTreeOpContext.java b/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/impls/RTreeOpContext.java
index 8e68ffd..dc4a753 100644
--- a/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/impls/RTreeOpContext.java
+++ b/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/impls/RTreeOpContext.java
@@ -16,31 +16,30 @@
 package edu.uci.ics.hyracks.storage.am.rtree.impls;
 
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexOpContext;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexOpContext;
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
 import edu.uci.ics.hyracks.storage.am.rtree.api.IRTreeInteriorFrame;
 import edu.uci.ics.hyracks.storage.am.rtree.api.IRTreeLeafFrame;
 
 public final class RTreeOpContext implements IIndexOpContext {
-	public final IndexOp op;
 	public final IRTreeInteriorFrame interiorFrame;
 	public final IRTreeLeafFrame leafFrame;
+	public IndexOp op;
 	public ITreeIndexCursor cursor;
 	public RTreeCursorInitialState cursorInitialState;
-	public final ITreeIndexMetaDataFrame metaFrame;
-	public final RTreeSplitKey splitKey;
+	public ITreeIndexMetaDataFrame metaFrame;
+	public RTreeSplitKey splitKey;
 	public ITupleReference tuple;
-	public final PathList pathList; // used to record the pageIds and pageLsns
-									// of the visited pages
-	public final PathList traverseList; // used for traversing the tree
+	public PathList pathList; // used to record the pageIds and pageLsns
+								// of the visited pages
+	public PathList traverseList; // used for traversing the tree
 	private static final int initTraverseListSize = 100;
 
 	public RTreeOpContext(IndexOp op, IRTreeLeafFrame leafFrame,
 			IRTreeInteriorFrame interiorFrame,
 			ITreeIndexMetaDataFrame metaFrame, int treeHeightHint) {
-		this.op = op;
 		this.interiorFrame = interiorFrame;
 		this.leafFrame = leafFrame;
 		this.metaFrame = metaFrame;
@@ -74,4 +73,25 @@
 			traverseList.clear();
 		}
 	}
+
+	@Override
+	public void reset(IndexOp newOp) {
+		if (op != IndexOp.SEARCH && op != IndexOp.DISKORDERSCAN) {
+			if (splitKey == null) {
+				splitKey = new RTreeSplitKey(interiorFrame.getTupleWriter()
+						.createTupleReference(), interiorFrame.getTupleWriter()
+						.createTupleReference());
+			}
+			if (traverseList == null) {
+				traverseList = new PathList(initTraverseListSize,
+						initTraverseListSize);
+			}
+
+		} else {
+			if (cursorInitialState == null) {
+				cursorInitialState = new RTreeCursorInitialState(pathList, 1);
+			}
+		}
+		this.op = newOp;
+	}
 }
diff --git a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeStatsTest.java b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeStatsTest.java
index 222a039..7c181c8 100644
--- a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeStatsTest.java
+++ b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeStatsTest.java
@@ -94,7 +94,7 @@
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
 
         BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-        btree.create(fileId, leafFrame, metaFrame);
+        btree.create(fileId);
         btree.open(fileId);
 
         Random rnd = new Random();
@@ -116,7 +116,7 @@
         accessor.reset(frame);
         FrameTupleReference tuple = new FrameTupleReference();
 
-        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT, leafFrame, interiorFrame, metaFrame);
+        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT);
 
         // 10000
         for (int i = 0; i < 100000; i++) {
diff --git a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeTest.java b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeTest.java
index 7ca504b..a357f2a 100644
--- a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeTest.java
+++ b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeTest.java
@@ -127,7 +127,7 @@
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
 
         BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-        btree.create(fileId, leafFrame, metaFrame);
+        btree.create(fileId);
         btree.open(fileId);
 
         Random rnd = new Random();
@@ -149,7 +149,7 @@
         accessor.reset(frame);
         FrameTupleReference tuple = new FrameTupleReference();
 
-        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT, leafFrame, interiorFrame, metaFrame);
+        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT);
 
         // 10000
         for (int i = 0; i < 10000; i++) {
@@ -197,7 +197,7 @@
         LOGGER.info("ORDERED SCAN:");
         ITreeIndexCursor scanCursor = new BTreeRangeSearchCursor(leafFrame);
         RangePredicate nullPred = new RangePredicate(true, null, null, true, true, null, null);
-        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH, leafFrame, interiorFrame, null);
+        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH);
         btree.search(scanCursor, nullPred, searchOpCtx);
         try {
             while (scanCursor.hasNext()) {
@@ -215,8 +215,8 @@
         // disk-order scan
         LOGGER.info("DISK-ORDER SCAN:");
         TreeDiskOrderScanCursor diskOrderCursor = new TreeDiskOrderScanCursor(leafFrame);
-        BTreeOpContext diskOrderScanOpCtx = btree.createOpContext(IndexOp.DISKORDERSCAN, leafFrame, null, null);
-        btree.diskOrderScan(diskOrderCursor, leafFrame, metaFrame, diskOrderScanOpCtx);
+        BTreeOpContext diskOrderScanOpCtx = btree.createOpContext(IndexOp.DISKORDERSCAN);
+        btree.diskOrderScan(diskOrderCursor, diskOrderScanOpCtx);
         try {
             while (diskOrderCursor.hasNext()) {
                 diskOrderCursor.next();
@@ -335,7 +335,7 @@
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
 
         BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-        btree.create(fileId, leafFrame, metaFrame);
+        btree.create(fileId);
         btree.open(fileId);
 
         Random rnd = new Random();
@@ -357,7 +357,7 @@
         accessor.reset(frame);
         FrameTupleReference tuple = new FrameTupleReference();
 
-        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT, leafFrame, interiorFrame, metaFrame);
+        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT);
         
         // Magic test number: 3029. 6398. 4875.
         for (int i = 0; i < 10000; i++) {
@@ -400,7 +400,7 @@
         LOGGER.info("ORDERED SCAN:");
         ITreeIndexCursor scanCursor = new BTreeRangeSearchCursor(leafFrame);
         RangePredicate nullPred = new RangePredicate(true, null, null, true, true, null, null);
-        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH, leafFrame, interiorFrame, null);
+        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH);
         btree.search(scanCursor, nullPred, searchOpCtx);
 
         try {
@@ -525,7 +525,7 @@
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
 
         BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-        btree.create(fileId, leafFrame, metaFrame);
+        btree.create(fileId);
         btree.open(fileId);
 
         Random rnd = new Random();
@@ -543,7 +543,7 @@
         accessor.reset(frame);
         FrameTupleReference tuple = new FrameTupleReference();
 
-        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT, leafFrame, interiorFrame, metaFrame);
+        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT);
         int maxLength = 10; // max string length to be generated
         for (int i = 0; i < 10000; i++) {
 
@@ -578,7 +578,7 @@
         LOGGER.info("ORDERED SCAN:");
         ITreeIndexCursor scanCursor = new BTreeRangeSearchCursor(leafFrame);
         RangePredicate nullPred = new RangePredicate(true, null, null, true, true, null, null);
-        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH, leafFrame, interiorFrame, null);
+        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH);
         btree.search(scanCursor, nullPred, searchOpCtx);
 
         try {
@@ -698,7 +698,7 @@
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
 
         BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-        btree.create(fileId, leafFrame, metaFrame);
+        btree.create(fileId);
         btree.open(fileId);
 
         Random rnd = new Random();
@@ -716,8 +716,8 @@
         accessor.reset(frame);
         FrameTupleReference tuple = new FrameTupleReference();
 
-        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT, leafFrame, interiorFrame, metaFrame);
-        BTreeOpContext deleteOpCtx = btree.createOpContext(IndexOp.DELETE, leafFrame, interiorFrame, metaFrame);
+        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT);
+        BTreeOpContext deleteOpCtx = btree.createOpContext(IndexOp.DELETE);
 
         int runs = 3;
         for (int run = 0; run < runs; run++) {
@@ -819,7 +819,7 @@
         LOGGER.info("ORDERED SCAN:");
         ITreeIndexCursor scanCursor = new BTreeRangeSearchCursor(leafFrame);
         RangePredicate nullPred = new RangePredicate(true, null, null, true, true, null, null);
-        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH, leafFrame, interiorFrame, null);
+        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH);
         btree.search(scanCursor, nullPred, searchOpCtx);
         StringBuilder scanResults = new StringBuilder();
         try {
@@ -900,7 +900,7 @@
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
 
         BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-        btree.create(fileId, leafFrame, metaFrame);
+        btree.create(fileId);
         btree.open(fileId);
 
         Random rnd = new Random();
@@ -918,8 +918,8 @@
         accessor.reset(frame);
         FrameTupleReference tuple = new FrameTupleReference();
 
-        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT, leafFrame, interiorFrame, metaFrame);
-        BTreeOpContext updateOpCtx = btree.createOpContext(IndexOp.UPDATE, leafFrame, interiorFrame, metaFrame);
+        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT);
+        BTreeOpContext updateOpCtx = btree.createOpContext(IndexOp.UPDATE);
 
         Map<String, String> expectedValues = new HashMap<String, String>();
         
@@ -962,7 +962,7 @@
         }
         ITreeIndexCursor insertCheckCursor = new BTreeRangeSearchCursor(leafFrame);
         RangePredicate nullPred = new RangePredicate(true, null, null, true, true, null, null);
-        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH, leafFrame, interiorFrame, null);
+        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH);
         btree.search(insertCheckCursor, nullPred, searchOpCtx);
         try {
             compareActualAndExpected(insertCheckCursor, expectedValues, fieldSerdes);
@@ -1066,7 +1066,7 @@
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
 
         BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-        btree.create(fileId, leafFrame, metaFrame);
+        btree.create(fileId);
         btree.open(fileId);
 
         Random rnd = new Random();
@@ -1084,7 +1084,7 @@
         accessor.reset(frame);
         FrameTupleReference tuple = new FrameTupleReference();
 
-        IIndexBulkLoadContext bulkLoadCtx = btree.beginBulkLoad(0.7f, leafFrame, interiorFrame, metaFrame);
+        IIndexBulkLoadContext bulkLoadCtx = btree.beginBulkLoad(0.7f);
 
         // generate sorted records
         int ins = 100000;
@@ -1156,7 +1156,7 @@
 
         // TODO: check when searching backwards
         RangePredicate rangePred = new RangePredicate(true, lowKey, highKey, true, true, searchCmp, searchCmp);
-        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH, leafFrame, interiorFrame, null);
+        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH);
         btree.search(rangeCursor, rangePred, searchOpCtx);
 
         try {
@@ -1220,7 +1220,7 @@
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, fileId, 0, metaFrameFactory);
 
         BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-        btree.create(fileId, leafFrame, metaFrame);
+        btree.create(fileId);
         btree.open(fileId);
 
         Random rnd = new Random();
@@ -1273,7 +1273,7 @@
         intervals[9][0] = 20;
         intervals[9][1] = 35;
 
-        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT, leafFrame, interiorFrame, metaFrame);
+        BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT);
 
         // int exceptionCount = 0;
         for (int i = 0; i < intervalCount; i++) {
@@ -1313,7 +1313,7 @@
         LOGGER.info("ORDERED SCAN:");
         ITreeIndexCursor scanCursor = new BTreeRangeSearchCursor(leafFrame);
         RangePredicate nullPred = new RangePredicate(true, null, null, true, true, null, null);
-        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH, leafFrame, interiorFrame, null);
+        BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH);
         btree.search(scanCursor, nullPred, searchOpCtx);
 
         try {
diff --git a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/RangeSearchCursorTest.java b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/RangeSearchCursorTest.java
index 9a18cf6..14246f7 100644
--- a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/RangeSearchCursorTest.java
+++ b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/RangeSearchCursorTest.java
@@ -100,14 +100,13 @@
 		IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, btreeFileId, 0, metaFrameFactory);
 		
 		BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-		btree.create(btreeFileId, leafFrame, metaFrame);
+		btree.create(btreeFileId);
 		btree.open(btreeFileId);
 
 		ArrayTupleBuilder tupleBuilder = new ArrayTupleBuilder(fieldCount);
 	    ArrayTupleReference tuple = new ArrayTupleReference();
 
-		BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT,
-				leafFrame, interiorFrame, metaFrame);
+		BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT);
 
 		// generate keys
 		int numKeys = 50;
@@ -187,14 +186,13 @@
 		IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, btreeFileId, 0, metaFrameFactory);
 		
 		BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-		btree.create(btreeFileId, leafFrame, metaFrame);
+		btree.create(btreeFileId);
 		btree.open(btreeFileId);
 
 		ArrayTupleBuilder tupleBuilder = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
 
-		BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT,
-				leafFrame, interiorFrame, metaFrame);
+		BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT);
 
 		// generate keys
 		int numKeys = 50;
@@ -271,14 +269,13 @@
 		IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, btreeFileId, 0, metaFrameFactory);		
 		
 		BTree btree = new BTree(bufferCache, fieldCount, cmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-		btree.create(btreeFileId, leafFrame, metaFrame);
+		btree.create(btreeFileId);
 		btree.open(btreeFileId);
 
 		ArrayTupleBuilder tupleBuilder = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
 
-		BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT,
-				leafFrame, interiorFrame, metaFrame);
+		BTreeOpContext insertOpCtx = btree.createOpContext(IndexOp.INSERT);
 
 		// generate keys
 		int numKeys = 50;
@@ -412,8 +409,7 @@
 				RangePredicate rangePred = createRangePredicate(lowKey,
 						highKey, isForward, lowKeyInclusive, highKeyInclusive,
 						btree.getMultiComparator());
-				BTreeOpContext searchOpCtx = btree.createOpContext(
-						IndexOp.SEARCH, leafFrame, interiorFrame, null);
+				BTreeOpContext searchOpCtx = btree.createOpContext(IndexOp.SEARCH);
 				btree.search(rangeCursor, rangePred, searchOpCtx);
 
 				try {
diff --git a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeTestContext.java b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeTestContext.java
index a517b1f..c56f1b6 100644
--- a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeTestContext.java
+++ b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeTestContext.java
@@ -23,6 +23,7 @@
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeInteriorFrame;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeLeafFrame;
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTree;
+import edu.uci.ics.hyracks.storage.am.btree.impls.BTreeOpContext;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 
@@ -37,15 +38,17 @@
     public final ArrayTupleBuilder tupleBuilder;
     public final ArrayTupleReference tuple = new ArrayTupleReference();
     public final TreeSet<CheckTuple> checkTuples = new TreeSet<CheckTuple>();
+    public final BTreeOpContext opCtx;
     
     public BTreeTestContext(IBufferCache bufferCache, ISerializerDeserializer[] fieldSerdes, BTree btree, IBTreeLeafFrame leafFrame,
-            IBTreeInteriorFrame interiorFrame, ITreeIndexMetaDataFrame metaFrame) {
+            IBTreeInteriorFrame interiorFrame, ITreeIndexMetaDataFrame metaFrame, BTreeOpContext opCtx) {
         this.bufferCache = bufferCache;
         this.fieldSerdes = fieldSerdes;
         this.btree = btree;
         this.leafFrame = leafFrame;
         this.interiorFrame = interiorFrame;
         this.metaFrame = metaFrame;
+        this.opCtx = opCtx;
         this.tupleBuilder = new ArrayTupleBuilder(fieldSerdes.length);
     }
     
diff --git a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeTestUtils.java b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeTestUtils.java
index 07acaa8..09d3dd4 100644
--- a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeTestUtils.java
+++ b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeTestUtils.java
@@ -49,15 +49,15 @@
         IBinaryComparator[] cmps = SerdeUtils.serdesToComparators(fieldSerdes, numKeyFields);
         
         BTree btree = BTreeUtils.createBTree(bufferCache, btreeFileId, typeTraits, cmps, leafType);
+        btree.create(btreeFileId);
+        btree.open(btreeFileId);
+        // Set an arbitrary index op in the context. Will be reset anyway.
+        BTreeOpContext opCtx = btree.createOpContext(IndexOp.SEARCH);
         
         IBTreeLeafFrame leafFrame = (IBTreeLeafFrame) btree.getLeafFrameFactory().createFrame();
         IBTreeInteriorFrame interiorFrame = (IBTreeInteriorFrame) btree.getInteriorFrameFactory().createFrame();
         ITreeIndexMetaDataFrame metaFrame = btree.getFreePageManager().getMetaDataFrameFactory().createFrame();
-
-        btree.create(btreeFileId, leafFrame, metaFrame);
-        btree.open(btreeFileId);
-        
-        BTreeTestContext testCtx = new BTreeTestContext(bufferCache, fieldSerdes, btree, leafFrame, interiorFrame, metaFrame);
+        BTreeTestContext testCtx = new BTreeTestContext(bufferCache, fieldSerdes, btree, leafFrame, interiorFrame, metaFrame, opCtx);
         return testCtx;
     }
     
@@ -105,8 +105,8 @@
         LOGGER.info("Testing Ordered Scan.");
         ITreeIndexCursor scanCursor = new BTreeRangeSearchCursor(testCtx.leafFrame);
         RangePredicate nullPred = new RangePredicate(true, null, null, true, true, null, null);
-        BTreeOpContext searchOpCtx = testCtx.btree.createOpContext(IndexOp.SEARCH, testCtx.leafFrame, testCtx.interiorFrame, null);
-        testCtx.btree.search(scanCursor, nullPred, searchOpCtx);
+        testCtx.opCtx.reset(IndexOp.SEARCH);
+        testCtx.btree.search(scanCursor, nullPred, testCtx.opCtx);
         Iterator<CheckTuple> checkIter = testCtx.checkTuples.iterator();
         int actualCount = 0;
         try {
@@ -131,8 +131,8 @@
     public static void checkDiskOrderScan(BTreeTestContext testCtx) throws Exception {
         LOGGER.info("Testing Disk-Order Scan.");
         ITreeIndexCursor diskOrderCursor = new TreeDiskOrderScanCursor(testCtx.leafFrame);
-        BTreeOpContext diskOrderScanOpCtx = testCtx.btree.createOpContext(IndexOp.DISKORDERSCAN, testCtx.leafFrame, null, null);
-        testCtx.btree.diskOrderScan(diskOrderCursor, testCtx.leafFrame, testCtx.metaFrame, diskOrderScanOpCtx);
+        testCtx.opCtx.reset(IndexOp.DISKORDERSCAN);
+        testCtx.btree.diskOrderScan(diskOrderCursor, testCtx.opCtx);
         int actualCount = 0;        
         try {
             while (diskOrderCursor.hasNext()) {
@@ -161,8 +161,8 @@
         MultiComparator highKeyCmp = BTreeUtils.getSearchMultiComparator(testCtx.btree.getMultiComparator(), highKey);
         ITreeIndexCursor searchCursor = new BTreeRangeSearchCursor(testCtx.leafFrame);
         RangePredicate rangePred = new RangePredicate(true, lowKey, highKey, lowKeyInclusive, highKeyInclusive, lowKeyCmp, highKeyCmp);
-        BTreeOpContext searchOpCtx = testCtx.btree.createOpContext(IndexOp.SEARCH, testCtx.leafFrame, testCtx.interiorFrame, null);
-        testCtx.btree.search(searchCursor, rangePred, searchOpCtx);
+        testCtx.opCtx.reset(IndexOp.SEARCH);
+        testCtx.btree.search(searchCursor, rangePred, testCtx.opCtx);
         // Get the subset of elements from the expected set within given key range.
         CheckTuple lowKeyCheck = createCheckTupleFromTuple(lowKey, testCtx.fieldSerdes, lowKeyCmp.getKeyFieldCount());
         CheckTuple highKeyCheck = createCheckTupleFromTuple(highKey, testCtx.fieldSerdes, highKeyCmp.getKeyFieldCount());
@@ -204,8 +204,7 @@
         ArrayTupleReference lowKey = new ArrayTupleReference();
         ArrayTupleBuilder highKeyBuilder = new ArrayTupleBuilder(testCtx.btree.getMultiComparator().getKeyFieldCount());
         ArrayTupleReference highKey = new ArrayTupleReference();
-        
-        BTreeOpContext searchOpCtx = testCtx.btree.createOpContext(IndexOp.SEARCH, testCtx.leafFrame, testCtx.interiorFrame, null);
+        testCtx.opCtx.reset(IndexOp.SEARCH);
         RangePredicate rangePred = new RangePredicate(true, lowKey, highKey, true, true, null, null);
 
         // Iterate through expected tuples, and perform a point search in the BTree to verify the tuple can be reached.
@@ -220,7 +219,7 @@
             rangePred.setLowKeyComparator(lowKeyCmp);
             rangePred.setHighKeyComparator(highKeyCmp);
             
-            testCtx.btree.search(searchCursor, rangePred, searchOpCtx);
+            testCtx.btree.search(searchCursor, rangePred, testCtx.opCtx);
             
             try {
                 // We expect exactly one answer.
@@ -271,7 +270,7 @@
         int numFields = testCtx.getFieldCount();
         int numKeyFields = testCtx.getKeyFieldCount();
         
-        BTreeOpContext insertOpCtx = testCtx.btree.createOpContext(IndexOp.INSERT, testCtx.leafFrame, testCtx.interiorFrame, testCtx.metaFrame);
+        testCtx.opCtx.reset(IndexOp.INSERT);
         
         int[] tupleValues = new int[testCtx.getFieldCount()];
         // Scale range of values according to number of keys. 
@@ -291,7 +290,7 @@
                 LOGGER.info("Inserting Tuple " + (i + 1) + "/" + numTuples);
             }
             try {
-                testCtx.btree.insert(testCtx.tuple, insertOpCtx);
+                testCtx.btree.insert(testCtx.tuple, testCtx.opCtx);
                 // Set expected values. Do this only after insertion succeeds because we ignore duplicate keys.
                 CheckTuple<Integer> checkTuple = new CheckTuple<Integer>(numFields, numKeyFields);
                 for(int v : tupleValues) {
@@ -308,7 +307,8 @@
         int numFields = testCtx.getFieldCount();
         int numKeyFields = testCtx.getKeyFieldCount();
         
-        BTreeOpContext insertOpCtx = testCtx.btree.createOpContext(IndexOp.INSERT, testCtx.leafFrame, testCtx.interiorFrame, testCtx.metaFrame);
+        testCtx.opCtx.reset(IndexOp.INSERT);
+
         Object[] tupleValues = new Object[numFields];
         for (int i = 0; i < numTuples; i++) {
             if ((i + 1) % (numTuples / Math.min(10, numTuples)) == 0) {
@@ -325,7 +325,7 @@
             }
             TupleUtils.createTuple(testCtx.tupleBuilder, testCtx.tuple, testCtx.fieldSerdes, tupleValues);
             try {
-                testCtx.btree.insert(testCtx.tuple, insertOpCtx);
+                testCtx.btree.insert(testCtx.tuple, testCtx.opCtx);
                 // Set expected values. Do this only after insertion succeeds because we ignore duplicate keys.
                 CheckTuple<String> checkTuple = new CheckTuple<String>(numFields, numKeyFields);
                 for(Object v : tupleValues) {
@@ -394,7 +394,7 @@
         ArrayTupleBuilder tupleBuilder = new ArrayTupleBuilder(numFields);
         ArrayTupleReference tuple = new ArrayTupleReference();
         // Perform bulk load.
-        IIndexBulkLoadContext bulkLoadCtx = testCtx.btree.beginBulkLoad(0.7f, testCtx.leafFrame, testCtx.interiorFrame, testCtx.metaFrame);
+        IIndexBulkLoadContext bulkLoadCtx = testCtx.btree.beginBulkLoad(0.7f);
         int c = 1;
         for (CheckTuple checkTuple : testCtx.checkTuples) {
             if (c % (numTuples / 10) == 0) {
@@ -411,7 +411,7 @@
         ArrayTupleBuilder deleteTupleBuilder = new ArrayTupleBuilder(testCtx.btree.getMultiComparator().getKeyFieldCount());
         ArrayTupleReference deleteTuple = new ArrayTupleReference();
         int numCheckTuples = testCtx.checkTuples.size();
-        BTreeOpContext deleteOpCtx = testCtx.btree.createOpContext(IndexOp.DELETE, testCtx.leafFrame, testCtx.interiorFrame, testCtx.metaFrame);
+        testCtx.opCtx.reset(IndexOp.DELETE);
         // Copy CheckTuple references into array, so we can randomly pick from there.
         CheckTuple[] checkTuples = new CheckTuple[numCheckTuples];
         int idx = 0;
@@ -425,7 +425,7 @@
             int checkTupleIdx = Math.abs(rnd.nextInt() % numCheckTuples);
             CheckTuple checkTuple = checkTuples[checkTupleIdx];            
             createTupleFromCheckTuple(checkTuple, deleteTupleBuilder, deleteTuple, testCtx.fieldSerdes);          
-            testCtx.btree.delete(deleteTuple, deleteOpCtx);
+            testCtx.btree.delete(deleteTuple, testCtx.opCtx);
             
             // Remove check tuple from expected results.
             testCtx.checkTuples.remove(checkTuple);
@@ -449,7 +449,7 @@
         ArrayTupleBuilder updateTupleBuilder = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference updateTuple = new ArrayTupleReference();
         int numCheckTuples = testCtx.checkTuples.size();
-        BTreeOpContext updateOpCtx = testCtx.btree.createOpContext(IndexOp.UPDATE, testCtx.leafFrame, testCtx.interiorFrame, testCtx.metaFrame);
+        testCtx.opCtx.reset(IndexOp.UPDATE);
         // Copy CheckTuple references into array, so we can randomly pick from there.
         CheckTuple[] checkTuples = new CheckTuple[numCheckTuples];
         int idx = 0;
@@ -469,7 +469,7 @@
             }
             
             createTupleFromCheckTuple(checkTuple, updateTupleBuilder, updateTuple, testCtx.fieldSerdes);            
-            testCtx.btree.update(updateTuple, updateOpCtx);
+            testCtx.btree.update(updateTuple, testCtx.opCtx);
             
             // Swap with last "valid" CheckTuple.
             CheckTuple tmp = checkTuples[numCheckTuples - 1];
diff --git a/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/AbstractInvIndexSearchTest.java b/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/AbstractInvIndexSearchTest.java
index c8d9c6e..fa1833a 100644
--- a/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/AbstractInvIndexSearchTest.java
+++ b/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/AbstractInvIndexSearchTest.java
@@ -169,7 +169,7 @@
         freePageManager = new LinkedListFreePageManager(bufferCache, btreeFileId, 0, metaFrameFactory);
 
         btree = new BTree(bufferCache, fieldCount, btreeCmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-        btree.create(btreeFileId, leafFrame, metaFrame);
+        btree.create(btreeFileId);
         btree.open(btreeFileId);
 
         // --- INVERTED INDEX ---
diff --git a/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/BulkLoadTest.java b/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/BulkLoadTest.java
index ebd8c28..86b3107 100644
--- a/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/BulkLoadTest.java
+++ b/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/BulkLoadTest.java
@@ -137,7 +137,7 @@
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, btreeFileId, 0, metaFrameFactory);
 
         BTree btree = new BTree(bufferCache, fieldCount, btreeCmp, freePageManager, interiorFrameFactory, leafFrameFactory);
-        btree.create(btreeFileId, leafFrame, metaFrame);
+        btree.create(btreeFileId);
         btree.open(btreeFileId);
 
         int invListFields = 1;
@@ -241,7 +241,7 @@
         IFrameTupleAccessor tokenAccessor = new FrameTupleAccessor(stageletCtx.getFrameSize(), tokenRecDesc);
         tokenAccessor.reset(frame);
 
-        BTreeOpContext btreeOpCtx = invIndex.getBTree().createOpContext(IndexOp.SEARCH, leafFrame, interiorFrame, null);
+        BTreeOpContext btreeOpCtx = invIndex.getBTree().createOpContext(IndexOp.SEARCH);
 
         // verify created inverted lists one-by-one
         for (int i = 0; i < tokens.size(); i++) {
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 0a04eca..ce3bd3c 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
@@ -132,7 +132,7 @@
 
 		RTree rtree = new RTree(bufferCache, fieldCount, cmp, freePageManager,
 				interiorFrameFactory, leafFrameFactory);
-		rtree.create(fileId, leafFrame, metaFrame);
+		rtree.create(fileId);
 		rtree.open(fileId);
 
 		ByteBuffer hyracksFrame = ctx.allocateFrame();
@@ -155,8 +155,7 @@
 		accessor.reset(hyracksFrame);
 		FrameTupleReference tuple = new FrameTupleReference();
 
-		RTreeOpContext insertOpCtx = rtree.createOpContext(IndexOp.INSERT,
-				leafFrame, interiorFrame, metaFrame);
+		RTreeOpContext insertOpCtx = rtree.createOpContext(IndexOp.INSERT);
 
 		Random rnd = new Random();
 		rnd.setSeed(50);
@@ -224,10 +223,8 @@
 		print("DISK-ORDER SCAN:\n");
 		TreeDiskOrderScanCursor diskOrderCursor = new TreeDiskOrderScanCursor(
 				leafFrame);
-		RTreeOpContext diskOrderScanOpCtx = rtree.createOpContext(
-				IndexOp.DISKORDERSCAN, leafFrame, null, null);
-		rtree.diskOrderScan(diskOrderCursor, leafFrame, metaFrame,
-				diskOrderScanOpCtx);
+		RTreeOpContext diskOrderScanOpCtx = rtree.createOpContext(IndexOp.DISKORDERSCAN);
+		rtree.diskOrderScan(diskOrderCursor, diskOrderScanOpCtx);
 		try {
 			while (diskOrderCursor.hasNext()) {
 				diskOrderCursor.next();
@@ -314,7 +311,7 @@
 
 		RTree rtree = new RTree(bufferCache, fieldCount, cmp, freePageManager,
 				interiorFrameFactory, leafFrameFactory);
-		rtree.create(fileId, leafFrame, metaFrame);
+		rtree.create(fileId);
 		rtree.open(fileId);
 
 		ByteBuffer hyracksFrame = ctx.allocateFrame();
@@ -337,8 +334,7 @@
 		accessor.reset(hyracksFrame);
 		FrameTupleReference tuple = new FrameTupleReference();
 
-		RTreeOpContext insertOpCtx = rtree.createOpContext(IndexOp.INSERT,
-				leafFrame, interiorFrame, metaFrame);
+		RTreeOpContext insertOpCtx = rtree.createOpContext(IndexOp.INSERT);
 
 		Random rnd = new Random();
 		rnd.setSeed(50);
@@ -400,8 +396,7 @@
 		String rtreeStats = rtree.printStats();
 		print(rtreeStats);
 
-		RTreeOpContext deleteOpCtx = rtree.createOpContext(IndexOp.DELETE,
-				leafFrame, interiorFrame, metaFrame);
+		RTreeOpContext deleteOpCtx = rtree.createOpContext(IndexOp.DELETE);
 		rnd.setSeed(50);
 		for (int i = 0; i < 5000; i++) {
 
@@ -532,7 +527,7 @@
 
 		RTree rtree = new RTree(bufferCache, fieldCount, cmp, freePageManager,
 				interiorFrameFactory, leafFrameFactory);
-		rtree.create(fileId, leafFrame, metaFrame);
+		rtree.create(fileId);
 		rtree.open(fileId);
 
 		ByteBuffer hyracksFrame = ctx.allocateFrame();
@@ -557,8 +552,7 @@
 		accessor.reset(hyracksFrame);
 		FrameTupleReference tuple = new FrameTupleReference();
 
-		RTreeOpContext insertOpCtx = rtree.createOpContext(IndexOp.INSERT,
-				leafFrame, interiorFrame, metaFrame);
+		RTreeOpContext insertOpCtx = rtree.createOpContext(IndexOp.INSERT);
 
 		Random rnd = new Random();
 		rnd.setSeed(50);
@@ -633,10 +627,8 @@
 		print("DISK-ORDER SCAN:\n");
 		TreeDiskOrderScanCursor diskOrderCursor = new TreeDiskOrderScanCursor(
 				leafFrame);
-		RTreeOpContext diskOrderScanOpCtx = rtree.createOpContext(
-				IndexOp.DISKORDERSCAN, leafFrame, null, null);
-		rtree.diskOrderScan(diskOrderCursor, leafFrame, metaFrame,
-				diskOrderScanOpCtx);
+		RTreeOpContext diskOrderScanOpCtx = rtree.createOpContext(IndexOp.DISKORDERSCAN);
+		rtree.diskOrderScan(diskOrderCursor, diskOrderScanOpCtx);
 		try {
 			while (diskOrderCursor.hasNext()) {
 				diskOrderCursor.next();
@@ -723,7 +715,7 @@
 
 		RTree rtree = new RTree(bufferCache, fieldCount, cmp, freePageManager,
 				interiorFrameFactory, leafFrameFactory);
-		rtree.create(fileId, leafFrame, metaFrame);
+		rtree.create(fileId);
 		rtree.open(fileId);
 
 		ByteBuffer hyracksFrame = ctx.allocateFrame();
@@ -746,8 +738,7 @@
 		accessor.reset(hyracksFrame);
 		FrameTupleReference tuple = new FrameTupleReference();
 
-		RTreeOpContext insertOpCtx = rtree.createOpContext(IndexOp.INSERT,
-				leafFrame, interiorFrame, metaFrame);
+		RTreeOpContext insertOpCtx = rtree.createOpContext(IndexOp.INSERT);
 
 		Random rnd = new Random();
 		rnd.setSeed(50);
@@ -815,10 +806,8 @@
 		print("DISK-ORDER SCAN:\n");
 		TreeDiskOrderScanCursor diskOrderCursor = new TreeDiskOrderScanCursor(
 				leafFrame);
-		RTreeOpContext diskOrderScanOpCtx = rtree.createOpContext(
-				IndexOp.DISKORDERSCAN, leafFrame, null, null);
-		rtree.diskOrderScan(diskOrderCursor, leafFrame, metaFrame,
-				diskOrderScanOpCtx);
+		RTreeOpContext diskOrderScanOpCtx = rtree.createOpContext(IndexOp.DISKORDERSCAN);
+		rtree.diskOrderScan(diskOrderCursor, diskOrderScanOpCtx);
 		try {
 			while (diskOrderCursor.hasNext()) {
 				diskOrderCursor.next();
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
index 706c19f..c87f0da 100644
--- 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
@@ -134,7 +134,7 @@
 
 		RTree rtree = new RTree(bufferCache, fieldCount, cmp, freePageManager,
 				interiorFrameFactory, leafFrameFactory);
-		rtree.create(fileId, leafFrame, metaFrame);
+		rtree.create(fileId);
 		rtree.open(fileId);
 
 		ByteBuffer hyracksFrame = ctx.allocateFrame();
@@ -155,8 +155,7 @@
 		accessor.reset(hyracksFrame);
 		FrameTupleReference tuple = new FrameTupleReference();
 
-		RTreeOpContext insertOpCtx = rtree.createOpContext(IndexOp.INSERT,
-				leafFrame, interiorFrame, metaFrame);
+		RTreeOpContext insertOpCtx = rtree.createOpContext(IndexOp.INSERT);
 
 		Random rnd = new Random();
 		rnd.setSeed(50);
@@ -243,8 +242,7 @@
 					interiorFrame, leafFrame);
 			SearchPredicate searchPredicate = new SearchPredicate(tuple, cmp);
 
-			RTreeOpContext searchOpCtx = rtree.createOpContext(IndexOp.SEARCH,
-					leafFrame, interiorFrame, metaFrame);
+			RTreeOpContext searchOpCtx = rtree.createOpContext(IndexOp.SEARCH);
 			rtree.search(searchCursor, searchPredicate, searchOpCtx);
 
 			ArrayList<Integer> results = new ArrayList<Integer>();