Changed all indexes to use the new bulkload interface


git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_lsm_tree@1604 123451ca-8445-de46-9d55-352943316053
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 3026630..6fe7720 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
@@ -16,6 +16,8 @@
 package edu.uci.ics.hyracks.storage.am.btree.impls;
 
 import java.util.ArrayList;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
 import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
@@ -29,6 +31,7 @@
 import edu.uci.ics.hyracks.storage.am.btree.exceptions.BTreeNotUpdateableException;
 import edu.uci.ics.hyracks.storage.am.btree.frames.BTreeNSMInteriorFrame;
 import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.IModificationOperationCallback;
 import edu.uci.ics.hyracks.storage.am.common.api.ISearchOperationCallback;
@@ -36,9 +39,7 @@
 import edu.uci.ics.hyracks.storage.am.common.api.ISplitKey;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexAccessor;
 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.ITreeIndexFrameFactory;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
 import edu.uci.ics.hyracks.storage.am.common.api.IndexType;
 import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
 import edu.uci.ics.hyracks.storage.am.common.frames.FrameOpSpaceStatus;
@@ -59,25 +60,13 @@
     private final static long RESTART_OP = Long.MIN_VALUE;
     private final static int MAX_RESTARTS = 10;
 
-    public BTree(IBufferCache bufferCache, int fieldCount, IBinaryComparatorFactory[] cmpFactories,
-            IFreePageManager freePageManager, ITreeIndexFrameFactory interiorFrameFactory,
-            ITreeIndexFrameFactory leafFrameFactory) {
-    	super(bufferCache, fieldCount, cmpFactories, freePageManager, interiorFrameFactory, leafFrameFactory);
-    }
+    private final ReadWriteLock treeLatch;
 
-    @Override
-    public void create(int fileId) throws HyracksDataException {
-        treeLatch.writeLock().lock();
-        try {
-            ITreeIndexFrame leafFrame = leafFrameFactory.createFrame();
-            ITreeIndexMetaDataFrame metaFrame = freePageManager.getMetaDataFrameFactory().createFrame();
-            this.fileId = fileId;
-            freePageManager.open(fileId);
-            freePageManager.init(metaFrame, rootPage);
-            initRoot(leafFrame, true);
-        } finally {
-            treeLatch.writeLock().unlock();
-        }
+    public BTree(IBufferCache bufferCache, IFreePageManager freePageManager,
+            ITreeIndexFrameFactory interiorFrameFactory, ITreeIndexFrameFactory leafFrameFactory,
+            IBinaryComparatorFactory[] cmpFactories, int fieldCount) {
+        super(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories, fieldCount);
+        this.treeLatch = new ReentrantReadWriteLock(true);
     }
 
     private void diskOrderScan(ITreeIndexCursor icursor, BTreeOpContext ctx) throws HyracksDataException {
@@ -153,18 +142,6 @@
         ctx.interiorFrame.setPage(originalPage);
     }
 
-    private void initRoot(ITreeIndexFrame leafFrame, boolean firstInit) throws HyracksDataException {
-        ICachedPage rootNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rootPage), firstInit);
-        rootNode.acquireWriteLatch();
-        try {
-            leafFrame.setPage(rootNode);
-            leafFrame.initBuffer((byte) 0);
-        } finally {
-            rootNode.releaseWriteLatch();
-            bufferCache.unpin(rootNode);
-        }
-    }
-
     private void createNewRoot(BTreeOpContext ctx) throws HyracksDataException, TreeIndexException {
         // Make sure the root is always in the same page.
         ICachedPage leftNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, ctx.splitKey.getLeftPage()),
@@ -694,9 +671,9 @@
         return IndexType.BTREE;
     }
 
-    @SuppressWarnings("rawtypes") 
-    public String printTree(IBTreeLeafFrame leafFrame, IBTreeInteriorFrame interiorFrame, ISerializerDeserializer[] keySerdes)
-            throws Exception {
+    @SuppressWarnings("rawtypes")
+    public String printTree(IBTreeLeafFrame leafFrame, IBTreeInteriorFrame interiorFrame,
+            ISerializerDeserializer[] keySerdes) throws Exception {
         MultiComparator cmp = MultiComparator.create(cmpFactories);
         byte treeHeight = getTreeHeight(leafFrame);
         StringBuilder strBuilder = new StringBuilder();
@@ -823,109 +800,108 @@
             return ctx;
         }
     }
-    
-	@Override
-	public AbstractTreeIndexBulkLoader createBulkLoader(float fillFactor) throws TreeIndexException {
-		try {
-			return new BTreeBulkLoader(fillFactor);
-		} catch (HyracksDataException e) {
-			throw new TreeIndexException(e);
-		}
-	}
-	
-	public class BTreeBulkLoader extends AbstractTreeIndex.AbstractTreeIndexBulkLoader {
-		protected final ISplitKey splitKey;
-		
-		public BTreeBulkLoader(float fillFactor) throws TreeIndexException,
-				HyracksDataException {
-			super(fillFactor);
-			splitKey = new BTreeSplitKey(leafFrame.getTupleWriter().createTupleReference());
+
+    @Override
+    public IIndexBulkLoader createBulkLoader(float fillFactor) throws TreeIndexException {
+        try {
+            return new BTreeBulkLoader(fillFactor);
+        } catch (HyracksDataException e) {
+            throw new TreeIndexException(e);
+        }
+    }
+
+    public class BTreeBulkLoader extends AbstractTreeIndex.AbstractTreeIndexBulkLoader {
+        protected final ISplitKey splitKey;
+
+        public BTreeBulkLoader(float fillFactor) throws TreeIndexException, HyracksDataException {
+            super(fillFactor);
+            splitKey = new BTreeSplitKey(leafFrame.getTupleWriter().createTupleReference());
             splitKey.getTuple().setFieldCount(cmp.getKeyFieldCount());
-		}
+        }
 
-		@Override
-	    public void add(ITupleReference tuple) throws HyracksDataException {
-	        NodeFrontier leafFrontier = nodeFrontiers.get(0);
+        @Override
+        public void add(ITupleReference tuple) throws HyracksDataException {
+            NodeFrontier leafFrontier = nodeFrontiers.get(0);
 
-	        int spaceNeeded = tupleWriter.bytesRequired(tuple) + slotSize;
-	        int spaceUsed = leafFrame.getBuffer().capacity() - leafFrame.getTotalFreeSpace();
+            int spaceNeeded = tupleWriter.bytesRequired(tuple) + slotSize;
+            int spaceUsed = leafFrame.getBuffer().capacity() - leafFrame.getTotalFreeSpace();
 
-	        // try to free space by compression
-	        if (spaceUsed + spaceNeeded > leafMaxBytes) {
-	            leafFrame.compress();
-	            spaceUsed = leafFrame.getBuffer().capacity() - leafFrame.getTotalFreeSpace();
-	        }
+            // try to free space by compression
+            if (spaceUsed + spaceNeeded > leafMaxBytes) {
+                leafFrame.compress();
+                spaceUsed = leafFrame.getBuffer().capacity() - leafFrame.getTotalFreeSpace();
+            }
 
-	        if (spaceUsed + spaceNeeded > leafMaxBytes) {
-	            leafFrontier.lastTuple.resetByTupleIndex(leafFrame, leafFrame.getTupleCount() - 1);
-	            int splitKeySize = tupleWriter.bytesRequired(leafFrontier.lastTuple, 0, cmp.getKeyFieldCount());
-	            splitKey.initData(splitKeySize);
-	            tupleWriter.writeTupleFields(leafFrontier.lastTuple, 0, cmp.getKeyFieldCount(),
-	                    splitKey.getBuffer().array(), 0);
-	            splitKey.getTuple().resetByTupleOffset(splitKey.getBuffer(), 0);
-	            splitKey.setLeftPage(leafFrontier.pageId);
-	            leafFrontier.pageId = freePageManager.getFreePage(metaFrame);
+            if (spaceUsed + spaceNeeded > leafMaxBytes) {
+                leafFrontier.lastTuple.resetByTupleIndex(leafFrame, leafFrame.getTupleCount() - 1);
+                int splitKeySize = tupleWriter.bytesRequired(leafFrontier.lastTuple, 0, cmp.getKeyFieldCount());
+                splitKey.initData(splitKeySize);
+                tupleWriter.writeTupleFields(leafFrontier.lastTuple, 0, cmp.getKeyFieldCount(), splitKey.getBuffer()
+                        .array(), 0);
+                splitKey.getTuple().resetByTupleOffset(splitKey.getBuffer(), 0);
+                splitKey.setLeftPage(leafFrontier.pageId);
+                leafFrontier.pageId = freePageManager.getFreePage(metaFrame);
 
-	            ((IBTreeLeafFrame) leafFrame).setNextLeaf(leafFrontier.pageId);
-	            leafFrontier.page.releaseWriteLatch();
-	            bufferCache.unpin(leafFrontier.page);
+                ((IBTreeLeafFrame) leafFrame).setNextLeaf(leafFrontier.pageId);
+                leafFrontier.page.releaseWriteLatch();
+                bufferCache.unpin(leafFrontier.page);
 
-	            splitKey.setRightPage(leafFrontier.pageId);
-	            propagateBulk(1);
+                splitKey.setRightPage(leafFrontier.pageId);
+                propagateBulk(1);
 
-	            leafFrontier.page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, leafFrontier.pageId),
-	                    true);
-	            leafFrontier.page.acquireWriteLatch();
-	            leafFrame.setPage(leafFrontier.page);
-	            leafFrame.initBuffer((byte) 0);
-	        }
+                leafFrontier.page = bufferCache
+                        .pin(BufferedFileHandle.getDiskPageId(fileId, leafFrontier.pageId), true);
+                leafFrontier.page.acquireWriteLatch();
+                leafFrame.setPage(leafFrontier.page);
+                leafFrame.initBuffer((byte) 0);
+            }
 
-	        leafFrame.setPage(leafFrontier.page);
-	        ((IBTreeLeafFrame) leafFrame).insertSorted(tuple);
-	    }
-		
-	    protected void propagateBulk(int level) throws HyracksDataException {
-	        if (splitKey.getBuffer() == null)
-	            return;
+            leafFrame.setPage(leafFrontier.page);
+            ((IBTreeLeafFrame) leafFrame).insertSorted(tuple);
+        }
 
-	        if (level >= nodeFrontiers.size())
-	            addLevel();
+        protected void propagateBulk(int level) throws HyracksDataException {
+            if (splitKey.getBuffer() == null)
+                return;
 
-	        NodeFrontier frontier = nodeFrontiers.get(level);
-	        interiorFrame.setPage(frontier.page);
+            if (level >= nodeFrontiers.size())
+                addLevel();
 
-	        ITupleReference tuple = splitKey.getTuple();
-	        int spaceNeeded = tupleWriter.bytesRequired(tuple, 0, cmp.getKeyFieldCount()) + slotSize + 4;
-	        int spaceUsed = interiorFrame.getBuffer().capacity() - interiorFrame.getTotalFreeSpace();
-	        if (spaceUsed + spaceNeeded > interiorMaxBytes) {
+            NodeFrontier frontier = nodeFrontiers.get(level);
+            interiorFrame.setPage(frontier.page);
 
-	            ISplitKey copyKey = splitKey.duplicate(leafFrame.getTupleWriter().createTupleReference());
-	            tuple = copyKey.getTuple();
+            ITupleReference tuple = splitKey.getTuple();
+            int spaceNeeded = tupleWriter.bytesRequired(tuple, 0, cmp.getKeyFieldCount()) + slotSize + 4;
+            int spaceUsed = interiorFrame.getBuffer().capacity() - interiorFrame.getTotalFreeSpace();
+            if (spaceUsed + spaceNeeded > interiorMaxBytes) {
 
-	            frontier.lastTuple.resetByTupleIndex(interiorFrame, interiorFrame.getTupleCount() - 1);
-	            int splitKeySize = tupleWriter.bytesRequired(frontier.lastTuple, 0, cmp.getKeyFieldCount());
-	            splitKey.initData(splitKeySize);
-	            tupleWriter
-	                    .writeTupleFields(frontier.lastTuple, 0, cmp.getKeyFieldCount(), splitKey.getBuffer().array(), 0);
-	            splitKey.getTuple().resetByTupleOffset(splitKey.getBuffer(), 0);
-	            splitKey.setLeftPage(frontier.pageId);
+                ISplitKey copyKey = splitKey.duplicate(leafFrame.getTupleWriter().createTupleReference());
+                tuple = copyKey.getTuple();
 
-	            ((IBTreeInteriorFrame) interiorFrame).deleteGreatest();
+                frontier.lastTuple.resetByTupleIndex(interiorFrame, interiorFrame.getTupleCount() - 1);
+                int splitKeySize = tupleWriter.bytesRequired(frontier.lastTuple, 0, cmp.getKeyFieldCount());
+                splitKey.initData(splitKeySize);
+                tupleWriter.writeTupleFields(frontier.lastTuple, 0, cmp.getKeyFieldCount(), splitKey.getBuffer()
+                        .array(), 0);
+                splitKey.getTuple().resetByTupleOffset(splitKey.getBuffer(), 0);
+                splitKey.setLeftPage(frontier.pageId);
 
-	            frontier.page.releaseWriteLatch();
-	            bufferCache.unpin(frontier.page);
-	            frontier.pageId = freePageManager.getFreePage(metaFrame);
+                ((IBTreeInteriorFrame) interiorFrame).deleteGreatest();
 
-	            splitKey.setRightPage(frontier.pageId);
-	            propagateBulk(level + 1);
+                frontier.page.releaseWriteLatch();
+                bufferCache.unpin(frontier.page);
+                frontier.pageId = freePageManager.getFreePage(metaFrame);
 
-	            frontier.page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, frontier.pageId), true);
-	            frontier.page.acquireWriteLatch();
-	            interiorFrame.setPage(frontier.page);
-	            interiorFrame.initBuffer((byte) level);
-	        }
-	        ((IBTreeInteriorFrame) interiorFrame).insertSorted(tuple);
-	    }
-		
-	}
+                splitKey.setRightPage(frontier.pageId);
+                propagateBulk(level + 1);
+
+                frontier.page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, frontier.pageId), true);
+                frontier.page.acquireWriteLatch();
+                interiorFrame.setPage(frontier.page);
+                interiorFrame.initBuffer((byte) level);
+            }
+            ((IBTreeInteriorFrame) interiorFrame).insertSorted(tuple);
+        }
+
+    }
 }
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeUtils.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeUtils.java
index 48b5b38..ff02ce4 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeUtils.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/util/BTreeUtils.java
@@ -27,7 +27,7 @@
         ITreeIndexFrameFactory interiorFrameFactory = new BTreeNSMInteriorFrameFactory(tupleWriterFactory);
         ITreeIndexMetaDataFrameFactory metaFrameFactory = new LIFOMetaDataFrameFactory();
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, 0, metaFrameFactory);
-        BTree btree = new BTree(bufferCache, typeTraits.length, cmpFactories, freePageManager, interiorFrameFactory, leafFrameFactory);
+        BTree btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories, typeTraits.length);
         return btree;
     }
     
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexBulkLoader.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexBulkLoader.java
similarity index 78%
rename from hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexBulkLoader.java
rename to hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexBulkLoader.java
index 3e2da28..fd0bbfc 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexBulkLoader.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexBulkLoader.java
@@ -3,7 +3,7 @@
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;

 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;

 

-public interface ITreeIndexBulkLoader {

+public interface IIndexBulkLoader {

     /**

      * Append a tuple to the index in the context of a bulk load.

      * 

@@ -12,8 +12,7 @@
      * @throws HyracksDataException

      *             If the BufferCache throws while un/pinning or un/latching.

      */

-    public void add(ITupleReference tuple)

-            throws HyracksDataException;

+    public void add(ITupleReference tuple) throws HyracksDataException;

 

     /**

      * Finalize the bulk loading operation in the given context.

@@ -21,7 +20,6 @@
      * @throws HyracksDataException

      *             If the BufferCache throws while un/pinning or un/latching.

      */

-    public void end()

-            throws HyracksDataException;

+    public void end() throws HyracksDataException;

 

 }

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 2c96a22..1965f3f 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
@@ -65,5 +65,5 @@
  	 * @throws TreeIndexException if the user tries to instantiate a second bulk
 	 * loader
  	 */
-	public ITreeIndexBulkLoader createBulkLoader(float fillFactor) throws TreeIndexException;
+	public IIndexBulkLoader createBulkLoader(float fillFactor) throws TreeIndexException;
 }
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndex.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndex.java
index 06efe6b..ac55236 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndex.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndex.java
@@ -16,9 +16,8 @@
 package edu.uci.ics.hyracks.storage.am.common.dataflow;
 
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
-import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexAccessor;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.IModificationOperationCallback;
 import edu.uci.ics.hyracks.storage.am.common.api.ISearchOperationCallback;
 import edu.uci.ics.hyracks.storage.am.common.api.IndexException;
@@ -69,41 +68,10 @@
             ISearchOperationCallback searchCallback);
 
     /**
-     * Prepares the index for bulk loading, returning a bulk load context. The
-     * index may require to be empty for bulk loading.
-     * 
-     * @param fillFactor
-     *            Desired fill factor in [0, 1.0].
-     * @throws HyracksDataException
-     *             If the BufferCache throws while un/pinning or un/latching.
-     * @throws IndexException
-     *             For example, if the index was already loaded and only
-     *             supports a single load.
-     * @returns A new context for bulk loading, required for appending tuples.
+     * @param fillFactor TODO
+     * @throws IndexException TODO
      */
-    public IIndexBulkLoadContext beginBulkLoad(float fillFactor) throws IndexException, HyracksDataException;
-
-    /**
-     * Append a tuple to the index in the context of a bulk load.
-     * 
-     * @param tuple
-     *            Tuple to be inserted.
-     * @param ictx
-     *            Existing bulk load context.
-     * @throws HyracksDataException
-     *             If the BufferCache throws while un/pinning or un/latching.
-     */
-    public void bulkLoadAddTuple(ITupleReference tuple, IIndexBulkLoadContext ictx) throws HyracksDataException;
-
-    /**
-     * Finalize the bulk loading operation in the given context.
-     * 
-     * @param ictx
-     *            Existing bulk load context to be finalized.
-     * @throws HyracksDataException
-     *             If the BufferCache throws while un/pinning or un/latching.
-     */
-    public void endBulkLoad(IIndexBulkLoadContext ictx) throws HyracksDataException;
+    public IIndexBulkLoader createBulkLoader(float fillFactor) throws IndexException;
 
     /**
      * @return BufferCache underlying this index.
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 d9f3a5a..62bfe12 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
@@ -22,14 +22,14 @@
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 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.ITreeIndex;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 
 public class TreeIndexBulkLoadOperatorNodePushable extends AbstractUnaryInputSinkOperatorNodePushable {
     private float fillFactor;
     private final TreeIndexDataflowHelper treeIndexHelper;
     private FrameTupleAccessor accessor;
-    private IIndexBulkLoadContext bulkLoadCtx;
+    private IIndexBulkLoader bulkLoader;
     private ITreeIndex treeIndex;
 
     private IRecordDescriptorProvider recordDescProvider;
@@ -55,7 +55,7 @@
             treeIndexHelper.init(false);
             treeIndex = (ITreeIndex) treeIndexHelper.getIndex();
             treeIndex.open(treeIndexHelper.getIndexFileId());
-            bulkLoadCtx = treeIndex.beginBulkLoad(fillFactor);
+            bulkLoader = treeIndex.createBulkLoader(fillFactor);
         } catch (Exception e) {
             // cleanup in case of failure
             treeIndexHelper.deinit();
@@ -69,14 +69,14 @@
         int tupleCount = accessor.getTupleCount();
         for (int i = 0; i < tupleCount; i++) {
             tuple.reset(accessor, i);
-            treeIndex.bulkLoadAddTuple(tuple, bulkLoadCtx);
+            bulkLoader.add(tuple);
         }
     }
 
     @Override
     public void close() throws HyracksDataException {
         try {
-            treeIndex.endBulkLoad(bulkLoadCtx);
+            bulkLoader.end();
         } catch (Exception e) {
             throw new HyracksDataException(e);
         } finally {
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/AbstractTreeIndex.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/AbstractTreeIndex.java
index bf563b1..bb98306 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/AbstractTreeIndex.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/AbstractTreeIndex.java
@@ -1,8 +1,6 @@
 package edu.uci.ics.hyracks.storage.am.common.impls;

 

 import java.util.ArrayList;

-import java.util.concurrent.locks.ReadWriteLock;

-import java.util.concurrent.locks.ReentrantReadWriteLock;

 import java.util.logging.Level;

 import java.util.logging.Logger;

 

@@ -10,10 +8,9 @@
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;

 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;

 import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;

-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;

+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;

 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;

 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexAccessor;

-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexBulkLoader;

 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;

 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrameFactory;

 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;

@@ -26,48 +23,65 @@
 import edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle;

 

 public abstract class AbstractTreeIndex implements ITreeIndex {

-	

-	protected final static int rootPage = 1;

-	

+

+    protected final static int rootPage = 1;

+

+    protected final IBufferCache bufferCache;

+    protected final IFreePageManager freePageManager;

     protected final ITreeIndexFrameFactory interiorFrameFactory;

     protected final ITreeIndexFrameFactory leafFrameFactory;

-    protected final IFreePageManager freePageManager;

-    protected final IBufferCache bufferCache;

-    protected final int fieldCount;

     protected final IBinaryComparatorFactory[] cmpFactories;

-    protected final ReadWriteLock treeLatch;

+    protected final int fieldCount;

+

     protected int fileId;

-	

-    public AbstractTreeIndex(IBufferCache bufferCache, int fieldCount, IBinaryComparatorFactory[] cmpFactories, IFreePageManager freePageManager,

-            ITreeIndexFrameFactory interiorFrameFactory, ITreeIndexFrameFactory leafFrameFactory) {

+

+    public AbstractTreeIndex(IBufferCache bufferCache, IFreePageManager freePageManager,

+            ITreeIndexFrameFactory interiorFrameFactory, ITreeIndexFrameFactory leafFrameFactory,

+            IBinaryComparatorFactory[] cmpFactories, int fieldCount) {

         this.bufferCache = bufferCache;

-        this.fieldCount = fieldCount;

-        this.cmpFactories = cmpFactories;       

         this.freePageManager = freePageManager;

-        this.treeLatch = new ReentrantReadWriteLock(true);

         this.interiorFrameFactory = interiorFrameFactory;

         this.leafFrameFactory = leafFrameFactory;

+        this.cmpFactories = cmpFactories;

+        this.fieldCount = fieldCount;

     }

-    

-    public boolean isEmptyTree(ITreeIndexFrame leafFrame) throws HyracksDataException {

-    	ICachedPage rootNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rootPage), false);

+

+    public boolean isEmptyTree(ITreeIndexFrame frame) throws HyracksDataException {

+        ICachedPage rootNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rootPage), false);

         rootNode.acquireReadLatch();

         try {

-            leafFrame.setPage(rootNode);

-            if (leafFrame.getLevel() == 0 && leafFrame.getTupleCount() == 0) {

-            	return true;

+            frame.setPage(rootNode);

+            if (frame.getLevel() == 0 && frame.getTupleCount() == 0) {

+                return true;

             } else {

-            	return false;

+                return false;

             }

         } finally {

             rootNode.releaseReadLatch();

             bufferCache.unpin(rootNode);

         }

     }

-    

-    public void open(int fileId) {    	

-    	this.fileId = fileId;

-    	freePageManager.open(fileId);

+

+    public synchronized void create(int fileId) throws HyracksDataException {

+        ITreeIndexFrame frame = leafFrameFactory.createFrame();

+        ITreeIndexMetaDataFrame metaFrame = freePageManager.getMetaDataFrameFactory().createFrame();

+        freePageManager.open(fileId);

+        freePageManager.init(metaFrame, rootPage);

+

+        ICachedPage rootNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rootPage), true);

+        rootNode.acquireWriteLatch();

+        try {

+            frame.setPage(rootNode);

+            frame.initBuffer((byte) 0);

+        } finally {

+            rootNode.releaseWriteLatch();

+            bufferCache.unpin(rootNode);

+        }

+    }

+

+    public void open(int fileId) {

+        this.fileId = fileId;

+        freePageManager.open(fileId);

     }

 

     public void close() {

@@ -78,23 +92,23 @@
     public int getFileId() {

         return fileId;

     }

-    

+

     public IBufferCache getBufferCache() {

         return bufferCache;

     }

-    

-    public byte getTreeHeight(ITreeIndexFrame leafFrame) throws HyracksDataException {

+

+    public byte getTreeHeight(ITreeIndexFrame frame) throws HyracksDataException {

         ICachedPage rootNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rootPage), false);

         rootNode.acquireReadLatch();

         try {

-            leafFrame.setPage(rootNode);

-            return leafFrame.getLevel();

+            frame.setPage(rootNode);

+            return frame.getLevel();

         } finally {

             rootNode.releaseReadLatch();

             bufferCache.unpin(rootNode);

         }

     }

-    

+

     public ITreeIndexFrameFactory getInteriorFrameFactory() {

         return interiorFrameFactory;

     }

@@ -110,60 +124,58 @@
     public IFreePageManager getFreePageManager() {

         return freePageManager;

     }

-    

+

     public int getRootPageId() {

         return rootPage;

-    }    

+    }

 

     public int getFieldCount() {

         return fieldCount;

     }

-    

-    public abstract AbstractTreeIndexBulkLoader createBulkLoader(float fillFactor) throws TreeIndexException;

-    

+

+    public abstract IIndexBulkLoader createBulkLoader(float fillFactor) throws TreeIndexException;

+

     public TreeIndexInsertBulkLoader createInsertBulkLoader() throws TreeIndexException {

         final Logger LOGGER = Logger.getLogger(TreeIndexInsertBulkLoader.class.getName());

-        

+

         if (LOGGER.isLoggable(Level.INFO)) {

             LOGGER.info("Using insert bulkload. This might negatively impact your performance.");

         }

 

-    	return new TreeIndexInsertBulkLoader();

+        return new TreeIndexInsertBulkLoader();

     }

 

+    public abstract class AbstractTreeIndexBulkLoader implements IIndexBulkLoader {

+        protected final MultiComparator cmp;

+        protected final int slotSize;

+        protected final int leafMaxBytes;

+        protected final int interiorMaxBytes;

+        // we maintain a frontier of nodes for each level

+        protected final ArrayList<NodeFrontier> nodeFrontiers = new ArrayList<NodeFrontier>();

+        protected final ITreeIndexMetaDataFrame metaFrame;

+        protected final ITreeIndexTupleWriter tupleWriter;

 

-	public abstract class AbstractTreeIndexBulkLoader implements ITreeIndexBulkLoader {

-		protected final MultiComparator cmp;

-	    protected final int slotSize;

-	    protected final int leafMaxBytes;

-	    protected final int interiorMaxBytes;

-	    // we maintain a frontier of nodes for each level

-	    protected final ArrayList<NodeFrontier> nodeFrontiers = new ArrayList<NodeFrontier>();

-	    protected final ITreeIndexMetaDataFrame metaFrame;

-	    protected final ITreeIndexTupleWriter tupleWriter;

-	    

-		protected ITreeIndexFrame leafFrame, interiorFrame;

-	    

-	    public AbstractTreeIndexBulkLoader(float fillFactor) throws TreeIndexException, HyracksDataException {

+        protected ITreeIndexFrame leafFrame, interiorFrame;

+

+        public AbstractTreeIndexBulkLoader(float fillFactor) throws TreeIndexException, HyracksDataException {

             leafFrame = leafFrameFactory.createFrame();

             interiorFrame = interiorFrameFactory.createFrame();

             metaFrame = freePageManager.getMetaDataFrameFactory().createFrame();

-            

+

             if (!isEmptyTree(leafFrame)) {

-	    		throw new TreeIndexException("Trying to Bulk-load a non-empty tree.");

-	    	}

-            

+                throw new TreeIndexException("Cannot bulk-load a non-empty tree.");

+            }

+

             this.cmp = MultiComparator.create(cmpFactories);

-            

-	    	leafFrame.setMultiComparator(cmp);

-        	interiorFrame.setMultiComparator(cmp);

-        	

+

+            leafFrame.setMultiComparator(cmp);

+            interiorFrame.setMultiComparator(cmp);

+

             tupleWriter = leafFrame.getTupleWriter();

 

             NodeFrontier leafFrontier = new NodeFrontier(leafFrame.createTupleReference());

             leafFrontier.pageId = freePageManager.getFreePage(metaFrame);

-            leafFrontier.page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, leafFrontier.pageId),

-                    true);

+            leafFrontier.page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, leafFrontier.pageId), true);

             leafFrontier.page.acquireWriteLatch();

 

             interiorFrame.setPage(leafFrontier.page);

@@ -173,44 +185,37 @@
             leafFrame.setPage(leafFrontier.page);

             leafFrame.initBuffer((byte) 0);

             leafMaxBytes = (int) ((float) leafFrame.getBuffer().capacity() * fillFactor);

-

             slotSize = leafFrame.getSlotSize();

 

             nodeFrontiers.add(leafFrontier);

-	    }

-	    

-	    public abstract void add(ITupleReference tuple) throws HyracksDataException;

-	    

-	    @Override

-	    public void end() throws HyracksDataException {  	

-	    	// copy root

-	        ICachedPage rootNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rootPage), true);

-	        rootNode.acquireWriteLatch();

-	        NodeFrontier lastNodeFrontier = nodeFrontiers.get(nodeFrontiers.size() - 1);

-	        try {

-	            ICachedPage toBeRoot = lastNodeFrontier.page;

-	            System.arraycopy(toBeRoot.getBuffer().array(), 0, rootNode.getBuffer().array(), 0, toBeRoot.getBuffer()

-	                    .capacity());

-	        } finally {

-	            rootNode.releaseWriteLatch();

-	            bufferCache.unpin(rootNode);

+        }

 

-	            // register old root as free page

-	            freePageManager.addFreePage(metaFrame, lastNodeFrontier.pageId);

+        public abstract void add(ITupleReference tuple) throws HyracksDataException;

 

-	            // make old root a free page

-	            interiorFrame.setPage(lastNodeFrontier.page);

-	            interiorFrame.initBuffer(freePageManager.getFreePageLevelIndicator());

+        @Override

+        public void end() throws HyracksDataException {

+            // copy the root generated from the bulk-load to *the* root page location

+            ICachedPage newRoot = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rootPage), true);

+            newRoot.acquireWriteLatch();

+            NodeFrontier lastNodeFrontier = nodeFrontiers.get(nodeFrontiers.size() - 1);

+            try {

+                System.arraycopy(lastNodeFrontier.page.getBuffer().array(), 0, newRoot.getBuffer().array(), 0,

+                        lastNodeFrontier.page.getBuffer().capacity());

+            } finally {

+                newRoot.releaseWriteLatch();

+                bufferCache.unpin(newRoot);

 

-	            // cleanup

-	            for (int i = 0; i < nodeFrontiers.size(); i++) {

-	                nodeFrontiers.get(i).page.releaseWriteLatch();

-	                bufferCache.unpin(nodeFrontiers.get(i).page);

-	            }

-	        }

-	    }

-	    

-	    protected void addLevel() throws HyracksDataException {

+                // register old root as a free page

+                freePageManager.addFreePage(metaFrame, lastNodeFrontier.pageId);

+

+                for (int i = 0; i < nodeFrontiers.size(); i++) {

+                    nodeFrontiers.get(i).page.releaseWriteLatch();

+                    bufferCache.unpin(nodeFrontiers.get(i).page);

+                }

+            }

+        }

+

+        protected void addLevel() throws HyracksDataException {

             NodeFrontier frontier = new NodeFrontier(tupleWriter.createTupleReference());

             frontier.pageId = freePageManager.getFreePage(metaFrame);

             frontier.page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, frontier.pageId), true);

@@ -220,45 +225,26 @@
             interiorFrame.initBuffer((byte) nodeFrontiers.size());

             nodeFrontiers.add(frontier);

         }

-	}

-	

-	public class TreeIndexInsertBulkLoader implements ITreeIndexBulkLoader {

-		// TODO: What callback to pass here?

-		ITreeIndexAccessor accessor = (ITreeIndexAccessor) createAccessor(

-				NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);

+    }

 

-		@Override

-		public void add(ITupleReference tuple) throws HyracksDataException {

-			try {

-				accessor.insert(tuple);

-			} catch (IndexException e) {

-				throw new HyracksDataException(e);

-			}

-		}

+    public class TreeIndexInsertBulkLoader implements IIndexBulkLoader {

+        ITreeIndexAccessor accessor = (ITreeIndexAccessor) createAccessor(NoOpOperationCallback.INSTANCE,

+                NoOpOperationCallback.INSTANCE);

 

-		@Override

-		public void end() throws HyracksDataException {

-			// do nothing

-		}

-		

-	}

-	

-	@Deprecated

-	protected ITreeIndexBulkLoader bulkloader;

-	

-	@Deprecated

-    public IIndexBulkLoadContext beginBulkLoad(float fillFactor) throws HyracksDataException, TreeIndexException {

-		if(this.bulkloader == null) this.bulkloader = this.createBulkLoader(fillFactor);

-		return null;

-	}

+        @Override

+        public void add(ITupleReference tuple) throws HyracksDataException {

+            try {

+                accessor.insert(tuple);

+            } catch (IndexException e) {

+                throw new HyracksDataException(e);

+            }

+        }

 

-	@Deprecated

-    public void bulkLoadAddTuple(ITupleReference tuple, IIndexBulkLoadContext ictx) throws HyracksDataException {

-		this.bulkloader.add(tuple);

-	}

+        @Override

+        public void end() throws HyracksDataException {

+            // do nothing

+        }

 

-	@Deprecated

-    public void endBulkLoad(IIndexBulkLoadContext ictx) throws HyracksDataException {

-		this.bulkloader.end();

-	}

+    }

+

 }

diff --git a/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/dataflow/InvertedIndexBulkLoadOperatorNodePushable.java b/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/dataflow/InvertedIndexBulkLoadOperatorNodePushable.java
index 62daff2..6da7481 100644
--- a/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/dataflow/InvertedIndexBulkLoadOperatorNodePushable.java
+++ b/hyracks-storage-am-invertedindex/src/main/java/edu/uci/ics/hyracks/storage/am/invertedindex/dataflow/InvertedIndexBulkLoadOperatorNodePushable.java
@@ -23,16 +23,16 @@
 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.btree.impls.BTree;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.dataflow.PermutingFrameTupleReference;
 import edu.uci.ics.hyracks.storage.am.common.dataflow.TreeIndexDataflowHelper;
 import edu.uci.ics.hyracks.storage.am.invertedindex.impls.InvertedIndex;
-import edu.uci.ics.hyracks.storage.am.invertedindex.impls.InvertedIndex.InvertedIndexBulkLoadContext;
 
 public class InvertedIndexBulkLoadOperatorNodePushable extends AbstractUnaryInputSinkOperatorNodePushable {
     private final TreeIndexDataflowHelper btreeDataflowHelper;
     private final InvertedIndexDataflowHelper invIndexDataflowHelper;
     private InvertedIndex invIndex;
-    private InvertedIndex.InvertedIndexBulkLoadContext bulkLoadCtx;
+    private IIndexBulkLoader bulkLoader;
 
     private FrameTupleAccessor accessor;
     private PermutingFrameTupleReference tuple = new PermutingFrameTupleReference();
@@ -72,7 +72,8 @@
         try {
             invIndexDataflowHelper.init(false);
             invIndex = (InvertedIndex) invIndexDataflowHelper.getIndex();
-            bulkLoadCtx = (InvertedIndexBulkLoadContext) invIndex.beginBulkLoad(BTree.DEFAULT_FILL_FACTOR);
+
+            bulkLoader = invIndex.createBulkLoader(BTree.DEFAULT_FILL_FACTOR);
         } catch (Exception e) {
             // Cleanup in case of failure.
             invIndexDataflowHelper.deinit();
@@ -90,14 +91,14 @@
         int tupleCount = accessor.getTupleCount();
         for (int i = 0; i < tupleCount; i++) {
             tuple.reset(accessor, i);
-            invIndex.bulkLoadAddTuple(tuple, bulkLoadCtx);
+            bulkLoader.add(tuple);
         }
     }
 
     @Override
     public void close() throws HyracksDataException {
         try {
-            invIndex.endBulkLoad(bulkLoadCtx);
+            bulkLoader.end();
         } catch (Exception e) {
             throw new HyracksDataException(e);
         } finally {
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 6d94f77..91cac3f 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
@@ -31,6 +31,7 @@
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangePredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexAccessor;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.IModificationOperationCallback;
 import edu.uci.ics.hyracks.storage.am.common.api.ISearchOperationCallback;
@@ -60,7 +61,7 @@
  */
 public class InvertedIndex implements IIndex {
     private final IHyracksCommonContext ctx = new DefaultHyracksCommonContext();
-    
+
     private BTree btree;
     private int rootPageId = 0;
     private IBufferCache bufferCache;
@@ -93,13 +94,12 @@
     @Override
     public void create(int indexFileId) throws HyracksDataException {
     }
-    
+
     @Override
     public void close() {
         this.fileId = -1;
     }
 
-        
     public boolean openCursor(ITreeIndexCursor btreeCursor, RangePredicate btreePred, ITreeIndexAccessor btreeAccessor,
             IInvertedListCursor invListCursor) throws HyracksDataException, IndexException {
         btreeAccessor.search(btreeCursor, btreePred);
@@ -128,114 +128,13 @@
         }
         return ret;
     }
-    
-    @Override
-    public IIndexBulkLoadContext beginBulkLoad(float fillFactor) throws TreeIndexException, HyracksDataException {
-        InvertedIndexBulkLoadContext ctx = new InvertedIndexBulkLoadContext(fillFactor);
-        ctx.init(rootPageId, fileId);
-        return ctx;
-    }
 
-    /**
-     * Assumptions:
-     * The first btree.getMultiComparator().getKeyFieldCount() fields in tuple
-     * are btree keys (e.g., a string token).
-     * The next invListCmp.getKeyFieldCount() fields in tuple are keys of the
-     * inverted list (e.g., primary key).
-     * Key fields of inverted list are fixed size.
-     * 
-     */
-    @Override
-    public void bulkLoadAddTuple(ITupleReference tuple, IIndexBulkLoadContext ictx) throws HyracksDataException {
-        InvertedIndexBulkLoadContext ctx = (InvertedIndexBulkLoadContext) ictx;
-        
-        // First inverted list, copy token to baaos and start new list.
-        if (ctx.currentInvListTokenBaaos.size() == 0) {
-            ctx.currentInvListStartPageId = ctx.currentPageId;
-            ctx.currentInvListStartOffset = invListBuilder.getPos();
-
-            // Remember current token.
-            ctx.currentInvListTokenBaaos.reset();
-            for (int i = 0; i < numTokenFields; i++) {
-                ctx.currentInvListTokenBaaos.write(tuple.getFieldData(i), tuple.getFieldStart(i),
-                        tuple.getFieldLength(i));
-            }
-
-            if (!invListBuilder.startNewList(tuple, numTokenFields)) {
-                ctx.pinNextPage();
-                invListBuilder.setTargetBuffer(ctx.currentPage.getBuffer().array(), 0);
-                if (!invListBuilder.startNewList(tuple, numTokenFields)) {
-                    throw new IllegalStateException("Failed to create first inverted list.");
-                }
-            }
-        }
-
-        // Create new inverted list?
-        ctx.currentInvListToken.reset(ctx.currentInvListTokenBaaos.getByteArray(), 0);
-        if (ctx.tokenCmp.compare(tuple, ctx.currentInvListToken) != 0) {
-
-            // Create entry in btree for last inverted list.
-            createAndInsertBTreeTuple(ctx);
-
-            // Remember new token.
-            ctx.currentInvListTokenBaaos.reset();
-            for (int i = 0; i < numTokenFields; i++) {
-                ctx.currentInvListTokenBaaos.write(tuple.getFieldData(i), tuple.getFieldStart(i),
-                        tuple.getFieldLength(i));
-            }
-
-            // Start new list.
-            if (!invListBuilder.startNewList(tuple, numTokenFields)) {
-                ctx.pinNextPage();
-                invListBuilder.setTargetBuffer(ctx.currentPage.getBuffer().array(), 0);
-                if (!invListBuilder.startNewList(tuple, numTokenFields)) {
-                    throw new IllegalStateException("Failed to start new inverted list after switching to a new page.");
-                }
-            }
-
-            ctx.currentInvListStartPageId = ctx.currentPageId;
-            ctx.currentInvListStartOffset = invListBuilder.getPos();
-        }
-
-        // Append to current inverted list.
-        if (!invListBuilder.appendElement(tuple, numTokenFields, numInvListKeys)) {
-            ctx.pinNextPage();
-            invListBuilder.setTargetBuffer(ctx.currentPage.getBuffer().array(), 0);
-            if (!invListBuilder.appendElement(tuple, numTokenFields, numInvListKeys)) {
-                throw new IllegalStateException(
-                        "Failed to append element to inverted list after switching to a new page.");
-            }
-        }
-    }
-
-    private void createAndInsertBTreeTuple(InvertedIndexBulkLoadContext ctx) throws HyracksDataException {        
-        // Build tuple.        
-        ctx.btreeTupleBuilder.reset();
-        ctx.btreeTupleBuilder.addField(ctx.currentInvListTokenBaaos.getByteArray(), 0,
-                ctx.currentInvListTokenBaaos.size());
-        ctx.btreeTupleBuilder.addField(IntegerSerializerDeserializer.INSTANCE, ctx.currentInvListStartPageId);
-        ctx.btreeTupleBuilder.addField(IntegerSerializerDeserializer.INSTANCE, ctx.currentPageId);
-        ctx.btreeTupleBuilder.addField(IntegerSerializerDeserializer.INSTANCE, ctx.currentInvListStartOffset);
-        ctx.btreeTupleBuilder.addField(IntegerSerializerDeserializer.INSTANCE, invListBuilder.getListSize());
-        // Reset tuple reference and add it.
-        ctx.btreeTupleReference.reset(ctx.btreeTupleBuilder.getFieldEndOffsets(), ctx.btreeTupleBuilder.getByteArray());
-        btree.bulkLoadAddTuple(ctx.btreeTupleReference, ctx.btreeBulkLoadCtx);
-    }
-
-    @Override
-    public void endBulkLoad(IIndexBulkLoadContext ictx) throws HyracksDataException {
-        // Create entry in btree for last inverted list.
-        InvertedIndexBulkLoadContext ctx = (InvertedIndexBulkLoadContext) ictx;
-        createAndInsertBTreeTuple(ctx);
-        btree.endBulkLoad(ctx.btreeBulkLoadCtx);
-        ctx.deinit();
-    }
-    
-    public final class InvertedIndexBulkLoadContext implements IIndexBulkLoadContext {
+    public final class InvertedIndexBulkLoader implements IIndexBulkLoader {
         private final ArrayTupleBuilder btreeTupleBuilder;
         private final ArrayTupleReference btreeTupleReference;
         private final float btreeFillFactor;
         private IIndexBulkLoadContext btreeBulkLoadCtx;
+        private final IIndexBulkLoader btreeBulkloader;
 
         private int currentInvListStartPageId;
         private int currentInvListStartOffset;
@@ -246,28 +145,20 @@
         private ICachedPage currentPage;
         private final MultiComparator tokenCmp;
 
-        public InvertedIndexBulkLoadContext(float btreeFillFactor) {
+        public InvertedIndexBulkLoader(float btreeFillFactor, int startPageId, int fileId) throws IndexException,
+                HyracksDataException {
             this.tokenCmp = MultiComparator.create(btree.getComparatorFactories());
             this.btreeTupleBuilder = new ArrayTupleBuilder(btree.getFieldCount());
             this.btreeTupleReference = new ArrayTupleReference();
             this.btreeFillFactor = btreeFillFactor;
-        }
 
-        public void init(int startPageId, int fileId) throws HyracksDataException, TreeIndexException {
-            btreeBulkLoadCtx = btree.beginBulkLoad(btreeFillFactor);
+            this.btreeBulkloader = btree.createBulkLoader(btreeFillFactor);
             currentPageId = startPageId;
             currentPage = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, currentPageId), true);
             currentPage.acquireWriteLatch();
             invListBuilder.setTargetBuffer(currentPage.getBuffer().array(), 0);
         }
 
-        public void deinit() throws HyracksDataException {
-            if (currentPage != null) {
-                currentPage.releaseWriteLatch();
-                bufferCache.unpin(currentPage);
-            }
-        }
-
         public void pinNextPage() throws HyracksDataException {
             currentPage.releaseWriteLatch();
             bufferCache.unpin(currentPage);
@@ -275,6 +166,101 @@
             currentPage = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, currentPageId), true);
             currentPage.acquireWriteLatch();
         }
+
+        private void createAndInsertBTreeTuple() throws HyracksDataException {
+            // Build tuple.        
+            btreeTupleBuilder.reset();
+            btreeTupleBuilder.addField(currentInvListTokenBaaos.getByteArray(), 0, currentInvListTokenBaaos.size());
+            btreeTupleBuilder.addField(IntegerSerializerDeserializer.INSTANCE, currentInvListStartPageId);
+            btreeTupleBuilder.addField(IntegerSerializerDeserializer.INSTANCE, currentPageId);
+            btreeTupleBuilder.addField(IntegerSerializerDeserializer.INSTANCE, currentInvListStartOffset);
+            btreeTupleBuilder.addField(IntegerSerializerDeserializer.INSTANCE, invListBuilder.getListSize());
+            // Reset tuple reference and add it.
+            btreeTupleReference.reset(btreeTupleBuilder.getFieldEndOffsets(), btreeTupleBuilder.getByteArray());
+            btreeBulkloader.add(btreeTupleReference);
+        }
+
+        /**
+         * Assumptions:
+         * The first btree.getMultiComparator().getKeyFieldCount() fields in tuple
+         * are btree keys (e.g., a string token).
+         * The next invListCmp.getKeyFieldCount() fields in tuple are keys of the
+         * inverted list (e.g., primary key).
+         * Key fields of inverted list are fixed size.
+         * 
+         */
+        @Override
+        public void add(ITupleReference tuple) throws HyracksDataException {
+            // First inverted list, copy token to baaos and start new list.
+            if (currentInvListTokenBaaos.size() == 0) {
+                currentInvListStartPageId = currentPageId;
+                currentInvListStartOffset = invListBuilder.getPos();
+
+                // Remember current token.
+                currentInvListTokenBaaos.reset();
+                for (int i = 0; i < numTokenFields; i++) {
+                    currentInvListTokenBaaos.write(tuple.getFieldData(i), tuple.getFieldStart(i),
+                            tuple.getFieldLength(i));
+                }
+
+                if (!invListBuilder.startNewList(tuple, numTokenFields)) {
+                    pinNextPage();
+                    invListBuilder.setTargetBuffer(currentPage.getBuffer().array(), 0);
+                    if (!invListBuilder.startNewList(tuple, numTokenFields)) {
+                        throw new IllegalStateException("Failed to create first inverted list.");
+                    }
+                }
+            }
+
+            // Create new inverted list?
+            currentInvListToken.reset(currentInvListTokenBaaos.getByteArray(), 0);
+            if (tokenCmp.compare(tuple, currentInvListToken) != 0) {
+
+                // Create entry in btree for last inverted list.
+                createAndInsertBTreeTuple();
+
+                // Remember new token.
+                currentInvListTokenBaaos.reset();
+                for (int i = 0; i < numTokenFields; i++) {
+                    currentInvListTokenBaaos.write(tuple.getFieldData(i), tuple.getFieldStart(i),
+                            tuple.getFieldLength(i));
+                }
+
+                // Start new list.
+                if (!invListBuilder.startNewList(tuple, numTokenFields)) {
+                    pinNextPage();
+                    invListBuilder.setTargetBuffer(currentPage.getBuffer().array(), 0);
+                    if (!invListBuilder.startNewList(tuple, numTokenFields)) {
+                        throw new IllegalStateException(
+                                "Failed to start new inverted list after switching to a new page.");
+                    }
+                }
+
+                currentInvListStartPageId = currentPageId;
+                currentInvListStartOffset = invListBuilder.getPos();
+            }
+
+            // Append to current inverted list.
+            if (!invListBuilder.appendElement(tuple, numTokenFields, numInvListKeys)) {
+                pinNextPage();
+                invListBuilder.setTargetBuffer(currentPage.getBuffer().array(), 0);
+                if (!invListBuilder.appendElement(tuple, numTokenFields, numInvListKeys)) {
+                    throw new IllegalStateException(
+                            "Failed to append element to inverted list after switching to a new page.");
+                }
+            }
+        }
+
+        @Override
+        public void end() throws HyracksDataException {
+            createAndInsertBTreeTuple();
+            btreeBulkloader.end();
+
+            if (currentPage != null) {
+                currentPage.releaseWriteLatch();
+                bufferCache.unpin(currentPage);
+            }
+        }
     }
 
     @Override
@@ -289,7 +275,7 @@
     public IBinaryComparatorFactory[] getInvListElementCmpFactories() {
         return invListCmpFactories;
     }
-    
+
     public ITypeTraits[] getTypeTraits() {
         return invListTypeTraits;
     }
@@ -297,14 +283,14 @@
     public BTree getBTree() {
         return btree;
     }
-    
-    public class InvertedIndexAccessor implements IIndexAccessor {        
+
+    public class InvertedIndexAccessor implements IIndexAccessor {
         private final IInvertedIndexSearcher searcher;
-        
+
         public InvertedIndexAccessor(InvertedIndex index) {
             this.searcher = new TOccurrenceSearcher(ctx, index, tokenizer);
         }
-        
+
         @Override
         public void insert(ITupleReference tuple) throws HyracksDataException, IndexException {
             // TODO Auto-generated method stub
@@ -322,9 +308,9 @@
 
         @Override
         public void upsert(ITupleReference tuple) throws HyracksDataException, TreeIndexException {
-        	// TODO Auto-generated method stub
+            // TODO Auto-generated method stub
         }
-        
+
         @Override
         public IIndexCursor createSearchCursor() {
             return new InvertedIndexSearchCursor(searcher);
@@ -335,14 +321,15 @@
                 IndexException {
             searcher.search((InvertedIndexSearchCursor) cursor, (InvertedIndexSearchPredicate) searchPred);
         }
-        
+
         public IInvertedIndexSearcher getSearcher() {
             return searcher;
         }
     }
-    
+
     @Override
-    public IIndexAccessor createAccessor(IModificationOperationCallback modificationCallback, ISearchOperationCallback searchCallback) {
+    public IIndexAccessor createAccessor(IModificationOperationCallback modificationCallback,
+            ISearchOperationCallback searchCallback) {
         return new InvertedIndexAccessor(this);
     }
 
@@ -373,4 +360,13 @@
             return null;
         }
     }
+
+    @Override
+    public IIndexBulkLoader createBulkLoader(float fillFactor) throws IndexException {
+        try {
+            return new InvertedIndexBulkLoader(fillFactor, rootPageId, fileId);
+        } catch (HyracksDataException e) {
+            throw new IndexException(e);
+        }
+    }
 }
diff --git a/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java b/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java
index 6742734..1e5e0cd 100644
--- a/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java
+++ b/hyracks-storage-am-lsm-btree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/btree/impls/LSMBTree.java
@@ -31,7 +31,7 @@
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangePredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexAccessor;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexOpContext;
 import edu.uci.ics.hyracks.storage.am.common.api.IModificationOperationCallback;
@@ -39,7 +39,6 @@
 import edu.uci.ics.hyracks.storage.am.common.api.ISearchPredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexAccessor;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrameFactory;
 import edu.uci.ics.hyracks.storage.am.common.api.IndexException;
@@ -99,8 +98,8 @@
             BTreeFactory diskBTreeFactory, BTreeFactory bulkLoadBTreeFactory, IFileMapProvider diskFileMapProvider,
             int fieldCount, IBinaryComparatorFactory[] cmpFactories, ILSMFlushController flushController,
             ILSMMergePolicy mergePolicy, ILSMOperationTracker opTracker, ILSMIOScheduler ioScheduler) {
-        memBTree = new BTree(memBufferCache, fieldCount, cmpFactories, memFreePageManager, interiorFrameFactory,
-                insertLeafFrameFactory);
+        memBTree = new BTree(memBufferCache, memFreePageManager, interiorFrameFactory, insertLeafFrameFactory,
+                cmpFactories, fieldCount);
         this.memFreePageManager = memFreePageManager;
         this.insertLeafFrameFactory = insertLeafFrameFactory;
         this.deleteLeafFrameFactory = deleteLeafFrameFactory;
@@ -191,16 +190,16 @@
         memBTreeAccessor.search(scanCursor, nullPred);
         BTree diskBTree = createFlushTarget();
         // Bulk load the tuples from the in-memory BTree into the new disk BTree.
-        IIndexBulkLoadContext bulkLoadCtx = diskBTree.beginBulkLoad(1.0f);
+        IIndexBulkLoader bulkLoader = diskBTree.createBulkLoader(1.0f);
         try {
             while (scanCursor.hasNext()) {
                 scanCursor.next();
-                diskBTree.bulkLoadAddTuple(scanCursor.getTuple(), bulkLoadCtx);
+                bulkLoader.add(scanCursor.getTuple());
             }
         } finally {
             scanCursor.close();
         }
-        diskBTree.endBulkLoad(bulkLoadCtx);
+        bulkLoader.end();
         return diskBTree;
     }
 
@@ -308,17 +307,17 @@
 
         // Bulk load the tuples from all on-disk BTrees into the new BTree.
         BTree mergedBTree = createMergeTarget(mergingDiskBTrees);
-        IIndexBulkLoadContext bulkLoadCtx = mergedBTree.beginBulkLoad(1.0f);
+        IIndexBulkLoader bulkLoader = mergedBTree.createBulkLoader(1.0f);
         try {
             while (cursor.hasNext()) {
                 cursor.next();
                 ITupleReference frameTuple = cursor.getTuple();
-                mergedBTree.bulkLoadAddTuple(frameTuple, bulkLoadCtx);
+                bulkLoader.add(frameTuple);
             }
         } finally {
             cursor.close();
         }
-        mergedBTree.endBulkLoad(bulkLoadCtx);
+        bulkLoader.end();
         return mergedBTree;
     }
 
@@ -351,11 +350,11 @@
     }
 
     @Override
-    public ITreeIndexBulkLoader createBulkLoader(float fillLevel) throws TreeIndexException {
+    public IIndexBulkLoader createBulkLoader(float fillLevel) throws TreeIndexException {
         return new LSMBTreeBulkLoader(fillLevel);
     }
 
-    public class LSMBTreeBulkLoader implements ITreeIndexBulkLoader {
+    public class LSMBTreeBulkLoader implements IIndexBulkLoader {
         private final BTree diskBTree;
         private final BTreeBulkLoader bulkLoader;
 
@@ -381,25 +380,6 @@
 
     }
 
-    @Deprecated
-    private ITreeIndexBulkLoader bulkloader;
-
-    @Override
-    public IIndexBulkLoadContext beginBulkLoad(float fillFactor) throws TreeIndexException, HyracksDataException {
-        bulkloader = createBulkLoader(fillFactor);
-        return null;
-    }
-
-    @Override
-    public void bulkLoadAddTuple(ITupleReference tuple, IIndexBulkLoadContext ictx) throws HyracksDataException {
-        bulkloader.add(tuple);
-    }
-
-    @Override
-    public void endBulkLoad(IIndexBulkLoadContext ictx) throws HyracksDataException {
-        bulkloader.end();
-    }
-
     @Override
     public ITreeIndexFrameFactory getLeafFrameFactory() {
         return memBTree.getLeafFrameFactory();
diff --git a/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/BTreeFactory.java b/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/BTreeFactory.java
index b51b84b..8f502fa 100644
--- a/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/BTreeFactory.java
+++ b/hyracks-storage-am-lsm-common/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/common/impls/BTreeFactory.java
@@ -31,8 +31,8 @@
 
     @Override
     public BTree createIndexInstance() {
-        return new BTree(bufferCache, fieldCount, cmpFactories, freePageManagerFactory.createFreePageManager(),
-                interiorFrameFactory, leafFrameFactory);
+        return new BTree(bufferCache, freePageManagerFactory.createFreePageManager(), interiorFrameFactory, leafFrameFactory,
+                cmpFactories, fieldCount);
     }
 
 }
diff --git a/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/AbstractLSMRTree.java b/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/AbstractLSMRTree.java
index 807548c..d105cea 100644
--- a/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/AbstractLSMRTree.java
+++ b/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/AbstractLSMRTree.java
@@ -28,10 +28,8 @@
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTree;
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangePredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexOpContext;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrameFactory;
 import edu.uci.ics.hyracks.storage.am.common.api.IndexType;
@@ -121,11 +119,11 @@
             IBinaryComparatorFactory[] btreeCmpFactories, ILinearizeComparatorFactory linearizer,
             int[] comparatorFields, IBinaryComparatorFactory[] linearizerArray, ILSMFlushController flushController,
             ILSMMergePolicy mergePolicy, ILSMOperationTracker opTracker, ILSMIOScheduler ioScheduler) {
-        RTree memRTree = new RTree(memBufferCache, fieldCount, rtreeCmpFactories, memFreePageManager,
-                rtreeInteriorFrameFactory, rtreeLeafFrameFactory);
+        RTree memRTree = new RTree(memBufferCache, memFreePageManager, rtreeInteriorFrameFactory,
+                rtreeLeafFrameFactory, rtreeCmpFactories, fieldCount);
         // TODO: Do we need another operation callback here?
-        BTree memBTree = new BTree(memBufferCache, fieldCount, btreeCmpFactories, memFreePageManager,
-                btreeInteriorFrameFactory, btreeLeafFrameFactory);
+        BTree memBTree = new BTree(memBufferCache, memFreePageManager, btreeInteriorFrameFactory,
+                btreeLeafFrameFactory, btreeCmpFactories, fieldCount);
         memComponent = new LSMRTreeComponent(memRTree, memBTree);
         this.memFreePageManager = memFreePageManager;
         this.diskBufferCache = diskRTreeFactory.getBufferCache();
@@ -182,25 +180,6 @@
         return diskTree;
     }
 
-    @Deprecated
-    private ITreeIndexBulkLoader bulkloader;
-
-    @Override
-    public IIndexBulkLoadContext beginBulkLoad(float fillFactor) throws TreeIndexException, HyracksDataException {
-        bulkloader = createBulkLoader(fillFactor);
-        return null;
-    }
-
-    @Override
-    public void bulkLoadAddTuple(ITupleReference tuple, IIndexBulkLoadContext ictx) throws HyracksDataException {
-        bulkloader.add(tuple);
-    }
-
-    @Override
-    public void endBulkLoad(IIndexBulkLoadContext ictx) throws HyracksDataException {
-        bulkloader.end();
-    }
-
     @Override
     public ITreeIndexFrameFactory getLeafFrameFactory() {
         return memComponent.getRTree().getLeafFrameFactory();
diff --git a/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTree.java b/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTree.java
index 871768c..8d25eb0 100644
--- a/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTree.java
+++ b/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTree.java
@@ -28,14 +28,13 @@
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTree;
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangePredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexAccessor;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexOpContext;
 import edu.uci.ics.hyracks.storage.am.common.api.IModificationOperationCallback;
 import edu.uci.ics.hyracks.storage.am.common.api.ISearchOperationCallback;
 import edu.uci.ics.hyracks.storage.am.common.api.ISearchPredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexAccessor;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexBulkLoader;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrameFactory;
 import edu.uci.ics.hyracks.storage.am.common.api.IndexException;
@@ -182,7 +181,7 @@
         LSMRTreeFileNameComponent fileNames = (LSMRTreeFileNameComponent) fileManager.getRelFlushFileName();
         FileReference rtreeFile = fileManager.createFlushFile(fileNames.getRTreeFileName());
         RTree diskRTree = (RTree) createDiskTree(diskRTreeFactory, rtreeFile, true);
-        ITreeIndexBulkLoader rTreeBulkloader;
+        IIndexBulkLoader rTreeBulkloader;
         ITreeIndexCursor cursor;
 
         IBinaryComparatorFactory[] linearizerArray = { linearizer };
@@ -236,7 +235,7 @@
         BTree diskBTree = (BTree) createDiskTree(diskBTreeFactory, btreeFile, true);
 
         // BulkLoad the tuples from the in-memory tree into the new disk BTree.
-        ITreeIndexBulkLoader bTreeBulkloader = diskBTree.createBulkLoader(1.0f);
+        IIndexBulkLoader bTreeBulkloader = diskBTree.createBulkLoader(1.0f);
         try {
             while (btreeScanCursor.hasNext()) {
                 btreeScanCursor.next();
@@ -277,7 +276,7 @@
         RTree mergedRTree = (RTree) createDiskTree(diskRTreeFactory, rtreeFile, true);
         BTree mergedBTree = (BTree) createDiskTree(diskBTreeFactory, btreeFile, true);
 
-        ITreeIndexBulkLoader bulkloader = mergedRTree.createBulkLoader(1.0f);
+        IIndexBulkLoader bulkloader = mergedRTree.createBulkLoader(1.0f);
         try {
             while (cursor.hasNext()) {
                 cursor.next();
@@ -290,8 +289,7 @@
         bulkloader.end();
 
         // Load an empty BTree tree.
-        IIndexBulkLoadContext btreeBulkLoadCtx = mergedBTree.beginBulkLoad(1.0f);
-        mergedBTree.endBulkLoad(btreeBulkLoadCtx);
+        mergedBTree.createBulkLoader(1.0f).end();
 
         return new LSMRTreeComponent(mergedRTree, mergedBTree);
     }
@@ -338,11 +336,11 @@
     }
 
     @Override
-    public ITreeIndexBulkLoader createBulkLoader(float fillLevel) throws TreeIndexException {
+    public IIndexBulkLoader createBulkLoader(float fillLevel) throws TreeIndexException {
         return new LSMRTreeBulkLoader(fillLevel);
     }
 
-    public class LSMRTreeBulkLoader implements ITreeIndexBulkLoader {
+    public class LSMRTreeBulkLoader implements IIndexBulkLoader {
         private final RTree diskRTree;
         private final BTree diskBTree;
         private final RTreeBulkLoader bulkLoader;
diff --git a/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeBulkLoadContext.java b/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeBulkLoadContext.java
deleted file mode 100644
index 1f74be8..0000000
--- a/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeBulkLoadContext.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2009-2010 by The Regents of the University of California
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * you may obtain a copy of the License from
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package edu.uci.ics.hyracks.storage.am.lsm.rtree.impls;
-
-import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
-import edu.uci.ics.hyracks.storage.am.btree.impls.BTree;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
-import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
-import edu.uci.ics.hyracks.storage.am.rtree.impls.RTree;
-
-public class LSMRTreeBulkLoadContext implements IIndexBulkLoadContext {
-    private final RTree rtree;
-    private final BTree btree;
-    private IIndexBulkLoadContext bulkLoadCtx;
-
-    public LSMRTreeBulkLoadContext(RTree rtree, BTree btree) {
-        this.rtree = rtree;
-        this.btree = btree;
-    }
-
-    public void beginBulkLoad(float fillFactor) throws HyracksDataException, TreeIndexException {
-        bulkLoadCtx = rtree.beginBulkLoad(fillFactor);
-    }
-
-    public RTree getRTree() {
-        return rtree;
-    }
-
-    public BTree getBTree() {
-        return btree;
-    }
-
-    public IIndexBulkLoadContext getBulkLoadCtx() {
-        return bulkLoadCtx;
-    }
-}
\ No newline at end of file
diff --git a/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuples.java b/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuples.java
index eb79c3a..1fb77a9 100644
--- a/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuples.java
+++ b/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/LSMRTreeWithAntiMatterTuples.java
@@ -35,7 +35,7 @@
 import edu.uci.ics.hyracks.storage.am.common.api.ISearchPredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexAccessor;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexBulkLoader;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrameFactory;
 import edu.uci.ics.hyracks.storage.am.common.api.IndexException;
@@ -242,7 +242,7 @@
             bTreeTupleSorter.sort();
         }
 
-        ITreeIndexBulkLoader rTreeBulkloader = diskRTree.createBulkLoader(1.0f);
+        IIndexBulkLoader rTreeBulkloader = diskRTree.createBulkLoader(1.0f);
         LSMRTreeFlushCursor cursor = new LSMRTreeFlushCursor(rTreeTupleSorter, bTreeTupleSorter, comparatorFields,
                 linearizerArray);
         cursor.open(null, null);
@@ -282,7 +282,7 @@
 
         // Bulk load the tuples from all on-disk RTrees into the new RTree.
         RTree mergedRTree = createMergeTarget(mergingDiskRTrees);
-        ITreeIndexBulkLoader bulkloader = mergedRTree.createBulkLoader(1.0f);
+        IIndexBulkLoader bulkloader = mergedRTree.createBulkLoader(1.0f);
         try {
             while (cursor.hasNext()) {
                 cursor.next();
@@ -331,7 +331,7 @@
     }
 
     @Override
-    public ITreeIndexBulkLoader createBulkLoader(float fillLevel) throws TreeIndexException {
+    public IIndexBulkLoader createBulkLoader(float fillLevel) throws TreeIndexException {
         return new LSMRTreeWithAntiMatterTuplesBulkLoader(fillLevel);
     }
 
@@ -341,7 +341,7 @@
         return (RTree) createDiskTree(bulkLoadRTreeFactory, fileRef, true);
     }
 
-    public class LSMRTreeWithAntiMatterTuplesBulkLoader implements ITreeIndexBulkLoader {
+    public class LSMRTreeWithAntiMatterTuplesBulkLoader implements IIndexBulkLoader {
         private final RTree diskRTree;
         private final RTreeBulkLoader bulkLoader;
 
diff --git a/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/RTreeFactory.java b/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/RTreeFactory.java
index 3e19097..f1dbd43 100644
--- a/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/RTreeFactory.java
+++ b/hyracks-storage-am-lsm-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/lsm/rtree/impls/RTreeFactory.java
@@ -31,8 +31,8 @@
 
     @Override
     public RTree createIndexInstance() {
-        return new RTree(bufferCache, fieldCount, cmpFactories, freePageManagerFactory.createFreePageManager(),
-                interiorFrameFactory, leafFrameFactory);
+        return new RTree(bufferCache, freePageManagerFactory.createFreePageManager(), interiorFrameFactory, leafFrameFactory,
+                cmpFactories, fieldCount);
     }
 
 }
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 356c097..6a69d9b 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
@@ -24,6 +24,7 @@
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
 import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexOpContext;
 import edu.uci.ics.hyracks.storage.am.common.api.IModificationOperationCallback;
@@ -33,7 +34,6 @@
 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.ITreeIndexFrameFactory;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleReference;
 import edu.uci.ics.hyracks.storage.am.common.api.IndexException;
 import edu.uci.ics.hyracks.storage.am.common.api.IndexType;
@@ -60,10 +60,10 @@
     // Global node sequence number used for the concurrency control protocol
     private final AtomicLong globalNsn;
 
-    public RTree(IBufferCache bufferCache, int fieldCount, IBinaryComparatorFactory[] cmpFactories,
-            IFreePageManager freePageManager, ITreeIndexFrameFactory interiorFrameFactory,
-            ITreeIndexFrameFactory leafFrameFactory) {
-        super(bufferCache, fieldCount, cmpFactories, freePageManager, interiorFrameFactory, leafFrameFactory);
+    public RTree(IBufferCache bufferCache, IFreePageManager freePageManager,
+            ITreeIndexFrameFactory interiorFrameFactory, ITreeIndexFrameFactory leafFrameFactory,
+            IBinaryComparatorFactory[] cmpFactories, int fieldCount) {
+        super(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories, fieldCount);
         globalNsn = new AtomicLong();
     }
 
@@ -136,31 +136,6 @@
         }
     }
 
-    @Override
-    public void create(int fileId) throws HyracksDataException {
-        treeLatch.writeLock().lock();
-        try {
-            ITreeIndexFrame leafFrame = leafFrameFactory.createFrame();
-            ITreeIndexMetaDataFrame metaFrame = freePageManager.getMetaDataFrameFactory().createFrame();
-            freePageManager.open(fileId);
-            freePageManager.init(metaFrame, rootPage);
-
-            // initialize root page
-            ICachedPage rootNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rootPage), true);
-
-            rootNode.acquireWriteLatch();
-            try {
-                leafFrame.setPage(rootNode);
-                leafFrame.initBuffer((byte) 0);
-            } finally {
-                rootNode.releaseWriteLatch();
-                bufferCache.unpin(rootNode);
-            }
-        } finally {
-            treeLatch.writeLock().unlock();
-        }
-    }
-
     private RTreeOpContext createOpContext(IModificationOperationCallback modificationCallback,
             ISearchOperationCallback searchCallback) {
         return new RTreeOpContext((IRTreeLeafFrame) leafFrameFactory.createFrame(),
@@ -875,7 +850,7 @@
     }
 
     @Override
-    public AbstractTreeIndexBulkLoader createBulkLoader(float fillFactor) throws TreeIndexException {
+    public IIndexBulkLoader createBulkLoader(float fillFactor) throws TreeIndexException {
         try {
             return new RTreeBulkLoader(fillFactor);
         } catch (HyracksDataException e) {
diff --git a/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/util/RTreeUtils.java b/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/util/RTreeUtils.java
index 6527d40..cd7c6f7 100644
--- a/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/util/RTreeUtils.java
+++ b/hyracks-storage-am-rtree/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/util/RTreeUtils.java
@@ -48,8 +48,8 @@
         ITreeIndexMetaDataFrameFactory metaFrameFactory = new LIFOMetaDataFrameFactory();
 
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, 0, metaFrameFactory);
-        RTree rtree = new RTree(bufferCache, typeTraits.length, cmpFactories, freePageManager, interiorFrameFactory,
-                leafFrameFactory);
+        RTree rtree = new RTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories,
+                typeTraits.length);
         return rtree;
     }
 
diff --git a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexExamplesTest.java b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexExamplesTest.java
index 659325b..827e6d0 100644
--- a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexExamplesTest.java
+++ b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/btree/OrderedIndexExamplesTest.java
@@ -36,10 +36,10 @@
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangePredicate;
 import edu.uci.ics.hyracks.storage.am.btree.util.BTreeUtils;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexAccessor;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexAccessor;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
 import edu.uci.ics.hyracks.storage.am.common.impls.NoOpOperationCallback;
@@ -55,7 +55,7 @@
             throws TreeIndexException;
 
     protected abstract int getIndexFileId();
-    
+
     /**
      * Fixed-Length Key,Value Example.
      * 
@@ -94,7 +94,8 @@
         }
         ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
-        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE,
+                NoOpOperationCallback.INSTANCE);
         int numInserts = 10000;
         for (int i = 0; i < numInserts; i++) {
             int f0 = rnd.nextInt() % numInserts;
@@ -173,7 +174,8 @@
         }
         ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
-        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE,
+                NoOpOperationCallback.INSTANCE);
         int numInserts = 10000;
         for (int i = 0; i < 10000; i++) {
             int f0 = rnd.nextInt() % 2000;
@@ -250,7 +252,8 @@
         }
         ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
-        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE,
+                NoOpOperationCallback.INSTANCE);
         // Max string length to be generated.
         int maxLength = 10;
         int numInserts = 10000;
@@ -325,7 +328,8 @@
 
         ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
-        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE,
+                NoOpOperationCallback.INSTANCE);
         // Max string length to be generated.
         int runs = 3;
         for (int run = 0; run < runs; run++) {
@@ -427,7 +431,8 @@
         if (LOGGER.isLoggable(Level.INFO)) {
             LOGGER.info("Inserting into tree...");
         }
-        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE,
+                NoOpOperationCallback.INSTANCE);
         ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
         int maxLength = 10;
@@ -517,20 +522,21 @@
             LOGGER.info("Bulk loading " + ins + " tuples");
         }
         long start = System.currentTimeMillis();
-        IIndexBulkLoadContext bulkLoadCtx = treeIndex.beginBulkLoad(0.7f);
+        IIndexBulkLoader bulkLoader = treeIndex.createBulkLoader(0.7f);
         ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
         for (int i = 0; i < ins; i++) {
             TupleUtils.createIntegerTuple(tb, tuple, i, i, 5);
-            treeIndex.bulkLoadAddTuple(tuple, bulkLoadCtx);
+            bulkLoader.add(tuple);
         }
-        treeIndex.endBulkLoad(bulkLoadCtx);
+        bulkLoader.end();
         long end = System.currentTimeMillis();
         if (LOGGER.isLoggable(Level.INFO)) {
             LOGGER.info(ins + " tuples loaded in " + (end - start) + "ms");
         }
 
-        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE,
+                NoOpOperationCallback.INSTANCE);
 
         // Build low key.
         ArrayTupleBuilder lowKeyTb = new ArrayTupleBuilder(1);
@@ -548,12 +554,11 @@
         treeIndex.close();
     }
 
-    private void orderedScan(IIndexAccessor indexAccessor, ISerializerDeserializer[] fieldSerdes)
-            throws Exception {
+    private void orderedScan(IIndexAccessor indexAccessor, ISerializerDeserializer[] fieldSerdes) throws Exception {
         if (LOGGER.isLoggable(Level.INFO)) {
             LOGGER.info("Ordered Scan:");
         }
-        IIndexCursor scanCursor = (IIndexCursor) indexAccessor.createSearchCursor();        
+        IIndexCursor scanCursor = (IIndexCursor) indexAccessor.createSearchCursor();
         RangePredicate nullPred = new RangePredicate(null, null, true, true, null, null);
         indexAccessor.search(scanCursor, nullPred);
         try {
@@ -570,45 +575,44 @@
         }
     }
 
-	private void diskOrderScan(IIndexAccessor indexAccessor,
-			ISerializerDeserializer[] fieldSerdes) throws Exception {
-		try {
-			if (LOGGER.isLoggable(Level.INFO)) {
-				LOGGER.info("Disk-Order Scan:");
-			}
-			ITreeIndexAccessor treeIndexAccessor = (ITreeIndexAccessor) indexAccessor;
-			TreeDiskOrderScanCursor diskOrderCursor = (TreeDiskOrderScanCursor) treeIndexAccessor
-					.createDiskOrderScanCursor();
-			treeIndexAccessor.diskOrderScan(diskOrderCursor);
-			try {
-				while (diskOrderCursor.hasNext()) {
-					diskOrderCursor.next();
-					ITupleReference frameTuple = diskOrderCursor.getTuple();
-					String rec = TupleUtils.printTuple(frameTuple, fieldSerdes);
-					if (LOGGER.isLoggable(Level.INFO)) {
-						LOGGER.info(rec);
-					}
-				}
-			} finally {
-				diskOrderCursor.close();
-			}
-		} catch (UnsupportedOperationException e) {
-			// Ignore exception because some indexes, e.g. the LSMBTree, don't
-			// support disk-order scan.
-			if (LOGGER.isLoggable(Level.INFO)) {
-				LOGGER.info("Ignoring disk-order scan since it's not supported.");
-			}
-		} catch (ClassCastException e) {
-			// Ignore exception because IIndexAccessor sometimes isn't
-			// an ITreeIndexAccessor, e.g., for the LSMBTree.
-			if (LOGGER.isLoggable(Level.INFO)) {
-				LOGGER.info("Ignoring disk-order scan since it's not supported.");
-			}
-		}
-	}
+    private void diskOrderScan(IIndexAccessor indexAccessor, ISerializerDeserializer[] fieldSerdes) throws Exception {
+        try {
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Disk-Order Scan:");
+            }
+            ITreeIndexAccessor treeIndexAccessor = (ITreeIndexAccessor) indexAccessor;
+            TreeDiskOrderScanCursor diskOrderCursor = (TreeDiskOrderScanCursor) treeIndexAccessor
+                    .createDiskOrderScanCursor();
+            treeIndexAccessor.diskOrderScan(diskOrderCursor);
+            try {
+                while (diskOrderCursor.hasNext()) {
+                    diskOrderCursor.next();
+                    ITupleReference frameTuple = diskOrderCursor.getTuple();
+                    String rec = TupleUtils.printTuple(frameTuple, fieldSerdes);
+                    if (LOGGER.isLoggable(Level.INFO)) {
+                        LOGGER.info(rec);
+                    }
+                }
+            } finally {
+                diskOrderCursor.close();
+            }
+        } catch (UnsupportedOperationException e) {
+            // Ignore exception because some indexes, e.g. the LSMBTree, don't
+            // support disk-order scan.
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Ignoring disk-order scan since it's not supported.");
+            }
+        } catch (ClassCastException e) {
+            // Ignore exception because IIndexAccessor sometimes isn't
+            // an ITreeIndexAccessor, e.g., for the LSMBTree.
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Ignoring disk-order scan since it's not supported.");
+            }
+        }
+    }
 
-    private void rangeSearch(IBinaryComparatorFactory[] cmpFactories, IIndexAccessor indexAccessor, ISerializerDeserializer[] fieldSerdes,
-            ITupleReference lowKey, ITupleReference highKey) throws Exception {
+    private void rangeSearch(IBinaryComparatorFactory[] cmpFactories, IIndexAccessor indexAccessor,
+            ISerializerDeserializer[] fieldSerdes, ITupleReference lowKey, ITupleReference highKey) throws Exception {
         if (LOGGER.isLoggable(Level.INFO)) {
             String lowKeyString = TupleUtils.printTuple(lowKey, fieldSerdes);
             String highKeyString = TupleUtils.printTuple(highKey, fieldSerdes);
@@ -617,8 +621,7 @@
         ITreeIndexCursor rangeCursor = (ITreeIndexCursor) indexAccessor.createSearchCursor();
         MultiComparator lowKeySearchCmp = BTreeUtils.getSearchMultiComparator(cmpFactories, lowKey);
         MultiComparator highKeySearchCmp = BTreeUtils.getSearchMultiComparator(cmpFactories, highKey);
-        RangePredicate rangePred = new RangePredicate(lowKey, highKey, true, true, lowKeySearchCmp,
-                highKeySearchCmp);
+        RangePredicate rangePred = new RangePredicate(lowKey, highKey, true, true, lowKeySearchCmp, highKeySearchCmp);
         indexAccessor.search(rangeCursor, rangePred);
         try {
             while (rangeCursor.hasNext()) {
diff --git a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/common/TreeIndexTestUtils.java b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/common/TreeIndexTestUtils.java
index c99299f..47673c9 100644
--- a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/common/TreeIndexTestUtils.java
+++ b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/common/TreeIndexTestUtils.java
@@ -33,9 +33,9 @@
 import edu.uci.ics.hyracks.dataflow.common.comm.io.ArrayTupleReference;
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
 import edu.uci.ics.hyracks.dataflow.common.util.TupleUtils;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
 import edu.uci.ics.hyracks.storage.am.common.api.ISearchPredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexAccessor;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.IndexException;
 import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
@@ -143,12 +143,12 @@
                 LOGGER.info("Ignoring disk-order scan since it's not supported.");
             }
         } catch (ClassCastException e) {
-			// Ignore exception because IIndexAccessor sometimes isn't
-			// an ITreeIndexAccessor, e.g., for the LSMBTree.
-			if (LOGGER.isLoggable(Level.INFO)) {
-				LOGGER.info("Ignoring disk-order scan since it's not supported.");
-			}
-		}
+            // Ignore exception because IIndexAccessor sometimes isn't
+            // an ITreeIndexAccessor, e.g., for the LSMBTree.
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Ignoring disk-order scan since it's not supported.");
+            }
+        }
     }
 
     @SuppressWarnings("unchecked")
@@ -180,7 +180,7 @@
             }
         }
     }
-    
+
     @SuppressWarnings("unchecked")
     public void upsertIntTuples(ITreeIndexTestContext ctx, int numTuples, Random rnd) throws Exception {
         int fieldCount = ctx.getFieldCount();
@@ -243,7 +243,8 @@
         ArrayTupleBuilder tupleBuilder = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
         // Perform bulk load.
-        IIndexBulkLoadContext bulkLoadCtx = ctx.getIndex().beginBulkLoad(0.7f);
+        //        IIndexBulkLoadContext bulkLoadCtx = ctx.getIndex().beginBulkLoad(0.7f);
+        IIndexBulkLoader bulkLoader = ctx.getIndex().createBulkLoader(0.7f);
         int c = 1;
         for (CheckTuple checkTuple : checkTuples) {
             if (LOGGER.isLoggable(Level.INFO)) {
@@ -252,10 +253,12 @@
                 }
             }
             createTupleFromCheckTuple(checkTuple, tupleBuilder, tuple, ctx.getFieldSerdes());
-            ctx.getIndex().bulkLoadAddTuple(tuple, bulkLoadCtx);
+            //            ctx.getIndex().bulkLoadAddTuple(tuple, bulkLoadCtx);
+            bulkLoader.add(tuple);
             c++;
         }
-        ctx.getIndex().endBulkLoad(bulkLoadCtx);
+        //        ctx.getIndex().endBulkLoad(bulkLoadCtx);
+        bulkLoader.end();
     }
 
     @SuppressWarnings("unchecked")
diff --git a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/AbstractRTreeExamplesTest.java b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/AbstractRTreeExamplesTest.java
index 8b1f3c7..0d86b78 100644
--- a/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/AbstractRTreeExamplesTest.java
+++ b/hyracks-test-support/src/main/java/edu/uci/ics/hyracks/storage/am/rtree/AbstractRTreeExamplesTest.java
@@ -34,10 +34,10 @@
 import edu.uci.ics.hyracks.dataflow.common.data.marshalling.IntegerSerializerDeserializer;
 import edu.uci.ics.hyracks.dataflow.common.util.TupleUtils;
 import edu.uci.ics.hyracks.storage.am.common.api.IIndexAccessor;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
 import edu.uci.ics.hyracks.storage.am.common.api.IPrimitiveValueProviderFactory;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexAccessor;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
 import edu.uci.ics.hyracks.storage.am.common.impls.NoOpOperationCallback;
@@ -121,7 +121,8 @@
         }
         ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
-        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE,
+                NoOpOperationCallback.INSTANCE);
         int numInserts = 10000;
         for (int i = 0; i < numInserts; i++) {
             int p1x = rnd.nextInt();
@@ -229,7 +230,8 @@
         }
         ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
-        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE,
+                NoOpOperationCallback.INSTANCE);
         int numInserts = 10000;
         for (int i = 0; i < numInserts; i++) {
             double p1x = rnd.nextDouble();
@@ -325,7 +327,8 @@
 
         ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
-        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE,
+                NoOpOperationCallback.INSTANCE);
 
         int runs = 3;
         for (int run = 0; run < runs; run++) {
@@ -462,7 +465,7 @@
             LOGGER.info("Bulk loading " + numInserts + " tuples");
         }
         long start = System.currentTimeMillis();
-        IIndexBulkLoadContext bulkLoadCtx = treeIndex.beginBulkLoad(0.7f);
+        IIndexBulkLoader bulkLoader = treeIndex.createBulkLoader(0.7f);
         ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
         ArrayTupleReference tuple = new ArrayTupleReference();
 
@@ -476,16 +479,17 @@
 
             TupleUtils.createIntegerTuple(tb, tuple, Math.min(p1x, p2x), Math.min(p1y, p2y), Math.max(p1x, p2x),
                     Math.max(p1y, p2y), pk);
-            treeIndex.bulkLoadAddTuple(tuple, bulkLoadCtx);
+            bulkLoader.add(tuple);
         }
 
-        treeIndex.endBulkLoad(bulkLoadCtx);
+        bulkLoader.end();
         long end = System.currentTimeMillis();
         if (LOGGER.isLoggable(Level.INFO)) {
             LOGGER.info(numInserts + " tuples loaded in " + (end - start) + "ms");
         }
 
-        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE, NoOpOperationCallback.INSTANCE);
+        IIndexAccessor indexAccessor = (IIndexAccessor) treeIndex.createAccessor(NoOpOperationCallback.INSTANCE,
+                NoOpOperationCallback.INSTANCE);
 
         // Build key.
         ArrayTupleBuilder keyTb = new ArrayTupleBuilder(rtreeKeyFieldCount);
diff --git a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeSearchCursorTest.java b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeSearchCursorTest.java
index 46a8520..e283f52 100644
--- a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeSearchCursorTest.java
+++ b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeSearchCursorTest.java
@@ -100,7 +100,7 @@
 
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, 0, metaFrameFactory);
 
-        BTree btree = new BTree(bufferCache, fieldCount, cmpFactories, freePageManager, interiorFrameFactory, leafFrameFactory);
+        BTree btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories, fieldCount);
         btree.create(btreeFileId);
         btree.open(btreeFileId);
 
@@ -173,7 +173,7 @@
 
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, 0, metaFrameFactory);
 
-        BTree btree = new BTree(bufferCache, fieldCount, cmpFactories, freePageManager, interiorFrameFactory, leafFrameFactory);
+        BTree btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories, fieldCount);
         btree.create(btreeFileId);
         btree.open(btreeFileId);
 
@@ -243,7 +243,7 @@
 
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, 0, metaFrameFactory);
 
-        BTree btree = new BTree(bufferCache, fieldCount, cmpFactories, freePageManager, interiorFrameFactory, leafFrameFactory);
+        BTree btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories, fieldCount);
         btree.create(btreeFileId);
         btree.open(btreeFileId);
 
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 5b6dfe0..130302a 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
@@ -87,8 +87,8 @@
 
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, 0, metaFrameFactory);
 
-        BTree btree = new BTree(bufferCache, fieldCount, cmpFactories, freePageManager, interiorFrameFactory,
-                leafFrameFactory);
+        BTree btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories,
+                fieldCount);
         btree.create(fileId);
         btree.open(fileId);
 
diff --git a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeUpdateSearchTest.java b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeUpdateSearchTest.java
index 0a1c193..15b72f8 100644
--- a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeUpdateSearchTest.java
+++ b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeUpdateSearchTest.java
@@ -65,8 +65,8 @@
         IBTreeLeafFrame leafFrame = (IBTreeLeafFrame) leafFrameFactory.createFrame();
 
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, 0, metaFrameFactory);
-        BTree btree = new BTree(bufferCache, fieldCount, cmpFactories, freePageManager, interiorFrameFactory,
-                leafFrameFactory);
+        BTree btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories,
+                fieldCount);
         btree.create(btreeFileId);
         btree.open(btreeFileId);
 
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 9962ef4..ec7c76d 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
@@ -157,8 +157,8 @@
 
         freePageManager = new LinkedListFreePageManager(bufferCache, 0, metaFrameFactory);
 
-        btree = new BTree(bufferCache, btreeTypeTraits.length, btreeCmpFactories, freePageManager,
-                interiorFrameFactory, leafFrameFactory);
+        btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory,
+                btreeCmpFactories, btreeTypeTraits.length);
         btree.create(btreeFileId);
         btree.open(btreeFileId);
 
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 4c78c2b..b81a814 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
@@ -51,7 +51,7 @@
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTreeRangeSearchCursor;
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangePredicate;
 import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexAccessor;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
@@ -123,8 +123,8 @@
 
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, 0, metaFrameFactory);
 
-        BTree btree = new BTree(bufferCache, btreeTypeTraits.length, cmpFactories, freePageManager,
-                interiorFrameFactory, leafFrameFactory);
+        BTree btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories,
+                btreeTypeTraits.length);
         btree.create(btreeFileId);
         btree.open(btreeFileId);
 
@@ -176,7 +176,7 @@
         int addProb = 0;
         int addProbStep = 10;
 
-        IIndexBulkLoadContext ctx = invIndex.beginBulkLoad(BTree.DEFAULT_FILL_FACTOR);
+        IIndexBulkLoader bulkLoader = invIndex.createBulkLoader(BTree.DEFAULT_FILL_FACTOR);
 
         for (int i = 0; i < tokens.size(); i++) {
 
@@ -198,14 +198,14 @@
                     tuple.reset(accessor, 0);
 
                     try {
-                        invIndex.bulkLoadAddTuple(tuple, ctx);
+                        bulkLoader.add(tuple);
                     } catch (Exception e) {
                         e.printStackTrace();
                     }
                 }
             }
         }
-        invIndex.endBulkLoad(ctx);
+        bulkLoader.end();
 
         // ------- START VERIFICATION -----------
 
diff --git a/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/SearchPerfTest.java b/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/SearchPerfTest.java
index 11ae4a6..b2642d9 100644
--- a/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/SearchPerfTest.java
+++ b/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/SearchPerfTest.java
@@ -28,8 +28,8 @@
 import edu.uci.ics.hyracks.dataflow.common.data.marshalling.IntegerSerializerDeserializer;
 import edu.uci.ics.hyracks.dataflow.common.data.marshalling.UTF8StringSerializerDeserializer;
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTree;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
-import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
+import edu.uci.ics.hyracks.storage.am.common.api.IndexException;
 import edu.uci.ics.hyracks.storage.am.common.impls.NoOpOperationCallback;
 import edu.uci.ics.hyracks.storage.am.invertedindex.api.IInvertedIndexSearchModifier;
 import edu.uci.ics.hyracks.storage.am.invertedindex.impls.InvertedIndex.InvertedIndexAccessor;
@@ -66,7 +66,7 @@
         loadData();
     }
 
-    public void loadData() throws HyracksDataException, TreeIndexException {
+    public void loadData() throws HyracksDataException, IndexException {
         tokens.add("compilers");
         tokens.add("computer");
         tokens.add("databases");
@@ -85,7 +85,7 @@
         int addProb = 0;
         int addProbStep = 10;
 
-        IIndexBulkLoadContext ctx = invIndex.beginBulkLoad(BTree.DEFAULT_FILL_FACTOR);
+        IIndexBulkLoader bulkLoader = invIndex.createBulkLoader(BTree.DEFAULT_FILL_FACTOR);
 
         for (int i = 0; i < tokens.size(); i++) {
 
@@ -100,14 +100,14 @@
                     tuple.reset(tb.getFieldEndOffsets(), tb.getByteArray());
                     checkInvLists.get(i).add(j);
                     try {
-                        invIndex.bulkLoadAddTuple(tuple, ctx);
+                        bulkLoader.add(tuple);
                     } catch (Exception e) {
                         e.printStackTrace();
                     }
                 }
             }
         }
-        invIndex.endBulkLoad(ctx);
+        bulkLoader.end();
     }
 
     /**
diff --git a/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/SearchTest.java b/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/SearchTest.java
index 933e848..9999e95 100644
--- a/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/SearchTest.java
+++ b/hyracks-tests/hyracks-storage-am-invertedindex-test/src/test/java/edu/uci/ics/hyracks/storage/am/invertedindex/SearchTest.java
@@ -31,8 +31,8 @@
 import edu.uci.ics.hyracks.dataflow.common.data.marshalling.IntegerSerializerDeserializer;
 import edu.uci.ics.hyracks.dataflow.common.data.marshalling.UTF8StringSerializerDeserializer;
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTree;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
-import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
+import edu.uci.ics.hyracks.storage.am.common.api.IndexException;
 import edu.uci.ics.hyracks.storage.am.common.impls.NoOpOperationCallback;
 import edu.uci.ics.hyracks.storage.am.invertedindex.api.IInvertedIndexSearchModifier;
 import edu.uci.ics.hyracks.storage.am.invertedindex.impls.InvertedIndex.InvertedIndexAccessor;
@@ -133,7 +133,7 @@
         }
     }
 
-    public void loadData() throws IOException, TreeIndexException {
+    public void loadData() throws IOException, IndexException {
         List<TokenIdPair> pairs = new ArrayList<TokenIdPair>();
         // generate pairs for subsequent sorting and bulk-loading
         int id = 0;
@@ -152,7 +152,7 @@
         Collections.sort(pairs);
 
         // bulk load index
-        IIndexBulkLoadContext ctx = invIndex.beginBulkLoad(BTree.DEFAULT_FILL_FACTOR);
+        IIndexBulkLoader bulkLoader = invIndex.createBulkLoader(BTree.DEFAULT_FILL_FACTOR);
 
         for (TokenIdPair t : pairs) {
             tb.reset();
@@ -162,12 +162,12 @@
             tuple.reset(tb.getFieldEndOffsets(), tb.getByteArray());
 
             try {
-                invIndex.bulkLoadAddTuple(tuple, ctx);
+                bulkLoader.add(tuple);
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
-        invIndex.endBulkLoad(ctx);
+        bulkLoader.end();
     }
 
     /**
diff --git a/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/lsm/btree/perf/BTreeBulkLoadRunner.java b/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/lsm/btree/perf/BTreeBulkLoadRunner.java
index f568651..764faa5 100644
--- a/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/lsm/btree/perf/BTreeBulkLoadRunner.java
+++ b/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/lsm/btree/perf/BTreeBulkLoadRunner.java
@@ -19,16 +19,16 @@
 import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.storage.am.btree.exceptions.BTreeException;
-import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoader;
 import edu.uci.ics.hyracks.storage.am.common.datagen.DataGenThread;
 import edu.uci.ics.hyracks.storage.am.common.datagen.TupleBatch;
 
 public class BTreeBulkLoadRunner extends BTreeRunner {
 
     protected final float fillFactor;
-    
-    public BTreeBulkLoadRunner(int numBatches, int pageSize, int numPages, ITypeTraits[] typeTraits, IBinaryComparatorFactory[] cmpFactories, float fillFactor)
-            throws HyracksDataException, BTreeException {
+
+    public BTreeBulkLoadRunner(int numBatches, int pageSize, int numPages, ITypeTraits[] typeTraits,
+            IBinaryComparatorFactory[] cmpFactories, float fillFactor) throws HyracksDataException, BTreeException {
         super(numBatches, pageSize, numPages, typeTraits, cmpFactories);
         this.fillFactor = fillFactor;
     }
@@ -37,14 +37,14 @@
     public long runExperiment(DataGenThread dataGen, int numThreads) throws Exception {
         btree.create(btreeFileId);
         long start = System.currentTimeMillis();
-        IIndexBulkLoadContext bulkLoadCtx = btree.beginBulkLoad(1.0f);
+        IIndexBulkLoader bulkLoader = btree.createBulkLoader(1.0f);
         for (int i = 0; i < numBatches; i++) {
             TupleBatch batch = dataGen.tupleBatchQueue.take();
             for (int j = 0; j < batch.size(); j++) {
-                btree.bulkLoadAddTuple(batch.get(j), bulkLoadCtx);    
+                bulkLoader.add(batch.get(j));
             }
         }
-        btree.endBulkLoad(bulkLoadCtx);
+        bulkLoader.end();
         long end = System.currentTimeMillis();
         long time = end - start;
         return time;
diff --git a/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/lsm/btree/perf/InMemoryBTreeRunner.java b/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/lsm/btree/perf/InMemoryBTreeRunner.java
index b7f5a7d..9ae149c 100644
--- a/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/lsm/btree/perf/InMemoryBTreeRunner.java
+++ b/hyracks-tests/hyracks-storage-am-lsm-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/lsm/btree/perf/InMemoryBTreeRunner.java
@@ -71,8 +71,8 @@
         ITreeIndexFrameFactory interiorFrameFactory = new BTreeNSMInteriorFrameFactory(tupleWriterFactory);
         ITreeIndexMetaDataFrameFactory metaFrameFactory = new LIFOMetaDataFrameFactory();
         IFreePageManager freePageManager = new InMemoryFreePageManager(bufferCache.getNumPages(), metaFrameFactory);
-        btree = new BTree(bufferCache, typeTraits.length, cmpFactories, freePageManager, interiorFrameFactory,
-                leafFrameFactory);
+        btree = new BTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories,
+                typeTraits.length);
     }
 
     @Override
diff --git a/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeSearchCursorTest.java b/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeSearchCursorTest.java
index 7d18999..7f73e33 100644
--- a/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeSearchCursorTest.java
+++ b/hyracks-tests/hyracks-storage-am-rtree-test/src/test/java/edu/uci/ics/hyracks/storage/am/rtree/RTreeSearchCursorTest.java
@@ -117,8 +117,8 @@
         IRTreeLeafFrame leafFrame = (IRTreeLeafFrame) leafFrameFactory.createFrame();
         IFreePageManager freePageManager = new LinkedListFreePageManager(bufferCache, 0, metaFrameFactory);
 
-        RTree rtree = new RTree(bufferCache, fieldCount, cmpFactories, freePageManager, interiorFrameFactory,
-                leafFrameFactory);
+        RTree rtree = new RTree(bufferCache, freePageManager, interiorFrameFactory, leafFrameFactory, cmpFactories,
+                fieldCount);
         rtree.create(rtreeFileId);
         rtree.open(rtreeFileId);