Merged hyracks_dev_next -r 1287 into trunk

git-svn-id: https://hyracks.googlecode.com/svn/trunk@1288 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks/hyracks-storage-am-common/.classpath b/hyracks/hyracks-storage-am-common/.classpath
deleted file mode 100644
index 1f3c1ff..0000000
--- a/hyracks/hyracks-storage-am-common/.classpath
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
-	<classpathentry kind="output" path="target/classes"/>
-</classpath>
diff --git a/hyracks/hyracks-storage-am-common/.project b/hyracks/hyracks-storage-am-common/.project
deleted file mode 100644
index ec47f6b..0000000
--- a/hyracks/hyracks-storage-am-common/.project
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>hyracks-storage-am-common</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.maven.ide.eclipse.maven2Builder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-		<nature>org.maven.ide.eclipse.maven2Nature</nature>
-	</natures>
-</projectDescription>
diff --git a/hyracks/hyracks-storage-am-common/.settings/org.eclipse.jdt.core.prefs b/hyracks/hyracks-storage-am-common/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index b37b3bb..0000000
--- a/hyracks/hyracks-storage-am-common/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,6 +0,0 @@
-#Thu Jul 07 12:23:56 PDT 2011
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.source=1.6
diff --git a/hyracks/hyracks-storage-am-common/.settings/org.maven.ide.eclipse.prefs b/hyracks/hyracks-storage-am-common/.settings/org.maven.ide.eclipse.prefs
deleted file mode 100644
index 7b5e618..0000000
--- a/hyracks/hyracks-storage-am-common/.settings/org.maven.ide.eclipse.prefs
+++ /dev/null
@@ -1,8 +0,0 @@
-#Thu Jul 07 12:23:53 PDT 2011
-activeProfiles=
-eclipse.preferences.version=1
-fullBuildGoals=process-test-resources
-resolveWorkspaceProjects=true
-resourceFilterGoals=process-resources resources\:testResources
-skipCompilerPlugin=true
-version=1
diff --git a/hyracks/hyracks-storage-am-common/pom.xml b/hyracks/hyracks-storage-am-common/pom.xml
index eac7bc3..9f0e53a 100644
--- a/hyracks/hyracks-storage-am-common/pom.xml
+++ b/hyracks/hyracks-storage-am-common/pom.xml
@@ -2,12 +2,12 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>edu.uci.ics.hyracks</groupId>
   <artifactId>hyracks-storage-am-common</artifactId>
-  <version>0.1.9-SNAPSHOT</version>
+  <version>0.2.0-SNAPSHOT</version>
 
   <parent>
     <groupId>edu.uci.ics.hyracks</groupId>
     <artifactId>hyracks</artifactId>
-    <version>0.1.9-SNAPSHOT</version>
+    <version>0.2.0-SNAPSHOT</version>
   </parent>
 
   <build>
@@ -27,28 +27,28 @@
   	<dependency>
   		<groupId>edu.uci.ics.hyracks</groupId>
   		<artifactId>hyracks-api</artifactId>
-  		<version>0.1.9-SNAPSHOT</version>
+  		<version>0.2.0-SNAPSHOT</version>
   		<type>jar</type>
   		<scope>compile</scope>
   	</dependency>
   	<dependency>
   		<groupId>edu.uci.ics.hyracks</groupId>
   		<artifactId>hyracks-storage-common</artifactId>
-  		<version>0.1.9-SNAPSHOT</version>
+  		<version>0.2.0-SNAPSHOT</version>
   		<type>jar</type>
   		<scope>compile</scope>
   	</dependency>
   	<dependency>
   		<groupId>edu.uci.ics.hyracks</groupId>
   		<artifactId>hyracks-dataflow-common</artifactId>
-  		<version>0.1.9-SNAPSHOT</version>
+  		<version>0.2.0-SNAPSHOT</version>
   		<type>jar</type>
   		<scope>compile</scope>
   	</dependency>
   	<dependency>
   		<groupId>edu.uci.ics.hyracks</groupId>
   		<artifactId>hyracks-dataflow-std</artifactId>
-  		<version>0.1.9-SNAPSHOT</version>
+  		<version>0.2.0-SNAPSHOT</version>
   		<type>jar</type>
   		<scope>compile</scope>
   	</dependency>  
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ICursorInitialState.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ICursorInitialState.java
index 5f7c88d..60e8ba9 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ICursorInitialState.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ICursorInitialState.java
@@ -18,7 +18,6 @@
 import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
 
 public interface ICursorInitialState {
-    public ICachedPage getPage();
-
-    public void setPage(ICachedPage page);
+	public ICachedPage getPage();
+	public void setPage(ICachedPage page);
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IFreePageManager.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IFreePageManager.java
index 7abc0e3..a7901c8 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IFreePageManager.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IFreePageManager.java
@@ -3,23 +3,27 @@
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 
 public interface IFreePageManager {
-    public int getFreePage(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException;
+	public int getFreePage(ITreeIndexMetaDataFrame metaFrame)
+			throws HyracksDataException, PageAllocationException;
 
-    public void addFreePage(ITreeIndexMetaDataFrame metaFrame, int freePage) throws HyracksDataException;
+	public void addFreePage(ITreeIndexMetaDataFrame metaFrame, int freePage)
+			throws HyracksDataException;
 
-    public int getMaxPage(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException;
+	public int getMaxPage(ITreeIndexMetaDataFrame metaFrame)
+			throws HyracksDataException;
 
-    public void init(ITreeIndexMetaDataFrame metaFrame, int currentMaxPage) throws HyracksDataException;
+	public void init(ITreeIndexMetaDataFrame metaFrame, int currentMaxPage)
+			throws HyracksDataException;
 
-    public ITreeIndexMetaDataFrameFactory getMetaDataFrameFactory();
+	public ITreeIndexMetaDataFrameFactory getMetaDataFrameFactory();
 
-    // required to return negative values
-    public byte getMetaPageLevelIndicator();
+	// required to return negative values
+	public byte getMetaPageLevelIndicator();
 
-    public byte getFreePageLevelIndicator();
+	public byte getFreePageLevelIndicator();
 
-    // determined by examining level indicator
-    public boolean isMetaPage(ITreeIndexMetaDataFrame metaFrame);
+	// determined by examining level indicator
+	public boolean isMetaPage(ITreeIndexMetaDataFrame metaFrame);
 
-    public boolean isFreePage(ITreeIndexMetaDataFrame metaFrame);
+	public boolean isFreePage(ITreeIndexMetaDataFrame metaFrame);
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexOpContext.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexOpContext.java
new file mode 100644
index 0000000..7153f78
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexOpContext.java
@@ -0,0 +1,8 @@
+package edu.uci.ics.hyracks.storage.am.common.api;
+
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
+
+public interface IIndexOpContext {
+	void reset();
+	void reset(IndexOp newOp);
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProvider.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProvider.java
index ee2f9f7..4696e68 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProvider.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProvider.java
@@ -16,5 +16,5 @@
 package edu.uci.ics.hyracks.storage.am.common.api;
 
 public interface IPrimitiveValueProvider {
-    public double getValue(byte[] bytes, int offset);
+	public double getValue(byte[] bytes, int offset);
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProviderFactory.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProviderFactory.java
index 3953d63..8e45d0c 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProviderFactory.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProviderFactory.java
@@ -18,5 +18,5 @@
 import java.io.Serializable;
 
 public interface IPrimitiveValueProviderFactory extends Serializable {
-    public IPrimitiveValueProvider createPrimitiveValueProvider();
+	public IPrimitiveValueProvider createPrimitiveValueProvider();
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISearchPredicate.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISearchPredicate.java
index f4836e0..a96db28 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISearchPredicate.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISearchPredicate.java
@@ -20,7 +20,7 @@
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
 
 public interface ISearchPredicate extends Serializable {
-    public MultiComparator getLowKeyComparator();
+	public MultiComparator getLowKeyComparator();
 
-    public MultiComparator getHighKeyComparator();
+	public MultiComparator getHighKeyComparator();
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISlotManager.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISlotManager.java
index 29646e7..2619493 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISlotManager.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISlotManager.java
@@ -21,22 +21,27 @@
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
 
 public interface ISlotManager {
-    public void setFrame(ITreeIndexFrame frame);
+	public int findTupleIndex(ITupleReference searchKey,
+			ITreeIndexTupleReference frameTuple, MultiComparator multiCmp,
+			FindTupleMode mode, FindTupleNoExactMatchPolicy matchPolicy);
 
-    public int findTupleIndex(ITupleReference searchKey, ITreeIndexTupleReference frameTuple, MultiComparator multiCmp,
-            FindTupleMode mode, FindTupleNoExactMatchPolicy matchPolicy);
+	public int getGreatestKeyIndicator();
+	
+	public int getErrorIndicator();
 
-    public int insertSlot(int tupleIndex, int tupleOff);
+	public void setFrame(ITreeIndexFrame frame);
+	
+	public int insertSlot(int tupleIndex, int tupleOff);
 
-    public int getSlotStartOff();
+	public int getSlotStartOff();
 
-    public int getSlotEndOff();
+	public int getSlotEndOff();
 
-    public int getTupleOff(int slotOff);
+	public int getTupleOff(int slotOff);
 
-    public void setSlot(int slotOff, int value);
+	public void setSlot(int slotOff, int value);
 
-    public int getSlotOff(int tupleIndex);
+	public int getSlotOff(int tupleIndex);
 
-    public int getSlotSize();
+	public int getSlotSize();
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISplitKey.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISplitKey.java
index 246c09d..3a1c8a1 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISplitKey.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISplitKey.java
@@ -3,23 +3,23 @@
 import java.nio.ByteBuffer;
 
 public interface ISplitKey {
-    public void initData(int keySize);
+	public void initData(int keySize);
 
-    public void reset();
+	public void reset();
 
-    public ByteBuffer getBuffer();
+	public ByteBuffer getBuffer();
 
-    public ITreeIndexTupleReference getTuple();
+	public ITreeIndexTupleReference getTuple();
 
-    public int getLeftPage();
+	public int getLeftPage();
 
-    public int getRightPage();
+	public int getRightPage();
 
-    public void setLeftPage(int leftPage);
+	public void setLeftPage(int leftPage);
 
-    public void setRightPage(int rightPage);
+	public void setRightPage(int rightPage);
 
-    public void setPages(int leftPage, int rightPage);
+	public void setPages(int leftPage, int rightPage);
 
-    public ISplitKey duplicate(ITreeIndexTupleReference copyTuple);
+	public ISplitKey duplicate(ITreeIndexTupleReference copyTuple);
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java
index 2d77f06..46d22d1 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java
@@ -1,52 +1,113 @@
+/*
+ * 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.common.api;
 
 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.ophelpers.IndexOp;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOpContext;
+import edu.uci.ics.hyracks.storage.am.common.dataflow.IIndex;
 
-public interface ITreeIndex {
-    // init:
+/**
+ * Interface describing the operations of tree-based index structures. Indexes
+ * implementing this interface can easily reuse the tree index operators for
+ * dataflow. We assume that indexes store tuples with a fixed number of fields.
+ * Users must perform operations on an ITreeIndex via an ITreeIndexAccessor.
+ */
+public interface ITreeIndex extends IIndex {
 
-    public void create(int indexFileId, ITreeIndexFrame leafFrame, ITreeIndexMetaDataFrame metaFrame) throws Exception;
+	/**
+	 * Creates an index accessor for performing operations on this index.
+	 * (insert/delete/update/search/diskorderscan). An ITreeIndexAccessor is not
+	 * thread safe, but different ITreeIndexAccessors can concurrently operate
+	 * on the same ITreeIndex
+	 * 
+	 * @returns ITreeIndexAccessor A tree index accessor for this tree.
+	 */
+	public ITreeIndexAccessor createAccessor();
 
-    public void open(int indexFileId);
+	/**
+	 * Prepares the index for bulk loading, returning a bulk load context. The
+	 * index must be empty for bulk loading to be possible.
+	 * 
+	 * @param fillFactor
+	 *            Desired fill factor in [0, 1.0].
+	 * @throws HyracksDataException
+	 *             If the BufferCache throws while un/pinning or un/latching.
+	 * @throws TreeIndexException
+	 *             If the tree is not empty.
+	 * @throws PageAllocationException
+	 * @returns A new context for bulk loading, required for appending tuples.
+	 */
+	public IIndexBulkLoadContext beginBulkLoad(float fillFactor)
+			throws TreeIndexException, HyracksDataException,
+			PageAllocationException;
 
-    // operations:
+	/**
+	 * 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.
+	 * @throws PageAllocationException
+	 */
+	public void bulkLoadAddTuple(ITupleReference tuple,
+			IIndexBulkLoadContext ictx) throws HyracksDataException,
+			PageAllocationException;
 
-    public void insert(ITupleReference tuple, IndexOpContext ictx) throws Exception;
+	/**
+	 * 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.
+	 * @throws PageAllocationException
+	 */
+	public void endBulkLoad(IIndexBulkLoadContext ictx)
+			throws HyracksDataException, PageAllocationException;
 
-    public void update(ITupleReference tuple, IndexOpContext ictx) throws Exception;
+	/**
+	 * @return The index's leaf frame factory.
+	 */
+	public ITreeIndexFrameFactory getLeafFrameFactory();
 
-    public void delete(ITupleReference tuple, IndexOpContext ictx) throws Exception;
+	/**
+	 * @return The index's interior frame factory.
+	 */
+	public ITreeIndexFrameFactory getInteriorFrameFactory();
 
-    public IndexOpContext createOpContext(IndexOp op, ITreeIndexFrame leafFrame, ITreeIndexFrame interiorFrame,
-            ITreeIndexMetaDataFrame metaFrame);
+	/**
+	 * @return The index's free page manager.
+	 */
+	public IFreePageManager getFreePageManager();
 
-    // bulk loading:
+	/**
+	 * @return The number of fields tuples of this index have.
+	 */
+	public int getFieldCount();
 
-    public IIndexBulkLoadContext beginBulkLoad(float fillFactor, ITreeIndexFrame leafFrame,
-            ITreeIndexFrame interiorFrame, ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException;
+	/**
+	 * @return The current root page id of this index.
+	 */
+	public int getRootPageId();
 
-    public void bulkLoadAddTuple(IIndexBulkLoadContext ictx, ITupleReference tuple) throws HyracksDataException;
-
-    public void endBulkLoad(IIndexBulkLoadContext ictx) throws HyracksDataException;
-
-    // search:
-    public void diskOrderScan(ITreeIndexCursor icursor, ITreeIndexFrame leafFrame, ITreeIndexMetaDataFrame metaFrame,
-            IndexOpContext ictx) throws HyracksDataException;
-
-    // utility:
-
-    public IFreePageManager getFreePageManager();
-
-    public int getRootPageId();
-
-    public ITreeIndexFrameFactory getLeafFrameFactory();
-
-    public ITreeIndexFrameFactory getInteriorFrameFactory();
-
-    public int getFieldCount();
-
-    public IndexType getIndexType();
+	/**
+	 * @return An enum of the concrete type of this index.
+	 */
+	public IndexType getIndexType();
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexAccessor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexAccessor.java
new file mode 100644
index 0000000..1e679b2
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexAccessor.java
@@ -0,0 +1,101 @@
+/*
+ * 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.common.api;
+
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+
+/**
+ * Client handle for performing operations
+ * (insert/delete/update/search/diskorderscan) on an ITreeIndex. An
+ * ITreeIndexAccessor is not thread safe, but different ITreeIndexAccessors can
+ * concurrently operate on the same ITreeIndex (i.e., the ITreeIndex must allow
+ * concurrent operations).
+ */
+public interface ITreeIndexAccessor {
+	/**
+	 * Inserts the given tuple.
+	 * 
+	 * @param tuple
+	 *            Tuple to be inserted.
+	 * @throws HyracksDataException
+	 *             If the BufferCache throws while un/pinning or un/latching.
+	 * @throws TreeIndexException
+	 *             If an index-specific constraint is violated, e.g., the key
+	 *             already exists.
+	 * @throws PageAllocationException
+	 */
+	public void insert(ITupleReference tuple) throws HyracksDataException,
+			TreeIndexException, PageAllocationException;
+
+	/**
+	 * Updates the tuple in the index matching the given tuple with the new
+	 * contents in the given tuple.
+	 * 
+	 * @param tuple
+	 *            Tuple whose match in the index is to be update with the given
+	 *            tuples contents.
+	 * @throws HyracksDataException
+	 *             If the BufferCache throws while un/pinning or un/latching.
+	 * @throws TreeIndexException
+	 *             If there is no matching tuple in the index.
+	 * @throws PageAllocationException
+	 */
+	public void update(ITupleReference tuple) throws HyracksDataException,
+			TreeIndexException, PageAllocationException;
+
+	/**
+	 * Deletes the tuple in the index matching the given tuple.
+	 * 
+	 * @param tuple
+	 *            Tuple to be deleted.
+	 * @throws HyracksDataException
+	 *             If the BufferCache throws while un/pinning or un/latching.
+	 * @throws TreeIndexException
+	 *             If there is no matching tuple in the index.
+	 * @throws PageAllocationException
+	 */
+	public void delete(ITupleReference tuple) throws HyracksDataException,
+			TreeIndexException, PageAllocationException;
+
+	/**
+	 * Open the given cursor for an index search using the given predicate as
+	 * search condition.
+	 * 
+	 * @param icursor
+	 *            Cursor over the index entries satisfying searchPred.
+	 * @param searchPred
+	 *            Search condition.
+	 * @throws HyracksDataException
+	 *             If the BufferCache throws while un/pinning or un/latching.
+	 * @throws TreeIndexException
+	 * @throws PageAllocationException
+	 */
+	public void search(ITreeIndexCursor cursor, ISearchPredicate searchPred)
+			throws HyracksDataException, TreeIndexException, PageAllocationException;
+
+	/**
+	 * Open the given cursor for a disk-order scan, positioning the cursor to
+	 * the first leaf tuple.
+	 * 
+	 * @param icursor
+	 *            Cursor to be opened for disk-order scanning.
+	 * @throws HyracksDataException
+	 *             If the BufferCache throws while un/pinning or un/latching.
+	 */
+	public void diskOrderScan(ITreeIndexCursor cursor)
+			throws HyracksDataException;
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexCursor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexCursor.java
index 22b2b6f..d3ce3867 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexCursor.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexCursor.java
@@ -15,26 +15,31 @@
 
 package edu.uci.ics.hyracks.storage.am.common.api;
 
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
 
 public interface ITreeIndexCursor {
-    public void reset();
+	public void reset();
 
-    public boolean hasNext() throws Exception;
+	public boolean hasNext() throws Exception;
 
-    public void next() throws Exception;
+	public void next() throws Exception;
 
-    public void open(ICursorInitialState initialState, ISearchPredicate searchPred) throws Exception;
+	public void open(ICursorInitialState initialState,
+			ISearchPredicate searchPred) throws HyracksDataException;
 
-    public ICachedPage getPage();
+	public ICachedPage getPage();
 
-    public void close() throws Exception;
+	public void close() throws Exception;
 
-    public void setBufferCache(IBufferCache bufferCache);
+	public void setBufferCache(IBufferCache bufferCache);
 
-    public void setFileId(int fileId);
+	public void setFileId(int fileId);
 
-    public ITupleReference getTuple();
+	public ITupleReference getTuple();
+	
+	// For allowing updates.
+	public boolean exclusiveLatchNodes();
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrame.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrame.java
index 246efe4..c33a8d8 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrame.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrame.java
@@ -17,58 +17,51 @@
 
 import java.nio.ByteBuffer;
 
-import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
 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.frames.FrameOpSpaceStatus;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
 import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
 
 public interface ITreeIndexFrame {
-    public void setPage(ICachedPage page);
 
-    public ICachedPage getPage();
-
-    public ByteBuffer getBuffer();
-
-    public int findTupleIndex(ITupleReference tuple, MultiComparator cmp) throws Exception;
-
-    public void insert(ITupleReference tuple, MultiComparator cmp, int tupleIndex) throws Exception;
-
-    public void update(int rid, ITupleReference tuple) throws Exception;
-
-    public void delete(ITupleReference tuple, MultiComparator cmp, boolean exactDelete) throws Exception;
+	public void initBuffer(byte level);
+	
+    public FrameOpSpaceStatus hasSpaceInsert(ITupleReference tuple);
+	
+	public void insert(ITupleReference tuple, int tupleIndex);    
+    
+	public FrameOpSpaceStatus hasSpaceUpdate(ITupleReference newTuple, int oldTupleIndex);
+	
+	public void update(ITupleReference newTuple, int oldTupleIndex, boolean inPlace);    
+    
+    public void delete(ITupleReference tuple, int tupleIndex);
 
     // returns true if slots were modified, false otherwise
-    public boolean compact(MultiComparator cmp);
+    public boolean compact();
 
-    public boolean compress(MultiComparator cmp) throws HyracksDataException;
-
-    public void initBuffer(byte level);
+    // returns true if compressed.
+    public boolean compress() throws HyracksDataException;
 
     public int getTupleCount();
 
-    // assumption: page must be write-latched at this point
-    public FrameOpSpaceStatus hasSpaceInsert(ITupleReference tuple, MultiComparator cmp);
-
-    public FrameOpSpaceStatus hasSpaceUpdate(int rid, ITupleReference tuple, MultiComparator cmp);
-
     public int getTupleOffset(int slotNum);
 
     public int getTotalFreeSpace();
 
-    public void setPageLsn(int pageLsn);
+    public void setPageLsn(long pageLsn);
 
-    public int getPageLsn();
+    public long getPageLsn();
 
+    public void setPage(ICachedPage page);
+
+    public ICachedPage getPage();
+
+    public ByteBuffer getBuffer();
+    
     // for debugging
-    public void printHeader();
+    public String printHeader();
 
-    public String printKeys(MultiComparator cmp, ISerializerDeserializer[] fields) throws HyracksDataException;
-
-    // TODO; what if tuples more than half-page size?
-    public int split(ITreeIndexFrame rightFrame, ITupleReference tuple, MultiComparator cmp, ISplitKey splitKey)
-            throws Exception;
+    public void split(ITreeIndexFrame rightFrame, ITupleReference tuple, ISplitKey splitKey) throws TreeIndexException;
 
     public ISlotManager getSlotManager();
 
@@ -84,15 +77,8 @@
 
     public void setLevel(byte level);
 
-    public boolean getSmFlag(); // structure modification flag
-
-    public void setSmFlag(boolean smFlag);
-
     public int getSlotSize();
 
-    // TODO: should be removed after new tuple format
-    public void setPageTupleFieldCount(int fieldCount);
-
     // for debugging
     public int getFreeSpaceOff();
 
@@ -101,4 +87,6 @@
     public ITreeIndexTupleWriter getTupleWriter();
 
     public int getPageHeaderSize();
+    
+    public ITreeIndexTupleReference createTupleReference();
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrameCompressor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrameCompressor.java
new file mode 100644
index 0000000..75ee598
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrameCompressor.java
@@ -0,0 +1,22 @@
+/*
+ * 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.common.api;
+
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
+
+public interface ITreeIndexFrameCompressor {
+    public boolean compress(ITreeIndexFrame frame, MultiComparator cmp) throws Exception;
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrame.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrame.java
index bbd03d6..17519ae 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrame.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrame.java
@@ -18,27 +18,27 @@
 import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
 
 public interface ITreeIndexMetaDataFrame {
-    public void initBuffer(int level);
+	public void initBuffer(byte level);
 
-    public void setPage(ICachedPage page);
+	public void setPage(ICachedPage page);
 
-    public ICachedPage getPage();
+	public ICachedPage getPage();
 
-    public byte getLevel();
+	public byte getLevel();
 
-    public void setLevel(byte level);
+	public void setLevel(byte level);
 
-    public int getNextPage();
+	public int getNextPage();
 
-    public void setNextPage(int nextPage);
+	public void setNextPage(int nextPage);
 
-    public int getMaxPage();
+	public int getMaxPage();
 
-    public void setMaxPage(int maxPage);
+	public void setMaxPage(int maxPage);
 
-    public int getFreePage();
+	public int getFreePage();
 
-    public boolean hasSpace();
+	public boolean hasSpace();
 
-    public void addFreePage(int freePage);
+	public void addFreePage(int freePage);
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrameFactory.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrameFactory.java
index 6fd88e8..d5625b4 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrameFactory.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrameFactory.java
@@ -16,5 +16,5 @@
 package edu.uci.ics.hyracks.storage.am.common.api;
 
 public interface ITreeIndexMetaDataFrameFactory {
-    public ITreeIndexMetaDataFrame createFrame();
+	public ITreeIndexMetaDataFrame createFrame();
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleReference.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleReference.java
index d2c2df4..b989dd9 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleReference.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleReference.java
@@ -27,4 +27,6 @@
     public void resetByTupleOffset(ByteBuffer buf, int tupleStartOffset);
 
     public void resetByTupleIndex(ITreeIndexFrame frame, int tupleIndex);
+    
+    public int getTupleSize();
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleWriterFactory.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleWriterFactory.java
index bd7bfda..ea5e740 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleWriterFactory.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleWriterFactory.java
@@ -18,5 +18,5 @@
 import java.io.Serializable;
 
 public interface ITreeIndexTupleWriterFactory extends Serializable {
-    public ITreeIndexTupleWriter createTupleWriter();
+	public ITreeIndexTupleWriter createTupleWriter();
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleUpdater.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleUpdater.java
new file mode 100644
index 0000000..e201cc3
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleUpdater.java
@@ -0,0 +1,29 @@
+/*
+ * 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.common.api;
+
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+
+/**
+ * Interface for updating a tuple. Warning: By convention, this interface
+ * assumes that the modifications do not change the size of the tuple, and that
+ * it does not change keys (e.g., BTree keys). This interface is used to
+ * implement update scans.
+ * 
+ */
+public interface ITupleUpdater {
+	public void updateTuple(ITupleReference tuple);
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleUpdaterFactory.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleUpdaterFactory.java
new file mode 100644
index 0000000..ee20b6c
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleUpdaterFactory.java
@@ -0,0 +1,22 @@
+/*
+ * 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.common.api;
+
+import java.io.Serializable;
+
+public interface ITupleUpdaterFactory extends Serializable {
+	public ITupleUpdater createTupleUpdater();
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IndexType.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IndexType.java
index d5f9f44..6f83e0b 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IndexType.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IndexType.java
@@ -1,5 +1,5 @@
 package edu.uci.ics.hyracks.storage.am.common.api;
 
 public enum IndexType {
-    BTREE, RTREE, INVERTED
+	BTREE, RTREE, INVERTED
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/PageAllocationException.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/PageAllocationException.java
new file mode 100644
index 0000000..e6eec66
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/PageAllocationException.java
@@ -0,0 +1,29 @@
+/*
+ * 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.common.api;
+
+public class PageAllocationException extends Exception {
+
+	private static final long serialVersionUID = 1L;
+
+	public PageAllocationException(Throwable cause) {
+        super(cause);
+    }
+    
+    public PageAllocationException(String message) {
+        super(message);
+    }
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/TreeIndexException.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/TreeIndexException.java
index ad3db58..4cf596f 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/TreeIndexException.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/TreeIndexException.java
@@ -17,22 +17,22 @@
 
 public class TreeIndexException extends Exception {
 
-    private static final long serialVersionUID = 1L;
-    private boolean handled = false;
+	private static final long serialVersionUID = 1L;
+	private boolean handled = false;
 
-    public TreeIndexException(Exception e) {
-        super(e);
-    }
+	public TreeIndexException(Exception e) {		
+		super(e);
+	}
 
-    public TreeIndexException(String message) {
-        super(message);
-    }
+	public TreeIndexException(String message) {
+		super(message);
+	}
 
-    public void setHandled(boolean handled) {
-        this.handled = handled;
-    }
+	public void setHandled(boolean handled) {
+		this.handled = handled;
+	}
 
-    public boolean getHandled() {
-        return handled;
-    }
+	public boolean getHandled() {
+		return handled;
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/data/PointablePrimitiveValueProviderFactory.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/data/PointablePrimitiveValueProviderFactory.java
new file mode 100644
index 0000000..c159ba5
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/data/PointablePrimitiveValueProviderFactory.java
@@ -0,0 +1,47 @@
+/*
+ * 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.common.data;
+
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
+import edu.uci.ics.hyracks.data.std.api.INumeric;
+import edu.uci.ics.hyracks.data.std.api.IPointable;
+import edu.uci.ics.hyracks.data.std.api.IPointableFactory;
+import edu.uci.ics.hyracks.storage.am.common.api.IPrimitiveValueProvider;
+import edu.uci.ics.hyracks.storage.am.common.api.IPrimitiveValueProviderFactory;
+
+public class PointablePrimitiveValueProviderFactory implements IPrimitiveValueProviderFactory {
+    private static final long serialVersionUID = 1L;
+
+    private final IPointableFactory pf;
+
+    public PointablePrimitiveValueProviderFactory(IPointableFactory pf) {
+        this.pf = pf;
+    }
+
+    @Override
+    public IPrimitiveValueProvider createPrimitiveValueProvider() {
+        final IPointable p = pf.createPointable();
+        ITypeTraits traits = pf.getTypeTraits();
+        assert traits.isFixedLength();
+        final int length = traits.getFixedLength();
+        return new IPrimitiveValueProvider() {
+            @Override
+            public double getValue(byte[] bytes, int offset) {
+                p.set(bytes, offset, length);
+                return ((INumeric) p).doubleValue();
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/AbstractTreeIndexOperatorDescriptor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/AbstractTreeIndexOperatorDescriptor.java
index 8230e19..ff4d078 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/AbstractTreeIndexOperatorDescriptor.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/AbstractTreeIndexOperatorDescriptor.java
@@ -16,103 +16,98 @@
 package edu.uci.ics.hyracks.storage.am.common.dataflow;
 
 import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
 import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
 import edu.uci.ics.hyracks.api.job.JobSpecification;
 import edu.uci.ics.hyracks.dataflow.std.base.AbstractSingleActivityOperatorDescriptor;
 import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
-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.ITreeIndexFrameFactory;
 import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
 
-public abstract class AbstractTreeIndexOperatorDescriptor extends AbstractSingleActivityOperatorDescriptor implements
-        ITreeIndexOperatorDescriptorHelper {
+public abstract class AbstractTreeIndexOperatorDescriptor extends
+		AbstractSingleActivityOperatorDescriptor implements
+		ITreeIndexOperatorDescriptor {
 
-    private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = 1L;
 
-    protected final IFileSplitProvider fileSplitProvider;
+	protected final IFileSplitProvider fileSplitProvider;
 
-    protected final IBinaryComparatorFactory[] comparatorFactories;
-    protected final IPrimitiveValueProviderFactory[] valueProviderFactories;
+	protected final IBinaryComparatorFactory[] comparatorFactories;
 
-    protected final ITreeIndexFrameFactory interiorFrameFactory;
-    protected final ITreeIndexFrameFactory leafFrameFactory;
+	protected final ITreeIndexFrameFactory interiorFrameFactory;
+	protected final ITreeIndexFrameFactory leafFrameFactory;
 
-    protected final IStorageManagerInterface storageManager;
-    protected final IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider;
+	protected final IStorageManagerInterface storageManager;
+	protected final IIndexRegistryProvider<IIndex> indexRegistryProvider;
 
-    protected final ITypeTrait[] typeTraits;
+	protected final ITypeTraits[] typeTraits;
+	protected final IIndexDataflowHelperFactory dataflowHelperFactory;
 
-    protected final ITreeIndexOpHelperFactory opHelperFactory;
+	public AbstractTreeIndexOperatorDescriptor(JobSpecification spec,
+			int inputArity, int outputArity, RecordDescriptor recDesc,
+			IStorageManagerInterface storageManager,
+			IIndexRegistryProvider<IIndex> indexRegistryProvider,
+			IFileSplitProvider fileSplitProvider,
+			ITreeIndexFrameFactory interiorFrameFactory,
+			ITreeIndexFrameFactory leafFrameFactory, ITypeTraits[] typeTraits,
+			IBinaryComparatorFactory[] comparatorFactories,
+			IIndexDataflowHelperFactory dataflowHelperFactory) {
+		super(spec, inputArity, outputArity);
+		this.fileSplitProvider = fileSplitProvider;
+		this.storageManager = storageManager;
+		this.indexRegistryProvider = indexRegistryProvider;
+		this.interiorFrameFactory = interiorFrameFactory;
+		this.leafFrameFactory = leafFrameFactory;
+		this.typeTraits = typeTraits;
+		this.comparatorFactories = comparatorFactories;
+		this.dataflowHelperFactory = dataflowHelperFactory;
+		if (outputArity > 0) {
+			recordDescriptors[0] = recDesc;
+		}
+	}
 
-    public AbstractTreeIndexOperatorDescriptor(JobSpecification spec, int inputArity, int outputArity,
-            RecordDescriptor recDesc, IStorageManagerInterface storageManager,
-            IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider, IFileSplitProvider fileSplitProvider,
-            ITreeIndexFrameFactory interiorFrameFactory, ITreeIndexFrameFactory leafFrameFactory,
-            ITypeTrait[] typeTraits, IBinaryComparatorFactory[] comparatorFactories,
-            IPrimitiveValueProviderFactory[] valueProviderFactories, ITreeIndexOpHelperFactory opHelperFactory) {
-        super(spec, inputArity, outputArity);
-        this.fileSplitProvider = fileSplitProvider;
-        this.storageManager = storageManager;
-        this.treeIndexRegistryProvider = treeIndexRegistryProvider;
-        this.interiorFrameFactory = interiorFrameFactory;
-        this.leafFrameFactory = leafFrameFactory;
-        this.typeTraits = typeTraits;
-        this.comparatorFactories = comparatorFactories;
-        this.valueProviderFactories = valueProviderFactories;
-        this.opHelperFactory = opHelperFactory;
-        if (outputArity > 0)
-            recordDescriptors[0] = recDesc;
-    }
+	@Override
+	public IFileSplitProvider getFileSplitProvider() {
+		return fileSplitProvider;
+	}
 
-    @Override
-    public IFileSplitProvider getTreeIndexFileSplitProvider() {
-        return fileSplitProvider;
-    }
+	@Override
+	public IBinaryComparatorFactory[] getTreeIndexComparatorFactories() {
+		return comparatorFactories;
+	}
 
-    @Override
-    public IBinaryComparatorFactory[] getTreeIndexComparatorFactories() {
-        return comparatorFactories;
-    }
+	@Override
+	public ITypeTraits[] getTreeIndexTypeTraits() {
+		return typeTraits;
+	}
 
-    @Override
-    public ITypeTrait[] getTreeIndexTypeTraits() {
-        return typeTraits;
-    }
+	@Override
+	public ITreeIndexFrameFactory getTreeIndexInteriorFactory() {
+		return interiorFrameFactory;
+	}
 
-    @Override
-    public IPrimitiveValueProviderFactory[] getTreeIndexValueProviderFactories() {
-        return valueProviderFactories;
-    }
+	@Override
+	public ITreeIndexFrameFactory getTreeIndexLeafFactory() {
+		return leafFrameFactory;
+	}
 
-    @Override
-    public ITreeIndexFrameFactory getTreeIndexInteriorFactory() {
-        return interiorFrameFactory;
-    }
+	@Override
+	public IStorageManagerInterface getStorageManager() {
+		return storageManager;
+	}
 
-    @Override
-    public ITreeIndexFrameFactory getTreeIndexLeafFactory() {
-        return leafFrameFactory;
-    }
+	@Override
+	public IIndexRegistryProvider<IIndex> getIndexRegistryProvider() {
+		return indexRegistryProvider;
+	}
 
-    @Override
-    public IStorageManagerInterface getStorageManager() {
-        return storageManager;
-    }
+	@Override
+	public RecordDescriptor getRecordDescriptor() {
+		return recordDescriptors[0];
+	}
 
-    @Override
-    public IIndexRegistryProvider<ITreeIndex> getTreeIndexRegistryProvider() {
-        return treeIndexRegistryProvider;
-    }
-
-    @Override
-    public RecordDescriptor getRecordDescriptor() {
-        return recordDescriptors[0];
-    }
-
-    @Override
-    public ITreeIndexOpHelperFactory getTreeIndexOpHelperFactory() {
-        return opHelperFactory;
-    }
-}
+	@Override
+	public IIndexDataflowHelperFactory getIndexDataflowHelperFactory() {
+		return dataflowHelperFactory;
+	}
+}
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndex.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndex.java
new file mode 100644
index 0000000..38b275b
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndex.java
@@ -0,0 +1,47 @@
+/*
+ * 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.common.dataflow;
+
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+
+/**
+ * Interface describing the operations common to all indexes.
+ */
+public interface IIndex {
+    /**
+     * Initializes the persistent state of an index, e.g., the root page,
+     * and metadata pages.
+     * 
+     * @param indexFileId
+     *            The file id to use for this index.
+     * @throws HyracksDataException
+     *             If the BufferCache throws while un/pinning or un/latching.
+     */
+    public void create(int indexFileId) throws HyracksDataException;
+
+    /**
+     * Opens the index backed by the given file id.
+     * 
+     * @param indexFileId
+     *            The file id backing this index.
+     */
+    public void open(int indexFileId);
+    
+    /**
+     * Closes the index.
+     */
+    public void close();
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexDataflowHelperFactory.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexDataflowHelperFactory.java
new file mode 100644
index 0000000..a42cf5f
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexDataflowHelperFactory.java
@@ -0,0 +1,25 @@
+/*
+ * 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.common.dataflow;
+
+import java.io.Serializable;
+
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
+
+public interface IIndexDataflowHelperFactory extends Serializable {
+    public IndexDataflowHelper createIndexDataflowHelper(IIndexOperatorDescriptor opDesc,
+            final IHyracksTaskContext ctx, int partition, boolean createIfNotExists);
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.java
new file mode 100644
index 0000000..edf2bba
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.java
@@ -0,0 +1,33 @@
+/*
+ * 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.common.dataflow;
+
+import edu.uci.ics.hyracks.api.dataflow.IActivity;
+import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
+import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
+import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
+
+public interface IIndexOperatorDescriptor extends IActivity {
+    public IFileSplitProvider getFileSplitProvider();
+
+    public IStorageManagerInterface getStorageManager();
+
+    public IIndexRegistryProvider<IIndex> getIndexRegistryProvider();    
+    
+    public RecordDescriptor getRecordDescriptor();
+    
+    public IIndexDataflowHelperFactory getIndexDataflowHelperFactory();
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexRegistryProvider.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexRegistryProvider.java
index aadcaf9..ed20de0 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexRegistryProvider.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexRegistryProvider.java
@@ -17,8 +17,8 @@
 
 import java.io.Serializable;
 
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 
 public interface IIndexRegistryProvider<IndexType> extends Serializable {
-    public IndexRegistry<IndexType> getRegistry(IHyracksStageletContext ctx);
+	public IndexRegistry<IndexType> getRegistry(IHyracksTaskContext ctx);
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOpHelperFactory.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOpHelperFactory.java
deleted file mode 100644
index fa37fab..0000000
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOpHelperFactory.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package edu.uci.ics.hyracks.storage.am.common.dataflow;
-
-import java.io.Serializable;
-
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
-
-public interface ITreeIndexOpHelperFactory extends Serializable {
-    public TreeIndexOpHelper createTreeIndexOpHelper(ITreeIndexOperatorDescriptorHelper opDesc,
-            final IHyracksStageletContext ctx, int partition, IndexHelperOpenMode mode);
-}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOperatorDescriptor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOperatorDescriptor.java
new file mode 100644
index 0000000..e415cbb
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOperatorDescriptor.java
@@ -0,0 +1,31 @@
+/*
+ * 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.common.dataflow;
+
+import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrameFactory;
+
+public interface ITreeIndexOperatorDescriptor extends IIndexOperatorDescriptor {
+	public IBinaryComparatorFactory[] getTreeIndexComparatorFactories();
+	
+	public ITreeIndexFrameFactory getTreeIndexInteriorFactory();
+
+	public ITreeIndexFrameFactory getTreeIndexLeafFactory();
+
+	public ITypeTraits[] getTreeIndexTypeTraits();
+	
+}
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOperatorDescriptorHelper.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOperatorDescriptorHelper.java
deleted file mode 100644
index 98806ae..0000000
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOperatorDescriptorHelper.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package edu.uci.ics.hyracks.storage.am.common.dataflow;
-
-import edu.uci.ics.hyracks.api.dataflow.IActivityNode;
-import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
-import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
-import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
-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.ITreeIndexFrameFactory;
-import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
-
-public interface ITreeIndexOperatorDescriptorHelper extends IActivityNode {
-    public IFileSplitProvider getTreeIndexFileSplitProvider();
-
-    public IBinaryComparatorFactory[] getTreeIndexComparatorFactories();
-
-    public IPrimitiveValueProviderFactory[] getTreeIndexValueProviderFactories();
-
-    public ITypeTrait[] getTreeIndexTypeTraits();
-
-    public ITreeIndexFrameFactory getTreeIndexInteriorFactory();
-
-    public ITreeIndexFrameFactory getTreeIndexLeafFactory();
-
-    public IStorageManagerInterface getStorageManager();
-
-    public IIndexRegistryProvider<ITreeIndex> getTreeIndexRegistryProvider();
-
-    public RecordDescriptor getRecordDescriptor();
-
-    public ITreeIndexOpHelperFactory getTreeIndexOpHelperFactory();
-}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
new file mode 100644
index 0000000..99ebab7
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
@@ -0,0 +1,114 @@
+/*
+ * 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.common.dataflow;
+
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.api.io.FileReference;
+import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
+
+public abstract class IndexDataflowHelper {
+    protected IIndex index;
+    protected int indexFileId = -1;
+    protected int partition;
+    
+    protected final IIndexOperatorDescriptor opDesc;
+    protected final IHyracksTaskContext ctx;
+    protected final boolean createIfNotExists;
+    
+    public IndexDataflowHelper(IIndexOperatorDescriptor opDesc, final IHyracksTaskContext ctx,
+            int partition, boolean createIfNotExists) {
+        this.opDesc = opDesc;
+        this.ctx = ctx;        
+        this.partition = partition;
+        this.createIfNotExists = createIfNotExists;
+    }
+
+    public void init() throws HyracksDataException {
+        IBufferCache bufferCache = opDesc.getStorageManager().getBufferCache(ctx);
+        IFileMapProvider fileMapProvider = opDesc.getStorageManager().getFileMapProvider(ctx);        
+
+        FileReference f = getFilereference();
+        int fileId = -1;
+        synchronized (fileMapProvider) {
+            boolean fileIsMapped = fileMapProvider.isMapped(f);
+            if (!fileIsMapped) {
+                bufferCache.createFile(f);
+            }
+            fileId = fileMapProvider.lookupFileId(f);
+            try {
+                bufferCache.openFile(fileId);
+            } catch (HyracksDataException e) {
+                // Revert state of buffer cache since file failed to open.
+                if (!fileIsMapped) {
+                    bufferCache.deleteFile(fileId, false);
+                }
+                throw e;
+            }
+        }
+
+        // Only set indexFileId member when openFile() succeeds,
+        // otherwise deinit() will try to close the file that failed to open
+        indexFileId = fileId;
+        IndexRegistry<IIndex> indexRegistry = opDesc.getIndexRegistryProvider().getRegistry(ctx);
+        // Create new index instance and register it.
+        synchronized (indexRegistry) {
+            // Check if the index has already been registered.
+            index = indexRegistry.get(indexFileId);
+            if (index != null) {
+                return;
+            }
+            index = createIndexInstance();
+            if (createIfNotExists) {
+                index.create(indexFileId);                
+            }
+            index.open(indexFileId);
+            indexRegistry.register(indexFileId, index);
+        }
+    }
+
+    public abstract IIndex createIndexInstance() throws HyracksDataException;
+
+    public FileReference getFilereference() {
+        IFileSplitProvider fileSplitProvider = opDesc.getFileSplitProvider();
+        return fileSplitProvider.getFileSplits()[partition].getLocalFile();
+    }
+    
+    public void deinit() throws HyracksDataException {
+        if (indexFileId != -1) {
+            IBufferCache bufferCache = opDesc.getStorageManager().getBufferCache(ctx);
+            bufferCache.closeFile(indexFileId);
+        }
+    }
+
+    public IIndex getIndex() {
+        return index;
+    }
+
+    public IHyracksTaskContext getHyracksTaskContext() {
+        return ctx;
+    }
+
+    public IIndexOperatorDescriptor getOperatorDescriptor() {
+        return opDesc;
+    }
+
+    public int getIndexFileId() {
+        return indexFileId;
+    }
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexHelperOpenMode.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexHelperOpenMode.java
deleted file mode 100644
index aa41184..0000000
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexHelperOpenMode.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package edu.uci.ics.hyracks.storage.am.common.dataflow;
-
-public enum IndexHelperOpenMode {
-    OPEN, CREATE, ENLIST
-}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.java
index de00d5a..5f3b0b3 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.java
@@ -16,38 +16,27 @@
 package edu.uci.ics.hyracks.storage.am.common.dataflow;
 
 import java.util.HashMap;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
 
 public class IndexRegistry<IndexType> {
 
-    private HashMap<Integer, IndexType> map = new HashMap<Integer, IndexType>();
-    private Lock registryLock = new ReentrantLock();
+	private HashMap<Integer, IndexType> map = new HashMap<Integer, IndexType>();
 
-    public IndexType get(int fileId) {
-        return map.get(fileId);
-    }
+	public IndexType get(int fileId) {
+		return map.get(fileId);
+	}
 
-    public void lock() {
-        registryLock.lock();
-    }
+	public void register(int fileId, IndexType index) {
+		map.put(fileId, index);
+	}
 
-    public void unlock() {
-        registryLock.unlock();
-    }
+	public void unregister(int fileId) {
+		try {
+			map.remove(fileId);
+		} catch (Exception e) {
+		}
+	}
 
-    public void register(int fileId, IndexType index) {
-        map.put(fileId, index);
-    }
-
-    public void unregister(int fileId) {
-        try {
-            map.remove(fileId);
-        } catch (Exception e) {
-        }
-    }
-
-    public int size() {
-        return map.size();
-    }
+	public int size() {
+		return map.size();
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/PermutingFrameTupleReference.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/PermutingFrameTupleReference.java
index 3db9db2..0b296f0 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/PermutingFrameTupleReference.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/PermutingFrameTupleReference.java
@@ -19,47 +19,47 @@
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
 
 public class PermutingFrameTupleReference implements IFrameTupleReference {
-    private IFrameTupleAccessor fta;
-    private int tIndex;
-    private int[] fieldPermutation;
+	private IFrameTupleAccessor fta;
+	private int tIndex;
+	private int[] fieldPermutation;
 
-    public void setFieldPermutation(int[] fieldPermutation) {
-        this.fieldPermutation = fieldPermutation;
-    }
+	public void setFieldPermutation(int[] fieldPermutation) {
+		this.fieldPermutation = fieldPermutation;
+	}
 
-    public void reset(IFrameTupleAccessor fta, int tIndex) {
-        this.fta = fta;
-        this.tIndex = tIndex;
-    }
+	public void reset(IFrameTupleAccessor fta, int tIndex) {
+		this.fta = fta;
+		this.tIndex = tIndex;
+	}
 
-    @Override
-    public IFrameTupleAccessor getFrameTupleAccessor() {
-        return fta;
-    }
+	@Override
+	public IFrameTupleAccessor getFrameTupleAccessor() {
+		return fta;
+	}
 
-    @Override
-    public int getTupleIndex() {
-        return tIndex;
-    }
+	@Override
+	public int getTupleIndex() {
+		return tIndex;
+	}
 
-    @Override
-    public int getFieldCount() {
-        return fieldPermutation.length;
-    }
+	@Override
+	public int getFieldCount() {
+		return fieldPermutation.length;
+	}
 
-    @Override
-    public byte[] getFieldData(int fIdx) {
-        return fta.getBuffer().array();
-    }
+	@Override
+	public byte[] getFieldData(int fIdx) {
+		return fta.getBuffer().array();
+	}
 
-    @Override
-    public int getFieldStart(int fIdx) {
-        return fta.getTupleStartOffset(tIndex) + fta.getFieldSlotsLength()
-                + fta.getFieldStartOffset(tIndex, fieldPermutation[fIdx]);
-    }
+	@Override
+	public int getFieldStart(int fIdx) {
+		return fta.getTupleStartOffset(tIndex) + fta.getFieldSlotsLength()
+				+ fta.getFieldStartOffset(tIndex, fieldPermutation[fIdx]);
+	}
 
-    @Override
-    public int getFieldLength(int fIdx) {
-        return fta.getFieldLength(tIndex, fieldPermutation[fIdx]);
-    }
+	@Override
+	public int getFieldLength(int fIdx) {
+		return fta.getFieldLength(tIndex, fieldPermutation[fIdx]);
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java
index 30fd976..af30105 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java
@@ -15,16 +15,13 @@
 
 package edu.uci.ics.hyracks.storage.am.common.dataflow;
 
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.dataflow.IOperatorNodePushable;
 import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
 import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
-import edu.uci.ics.hyracks.api.job.IOperatorEnvironment;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
 import edu.uci.ics.hyracks.api.job.JobSpecification;
 import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
-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.ITreeIndexFrameFactory;
 import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
 
@@ -36,21 +33,20 @@
     private final float fillFactor;
 
     public TreeIndexBulkLoadOperatorDescriptor(JobSpecification spec, IStorageManagerInterface storageManager,
-            IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider, IFileSplitProvider fileSplitProvider,
+            IIndexRegistryProvider<IIndex> indexRegistryProvider, IFileSplitProvider fileSplitProvider,
             ITreeIndexFrameFactory interiorFrameFactory, ITreeIndexFrameFactory leafFrameFactory,
-            ITypeTrait[] typeTraits, IBinaryComparatorFactory[] comparatorFactories,
-            IPrimitiveValueProviderFactory[] valueProviderFactories, int[] fieldPermutation, float fillFactor,
-            ITreeIndexOpHelperFactory opHelperFactory) {
-        super(spec, 1, 0, null, storageManager, treeIndexRegistryProvider, fileSplitProvider, interiorFrameFactory,
-                leafFrameFactory, typeTraits, comparatorFactories, valueProviderFactories, opHelperFactory);
+            ITypeTraits[] typeTraits, IBinaryComparatorFactory[] comparatorFactories, int[] fieldPermutation,
+            float fillFactor, IIndexDataflowHelperFactory dataflowHelperFactory) {
+        super(spec, 1, 0, null, storageManager, indexRegistryProvider, fileSplitProvider, interiorFrameFactory,
+                leafFrameFactory, typeTraits, comparatorFactories, dataflowHelperFactory);
         this.fieldPermutation = fieldPermutation;
         this.fillFactor = fillFactor;
     }
 
     @Override
-    public IOperatorNodePushable createPushRuntime(IHyracksStageletContext ctx, IOperatorEnvironment env,
+    public IOperatorNodePushable createPushRuntime(IHyracksTaskContext ctx,
             IRecordDescriptorProvider recordDescProvider, int partition, int nPartitions) {
         return new TreeIndexBulkLoadOperatorNodePushable(this, ctx, partition, fieldPermutation, fillFactor,
                 recordDescProvider);
     }
-}
+}
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java
index 2001039..bc2d67e 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java
@@ -16,31 +16,31 @@
 
 import java.nio.ByteBuffer;
 
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
 import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
 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.ITreeIndexMetaDataFrame;
-import edu.uci.ics.hyracks.storage.am.common.frames.LIFOMetaDataFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
+import edu.uci.ics.hyracks.storage.am.common.api.PageAllocationException;
 
 public class TreeIndexBulkLoadOperatorNodePushable extends AbstractUnaryInputSinkOperatorNodePushable {
     private float fillFactor;
-    private final TreeIndexOpHelper treeIndexOpHelper;
+    private final TreeIndexDataflowHelper treeIndexHelper;
     private FrameTupleAccessor accessor;
     private IIndexBulkLoadContext bulkLoadCtx;
+    private ITreeIndex treeIndex;
 
     private IRecordDescriptorProvider recordDescProvider;
 
     private PermutingFrameTupleReference tuple = new PermutingFrameTupleReference();
 
-    public TreeIndexBulkLoadOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc,
-            IHyracksStageletContext ctx, int partition, int[] fieldPermutation, float fillFactor,
-            IRecordDescriptorProvider recordDescProvider) {
-        treeIndexOpHelper = opDesc.getTreeIndexOpHelperFactory().createTreeIndexOpHelper(opDesc, ctx, partition,
-                IndexHelperOpenMode.CREATE);
+    public TreeIndexBulkLoadOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc, IHyracksTaskContext ctx,
+            int partition, int[] fieldPermutation, float fillFactor, IRecordDescriptorProvider recordDescProvider) {
+        treeIndexHelper = (TreeIndexDataflowHelper) opDesc.getIndexDataflowHelperFactory().createIndexDataflowHelper(
+                opDesc, ctx, partition, true);
         this.fillFactor = fillFactor;
         this.recordDescProvider = recordDescProvider;
         tuple.setFieldPermutation(fieldPermutation);
@@ -48,19 +48,18 @@
 
     @Override
     public void open() throws HyracksDataException {
-        AbstractTreeIndexOperatorDescriptor opDesc = (AbstractTreeIndexOperatorDescriptor) treeIndexOpHelper
+        AbstractTreeIndexOperatorDescriptor opDesc = (AbstractTreeIndexOperatorDescriptor) treeIndexHelper
                 .getOperatorDescriptor();
         RecordDescriptor recDesc = recordDescProvider.getInputRecordDescriptor(opDesc.getOperatorId(), 0);
-        accessor = new FrameTupleAccessor(treeIndexOpHelper.getHyracksStageletContext().getFrameSize(), recDesc);
-        ITreeIndexMetaDataFrame metaFrame = new LIFOMetaDataFrame();
+        accessor = new FrameTupleAccessor(treeIndexHelper.getHyracksTaskContext().getFrameSize(), recDesc);
         try {
-            treeIndexOpHelper.init();
-            treeIndexOpHelper.getTreeIndex().open(treeIndexOpHelper.getIndexFileId());
-            bulkLoadCtx = treeIndexOpHelper.getTreeIndex().beginBulkLoad(fillFactor, treeIndexOpHelper.getLeafFrame(),
-                    treeIndexOpHelper.getInteriorFrame(), metaFrame);
+            treeIndexHelper.init();
+            treeIndex = (ITreeIndex) treeIndexHelper.getIndex();
+            treeIndex.open(treeIndexHelper.getIndexFileId());
+            bulkLoadCtx = treeIndex.beginBulkLoad(fillFactor);
         } catch (Exception e) {
             // cleanup in case of failure
-            treeIndexOpHelper.deinit();
+            treeIndexHelper.deinit();
             throw new HyracksDataException(e);
         }
     }
@@ -71,20 +70,26 @@
         int tupleCount = accessor.getTupleCount();
         for (int i = 0; i < tupleCount; i++) {
             tuple.reset(accessor, i);
-            treeIndexOpHelper.getTreeIndex().bulkLoadAddTuple(bulkLoadCtx, tuple);
+            try {
+                treeIndex.bulkLoadAddTuple(tuple, bulkLoadCtx);
+            } catch (PageAllocationException e) {
+                throw new HyracksDataException(e);
+            }
         }
     }
 
     @Override
     public void close() throws HyracksDataException {
         try {
-            treeIndexOpHelper.getTreeIndex().endBulkLoad(bulkLoadCtx);
+            treeIndex.endBulkLoad(bulkLoadCtx);
+        } catch (PageAllocationException e) {
+            throw new HyracksDataException(e);
         } finally {
-            treeIndexOpHelper.deinit();
+            treeIndexHelper.deinit();
         }
     }
 
     @Override
-    public void flush() throws HyracksDataException {
+    public void fail() throws HyracksDataException {
     }
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDataflowHelper.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDataflowHelper.java
new file mode 100644
index 0000000..17c1827
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDataflowHelper.java
@@ -0,0 +1,38 @@
+/*
+ * 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.common.dataflow;
+
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
+import edu.uci.ics.hyracks.storage.am.common.impls.TreeDiskOrderScanCursor;
+
+public abstract class TreeIndexDataflowHelper extends IndexDataflowHelper {
+    protected ITreeIndexOperatorDescriptor treeOpDesc;
+    public TreeIndexDataflowHelper(IIndexOperatorDescriptor opDesc, IHyracksTaskContext ctx, int partition,
+            boolean createIfNotExists) {
+        super(opDesc, ctx, partition, createIfNotExists);
+        this.treeOpDesc = (ITreeIndexOperatorDescriptor) opDesc;
+    }
+
+    public abstract ITreeIndex createIndexInstance() throws HyracksDataException;
+    
+    public ITreeIndexCursor createDiskOrderScanCursor(ITreeIndexFrame leafFrame) throws HyracksDataException {
+        return new TreeDiskOrderScanCursor(leafFrame);
+    }
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java
index 9e18efb..8d56d37 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java
@@ -15,33 +15,38 @@
 
 package edu.uci.ics.hyracks.storage.am.common.dataflow;
 
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.dataflow.IOperatorNodePushable;
 import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
 import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
-import edu.uci.ics.hyracks.api.job.IOperatorEnvironment;
 import edu.uci.ics.hyracks.api.job.JobSpecification;
 import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrameFactory;
 import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
 
-public class TreeIndexDiskOrderScanOperatorDescriptor extends AbstractTreeIndexOperatorDescriptor {
+public class TreeIndexDiskOrderScanOperatorDescriptor extends
+		AbstractTreeIndexOperatorDescriptor {
 
-    private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = 1L;
 
-    public TreeIndexDiskOrderScanOperatorDescriptor(JobSpecification spec, RecordDescriptor recDesc,
-            IStorageManagerInterface storageManager, IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider,
-            IFileSplitProvider fileSplitProvider, ITreeIndexFrameFactory interiorFrameFactory,
-            ITreeIndexFrameFactory leafFrameFactory, ITypeTrait[] typeTraits, ITreeIndexOpHelperFactory opHelperFactory) {
-        super(spec, 0, 1, recDesc, storageManager, treeIndexRegistryProvider, fileSplitProvider, interiorFrameFactory,
-                leafFrameFactory, typeTraits, null, null, opHelperFactory);
-    }
+	public TreeIndexDiskOrderScanOperatorDescriptor(JobSpecification spec,
+			RecordDescriptor recDesc, IStorageManagerInterface storageManager,
+			IIndexRegistryProvider<IIndex> indexRegistryProvider,
+			IFileSplitProvider fileSplitProvider,
+			ITreeIndexFrameFactory interiorFrameFactory,
+			ITreeIndexFrameFactory leafFrameFactory, ITypeTraits[] typeTraits,
+			IIndexDataflowHelperFactory dataflowHelperFactory) {
+		super(spec, 0, 1, recDesc, storageManager, indexRegistryProvider,
+				fileSplitProvider, interiorFrameFactory, leafFrameFactory,
+				typeTraits, null, dataflowHelperFactory);
+	}
 
-    @Override
-    public IOperatorNodePushable createPushRuntime(IHyracksStageletContext ctx, IOperatorEnvironment env,
-            IRecordDescriptorProvider recordDescProvider, int partition, int nPartitions) {
-        return new TreeIndexDiskOrderScanOperatorNodePushable(this, ctx, partition);
-    }
+	@Override
+	public IOperatorNodePushable createPushRuntime(IHyracksTaskContext ctx,
+			IRecordDescriptorProvider recordDescProvider,
+			int partition, int nPartitions) {
+		return new TreeIndexDiskOrderScanOperatorNodePushable(this, ctx,
+				partition);
+	}
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java
index 415b9e3..d9b4d87 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java
@@ -17,48 +17,44 @@
 import java.io.DataOutput;
 import java.nio.ByteBuffer;
 
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
 import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAppender;
 import edu.uci.ics.hyracks.dataflow.common.comm.util.FrameUtils;
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
 import edu.uci.ics.hyracks.dataflow.std.base.AbstractUnaryOutputSourceOperatorNodePushable;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
+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.ITreeIndexMetaDataFrame;
-import edu.uci.ics.hyracks.storage.am.common.frames.LIFOMetaDataFrame;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOpContext;
 
 public class TreeIndexDiskOrderScanOperatorNodePushable extends AbstractUnaryOutputSourceOperatorNodePushable {
-    private final TreeIndexOpHelper treeIndexOpHelper;
+    private final TreeIndexDataflowHelper treeIndexHelper;
+    private final ITreeIndexOperatorDescriptor opDesc;
+    private ITreeIndex treeIndex;
 
     public TreeIndexDiskOrderScanOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc,
-            IHyracksStageletContext ctx, int partition) {
-        treeIndexOpHelper = opDesc.getTreeIndexOpHelperFactory().createTreeIndexOpHelper(opDesc, ctx, partition,
-                IndexHelperOpenMode.OPEN);
+            IHyracksTaskContext ctx, int partition) {
+        treeIndexHelper = (TreeIndexDataflowHelper) opDesc.getIndexDataflowHelperFactory().createIndexDataflowHelper(
+                opDesc, ctx, partition, false);
+        this.opDesc = opDesc;
     }
 
     @Override
     public void initialize() throws HyracksDataException {
-
-        ITreeIndexFrame cursorFrame = treeIndexOpHelper.getOperatorDescriptor().getTreeIndexLeafFactory().createFrame();
-        ITreeIndexCursor cursor = treeIndexOpHelper.createDiskOrderScanCursor(cursorFrame);
-        ITreeIndexMetaDataFrame metaFrame = new LIFOMetaDataFrame();
-
-        IndexOpContext diskOrderScanOpCtx = treeIndexOpHelper.getTreeIndex().createOpContext(IndexOp.DISKORDERSCAN,
-                cursorFrame, null, null);
+        ITreeIndexFrame cursorFrame = opDesc.getTreeIndexLeafFactory().createFrame();
+        ITreeIndexCursor cursor = treeIndexHelper.createDiskOrderScanCursor(cursorFrame);
         try {
-
-            treeIndexOpHelper.init();
-
+            treeIndexHelper.init();
+            treeIndex = (ITreeIndex) treeIndexHelper.getIndex();
+            ITreeIndexAccessor indexAccessor = treeIndex.createAccessor();
+            writer.open();
             try {
-                treeIndexOpHelper.getTreeIndex().diskOrderScan(cursor, cursorFrame, metaFrame, diskOrderScanOpCtx);
-
-                int fieldCount = treeIndexOpHelper.getTreeIndex().getFieldCount();
-                ByteBuffer frame = treeIndexOpHelper.getHyracksStageletContext().allocateFrame();
-                FrameTupleAppender appender = new FrameTupleAppender(treeIndexOpHelper.getHyracksStageletContext()
+                indexAccessor.diskOrderScan(cursor);
+                int fieldCount = treeIndex.getFieldCount();
+                ByteBuffer frame = treeIndexHelper.getHyracksTaskContext().allocateFrame();
+                FrameTupleAppender appender = new FrameTupleAppender(treeIndexHelper.getHyracksTaskContext()
                         .getFrameSize());
                 appender.reset(frame, true);
                 ArrayTupleBuilder tb = new ArrayTupleBuilder(fieldCount);
@@ -82,15 +78,16 @@
                         }
                     }
                 }
-
                 if (appender.getTupleCount() > 0) {
                     FrameUtils.flushFrame(frame, writer);
                 }
+            } catch (Exception e) {
+                writer.fail();
+                throw new HyracksDataException(e);
             } finally {
                 cursor.close();
                 writer.close();
             }
-
         } catch (Exception e) {
             deinitialize();
             throw new HyracksDataException(e);
@@ -99,6 +96,6 @@
 
     @Override
     public void deinitialize() throws HyracksDataException {
-        treeIndexOpHelper.deinit();
+        treeIndexHelper.deinit();
     }
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorDescriptor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorDescriptor.java
index 2cfa905..6ce18db 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorDescriptor.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorDescriptor.java
@@ -15,36 +15,38 @@
 
 package edu.uci.ics.hyracks.storage.am.common.dataflow;
 
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.dataflow.IOperatorNodePushable;
 import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
-import edu.uci.ics.hyracks.api.job.IOperatorEnvironment;
 import edu.uci.ics.hyracks.api.job.JobSpecification;
 import edu.uci.ics.hyracks.dataflow.std.base.AbstractSingleActivityOperatorDescriptor;
 import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
 
-public class TreeIndexDropOperatorDescriptor extends AbstractSingleActivityOperatorDescriptor {
+public class TreeIndexDropOperatorDescriptor extends
+		AbstractSingleActivityOperatorDescriptor {
 
-    private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = 1L;
 
-    private IStorageManagerInterface storageManager;
-    private IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider;
-    private IFileSplitProvider fileSplitProvider;
+	private IStorageManagerInterface storageManager;
+	private IIndexRegistryProvider<IIndex> treeIndexRegistryProvider;
+	private IFileSplitProvider fileSplitProvider;
 
-    public TreeIndexDropOperatorDescriptor(JobSpecification spec, IStorageManagerInterface storageManager,
-            IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider, IFileSplitProvider fileSplitProvider) {
-        super(spec, 0, 0);
-        this.storageManager = storageManager;
-        this.treeIndexRegistryProvider = treeIndexRegistryProvider;
-        this.fileSplitProvider = fileSplitProvider;
-    }
+	public TreeIndexDropOperatorDescriptor(JobSpecification spec,
+			IStorageManagerInterface storageManager,
+			IIndexRegistryProvider<IIndex> treeIndexRegistryProvider,
+			IFileSplitProvider fileSplitProvider) {
+		super(spec, 0, 0);
+		this.storageManager = storageManager;
+		this.treeIndexRegistryProvider = treeIndexRegistryProvider;
+		this.fileSplitProvider = fileSplitProvider;
+	}
 
-    @Override
-    public IOperatorNodePushable createPushRuntime(IHyracksStageletContext ctx, IOperatorEnvironment env,
-            IRecordDescriptorProvider recordDescProvider, int partition, int nPartitions) {
-        return new TreeIndexDropOperatorNodePushable(ctx, storageManager, treeIndexRegistryProvider, fileSplitProvider,
-                partition);
-    }
+	@Override
+	public IOperatorNodePushable createPushRuntime(IHyracksTaskContext ctx,
+			IRecordDescriptorProvider recordDescProvider,
+			int partition, int nPartitions) {
+		return new TreeIndexDropOperatorNodePushable(ctx, storageManager,
+				treeIndexRegistryProvider, fileSplitProvider, partition);
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java
index 71346f7..5c96af8 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java
@@ -19,13 +19,12 @@
 import java.util.logging.Logger;
 
 import edu.uci.ics.hyracks.api.comm.IFrameWriter;
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.api.io.FileReference;
 import edu.uci.ics.hyracks.dataflow.std.base.AbstractOperatorNodePushable;
 import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
 import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
@@ -33,14 +32,14 @@
 public class TreeIndexDropOperatorNodePushable extends AbstractOperatorNodePushable {
     private static final Logger LOGGER = Logger.getLogger(TreeIndexDropOperatorNodePushable.class.getName());
 
-    private final IHyracksStageletContext ctx;
-    private IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider;
+    private final IHyracksTaskContext ctx;
+    private IIndexRegistryProvider<IIndex> treeIndexRegistryProvider;
     private IStorageManagerInterface storageManager;
     private IFileSplitProvider fileSplitProvider;
     private int partition;
 
-    public TreeIndexDropOperatorNodePushable(IHyracksStageletContext ctx, IStorageManagerInterface storageManager,
-            IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider, IFileSplitProvider fileSplitProvider,
+    public TreeIndexDropOperatorNodePushable(IHyracksTaskContext ctx, IStorageManagerInterface storageManager,
+            IIndexRegistryProvider<IIndex> treeIndexRegistryProvider, IFileSplitProvider fileSplitProvider,
             int partition) {
         this.ctx = ctx;
         this.storageManager = storageManager;
@@ -66,31 +65,27 @@
     @Override
     public void initialize() throws HyracksDataException {
         try {
-
-            IndexRegistry<ITreeIndex> treeIndexRegistry = treeIndexRegistryProvider.getRegistry(ctx);
+            IndexRegistry<IIndex> treeIndexRegistry = treeIndexRegistryProvider.getRegistry(ctx);
             IBufferCache bufferCache = storageManager.getBufferCache(ctx);
             IFileMapProvider fileMapProvider = storageManager.getFileMapProvider(ctx);
-
+            
             FileReference f = fileSplitProvider.getFileSplits()[partition].getLocalFile();
-
-            boolean fileIsMapped = fileMapProvider.isMapped(f);
-            if (!fileIsMapped) {
-                throw new HyracksDataException("Cannot drop Tree with name " + f.toString()
-                        + ". No file mapping exists.");
+            int indexFileId = -1;
+            synchronized (fileMapProvider) {
+                boolean fileIsMapped = fileMapProvider.isMapped(f);
+                if (!fileIsMapped) {
+                    throw new HyracksDataException("Cannot drop Tree with name " + f.toString()
+                            + ". No file mapping exists.");
+                }
+                indexFileId = fileMapProvider.lookupFileId(f);
             }
-
-            int indexFileId = fileMapProvider.lookupFileId(f);
-
-            // unregister tree instance
-            treeIndexRegistry.lock();
-            try {
+            // Unregister tree instance.
+            synchronized (treeIndexRegistry) {
                 treeIndexRegistry.unregister(indexFileId);
-            } finally {
-                treeIndexRegistry.unlock();
             }
 
             // remove name to id mapping
-            bufferCache.deleteFile(indexFileId);
+            bufferCache.deleteFile(indexFileId, false);
         }
         // TODO: for the time being we don't throw,
         // with proper exception handling (no hanging job problem) we should
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexFileEnlistmentOperatorDescriptor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexFileEnlistmentOperatorDescriptor.java
deleted file mode 100644
index 65069b8..0000000
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexFileEnlistmentOperatorDescriptor.java
+++ /dev/null
@@ -1,58 +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.common.dataflow;
-
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
-import edu.uci.ics.hyracks.api.dataflow.IOperatorNodePushable;
-import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
-import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
-import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
-import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
-import edu.uci.ics.hyracks.api.job.IOperatorEnvironment;
-import edu.uci.ics.hyracks.api.job.JobSpecification;
-import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
-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.ITreeIndexFrameFactory;
-import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
-
-// re-create in-memory state for a tree index that has already been built (i.e., the file exists):
-// 1. register files in file manager (FileManager)
-// 2. create file mappings (FileMappingProvider)
-// 3. register tree index instance (IndexRegistry)
-
-public class TreeIndexFileEnlistmentOperatorDescriptor extends AbstractTreeIndexOperatorDescriptor {
-
-    private static final long serialVersionUID = 1L;
-
-    public TreeIndexFileEnlistmentOperatorDescriptor(JobSpecification spec, RecordDescriptor recDesc,
-            IStorageManagerInterface storageManager, IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider,
-            IFileSplitProvider fileSplitProvider, ITreeIndexFrameFactory interiorFrameFactory,
-            ITreeIndexFrameFactory leafFrameFactory, ITypeTrait[] typeTraits,
-            IBinaryComparatorFactory[] comparatorFactories, IPrimitiveValueProviderFactory[] valueProviderFactories,
-            ITreeIndexOpHelperFactory opHelperFactory) {
-        super(spec, 0, 0, recDesc, storageManager, treeIndexRegistryProvider, fileSplitProvider, interiorFrameFactory,
-                leafFrameFactory, typeTraits, comparatorFactories, valueProviderFactories, opHelperFactory);
-    }
-
-    @Override
-    public IOperatorNodePushable createPushRuntime(IHyracksStageletContext ctx, IOperatorEnvironment env,
-            IRecordDescriptorProvider recordDescProvider, int partition, int partitions) throws HyracksDataException {
-        return new TreeIndexFileEnlistmentOperatorNodePushable(this, ctx, partition);
-    }
-
-}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexFileEnlistmentOperatorNodePushable.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexFileEnlistmentOperatorNodePushable.java
deleted file mode 100644
index 8ff6586..0000000
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexFileEnlistmentOperatorNodePushable.java
+++ /dev/null
@@ -1,60 +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.common.dataflow;
-
-import edu.uci.ics.hyracks.api.comm.IFrameWriter;
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
-import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
-import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
-import edu.uci.ics.hyracks.dataflow.std.base.AbstractOperatorNodePushable;
-
-public class TreeIndexFileEnlistmentOperatorNodePushable extends AbstractOperatorNodePushable {
-
-    private final TreeIndexOpHelper treeIndexOpHelper;
-
-    public TreeIndexFileEnlistmentOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc,
-            IHyracksStageletContext ctx, int partition) {
-        treeIndexOpHelper = opDesc.getTreeIndexOpHelperFactory().createTreeIndexOpHelper(opDesc, ctx, partition,
-                IndexHelperOpenMode.ENLIST);
-    }
-
-    @Override
-    public void deinitialize() throws HyracksDataException {
-    }
-
-    @Override
-    public int getInputArity() {
-        return 0;
-    }
-
-    @Override
-    public IFrameWriter getInputFrameWriter(int index) {
-        return null;
-    }
-
-    @Override
-    public void initialize() throws HyracksDataException {
-        try {
-            treeIndexOpHelper.init();
-        } finally {
-            treeIndexOpHelper.deinit();
-        }
-    }
-
-    @Override
-    public void setOutputFrameWriter(int index, IFrameWriter writer, RecordDescriptor recordDesc) {
-    }
-}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java
index 7f242bd..e08f5d6 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java
@@ -15,45 +15,49 @@
 
 package edu.uci.ics.hyracks.storage.am.common.dataflow;
 
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.dataflow.IOperatorNodePushable;
 import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
 import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
 import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
-import edu.uci.ics.hyracks.api.job.IOperatorEnvironment;
 import edu.uci.ics.hyracks.api.job.JobSpecification;
 import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
-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.ITreeIndexFrameFactory;
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
 import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
 
-public class TreeIndexInsertUpdateDeleteOperatorDescriptor extends AbstractTreeIndexOperatorDescriptor {
+public class TreeIndexInsertUpdateDeleteOperatorDescriptor extends
+		AbstractTreeIndexOperatorDescriptor {
 
-    private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = 1L;
 
-    private final int[] fieldPermutation;
+	private final int[] fieldPermutation;
 
-    private IndexOp op;
+	private IndexOp op;
 
-    public TreeIndexInsertUpdateDeleteOperatorDescriptor(JobSpecification spec, RecordDescriptor recDesc,
-            IStorageManagerInterface storageManager, IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider,
-            IFileSplitProvider fileSplitProvider, ITreeIndexFrameFactory interiorFrameFactory,
-            ITreeIndexFrameFactory leafFrameFactory, ITypeTrait[] typeTraits,
-            IBinaryComparatorFactory[] comparatorFactories, IPrimitiveValueProviderFactory[] valueProviderFactories,
-            int[] fieldPermutation, IndexOp op, ITreeIndexOpHelperFactory opHelperFactory) {
-        super(spec, 1, 1, recDesc, storageManager, treeIndexRegistryProvider, fileSplitProvider, interiorFrameFactory,
-                leafFrameFactory, typeTraits, comparatorFactories, valueProviderFactories, opHelperFactory);
-        this.fieldPermutation = fieldPermutation;
-        this.op = op;
-    }
+	public TreeIndexInsertUpdateDeleteOperatorDescriptor(JobSpecification spec,
+			RecordDescriptor recDesc, IStorageManagerInterface storageManager,
+			IIndexRegistryProvider<IIndex> indexRegistryProvider,
+			IFileSplitProvider fileSplitProvider,
+			ITreeIndexFrameFactory interiorFrameFactory,
+			ITreeIndexFrameFactory leafFrameFactory, ITypeTraits[] typeTraits,
+			IBinaryComparatorFactory[] comparatorFactories,
+			int[] fieldPermutation, IndexOp op,
+			IIndexDataflowHelperFactory dataflowHelperFactory) {
+		super(spec, 1, 1, recDesc, storageManager, indexRegistryProvider,
+				fileSplitProvider, interiorFrameFactory, leafFrameFactory,
+				typeTraits, comparatorFactories,
+				dataflowHelperFactory);
+		this.fieldPermutation = fieldPermutation;
+		this.op = op;
+	}
 
-    @Override
-    public IOperatorNodePushable createPushRuntime(IHyracksStageletContext ctx, IOperatorEnvironment env,
-            IRecordDescriptorProvider recordDescProvider, int partition, int nPartitions) {
-        return new TreeIndexInsertUpdateDeleteOperatorNodePushable(this, ctx, partition, fieldPermutation,
-                recordDescProvider, op);
-    }
-}
+	@Override
+	public IOperatorNodePushable createPushRuntime(IHyracksTaskContext ctx,
+			IRecordDescriptorProvider recordDescProvider,
+			int partition, int nPartitions) {
+		return new TreeIndexInsertUpdateDeleteOperatorNodePushable(this, ctx,
+				partition, fieldPermutation, recordDescProvider, op);
+	}
+}
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java
index 74a9efc..bf78249 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java
@@ -16,7 +16,7 @@
 
 import java.nio.ByteBuffer;
 
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
 import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
@@ -24,24 +24,25 @@
 import edu.uci.ics.hyracks.dataflow.common.comm.util.FrameUtils;
 import edu.uci.ics.hyracks.dataflow.std.base.AbstractUnaryInputUnaryOutputOperatorNodePushable;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
-import edu.uci.ics.hyracks.storage.am.common.frames.LIFOMetaDataFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexAccessor;
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOpContext;
 
 public class TreeIndexInsertUpdateDeleteOperatorNodePushable extends AbstractUnaryInputUnaryOutputOperatorNodePushable {
-    private final TreeIndexOpHelper treeIndexOpHelper;
+    private final TreeIndexDataflowHelper treeIndexHelper;
     private FrameTupleAccessor accessor;
     private final IRecordDescriptorProvider recordDescProvider;
     private final IndexOp op;
     private final PermutingFrameTupleReference tuple = new PermutingFrameTupleReference();
     private ByteBuffer writeBuffer;
-    private IndexOpContext opCtx;
+    private ITreeIndexAccessor indexAccessor;
 
     public TreeIndexInsertUpdateDeleteOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc,
-            IHyracksStageletContext ctx, int partition, int[] fieldPermutation,
+            IHyracksTaskContext ctx, int partition, int[] fieldPermutation,
             IRecordDescriptorProvider recordDescProvider, IndexOp op) {
-        treeIndexOpHelper = opDesc.getTreeIndexOpHelperFactory().createTreeIndexOpHelper(opDesc, ctx, partition,
-                IndexHelperOpenMode.OPEN);
+        // Only create the if insert operation is an insert.
+        boolean createIfNotExists = (op == IndexOp.INSERT);
+        treeIndexHelper = (TreeIndexDataflowHelper) opDesc.getIndexDataflowHelperFactory().createIndexDataflowHelper(
+                opDesc, ctx, partition, createIfNotExists);
         this.recordDescProvider = recordDescProvider;
         this.op = op;
         tuple.setFieldPermutation(fieldPermutation);
@@ -49,57 +50,55 @@
 
     @Override
     public void open() throws HyracksDataException {
-        AbstractTreeIndexOperatorDescriptor opDesc = (AbstractTreeIndexOperatorDescriptor) treeIndexOpHelper
+        AbstractTreeIndexOperatorDescriptor opDesc = (AbstractTreeIndexOperatorDescriptor) treeIndexHelper
                 .getOperatorDescriptor();
         RecordDescriptor inputRecDesc = recordDescProvider.getInputRecordDescriptor(opDesc.getOperatorId(), 0);
-        accessor = new FrameTupleAccessor(treeIndexOpHelper.getHyracksStageletContext().getFrameSize(), inputRecDesc);
-        writeBuffer = treeIndexOpHelper.getHyracksStageletContext().allocateFrame();
+        accessor = new FrameTupleAccessor(treeIndexHelper.getHyracksTaskContext().getFrameSize(), inputRecDesc);
+        writeBuffer = treeIndexHelper.getHyracksTaskContext().allocateFrame();
+        writer.open();
         try {
-            treeIndexOpHelper.init();
-            treeIndexOpHelper.getTreeIndex().open(treeIndexOpHelper.getIndexFileId());
-            opCtx = treeIndexOpHelper.getTreeIndex().createOpContext(op, treeIndexOpHelper.getLeafFrame(),
-                    treeIndexOpHelper.getInteriorFrame(), new LIFOMetaDataFrame());
+            treeIndexHelper.init();
+            ITreeIndex treeIndex = (ITreeIndex) treeIndexHelper.getIndex();
+            indexAccessor = treeIndex.createAccessor();
         } catch (Exception e) {
             // cleanup in case of failure
-            treeIndexOpHelper.deinit();
+            treeIndexHelper.deinit();
             throw new HyracksDataException(e);
         }
     }
 
     @Override
     public void nextFrame(ByteBuffer buffer) throws HyracksDataException {
-        final ITreeIndex treeIndex = treeIndexOpHelper.getTreeIndex();
         accessor.reset(buffer);
-
         int tupleCount = accessor.getTupleCount();
         for (int i = 0; i < tupleCount; i++) {
             tuple.reset(accessor, i);
             try {
                 switch (op) {
-
                     case INSERT: {
-                        treeIndex.insert(tuple, opCtx);
-                    }
+                        indexAccessor.insert(tuple);
                         break;
-
+                    }
+                    case UPDATE: {
+                        indexAccessor.update(tuple);
+                        break;
+                    }
                     case DELETE: {
-                        treeIndex.delete(tuple, opCtx);
-                    }
+                        indexAccessor.delete(tuple);
                         break;
-
+                    }
                     default: {
                         throw new HyracksDataException("Unsupported operation " + op
                                 + " in tree index InsertUpdateDelete operator");
                     }
-
                 }
-
+            } catch (HyracksDataException e) {
+                throw e;
             } catch (Exception e) {
-                e.printStackTrace();
+                throw new HyracksDataException(e);
             }
         }
-
-        // pass a copy of the frame to next op
+        // Pass a copy of the frame to next op.
         System.arraycopy(buffer.array(), 0, writeBuffer.array(), 0, buffer.capacity());
         FrameUtils.flushFrame(writeBuffer, writer);
     }
@@ -109,11 +108,12 @@
         try {
             writer.close();
         } finally {
-            treeIndexOpHelper.deinit();
+            treeIndexHelper.deinit();
         }
     }
 
     @Override
-    public void flush() throws HyracksDataException {
+    public void fail() throws HyracksDataException {
+        writer.fail();
     }
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexOpHelper.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexOpHelper.java
deleted file mode 100644
index 2b53592..0000000
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexOpHelper.java
+++ /dev/null
@@ -1,157 +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.common.dataflow;
-
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
-import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparator;
-import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
-import edu.uci.ics.hyracks.api.io.FileReference;
-import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexCursor;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
-import edu.uci.ics.hyracks.storage.am.common.impls.TreeDiskOrderScanCursor;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
-import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
-import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
-
-public abstract class TreeIndexOpHelper {
-
-    protected ITreeIndexFrame interiorFrame;
-    protected ITreeIndexFrame leafFrame;
-    protected MultiComparator cmp;
-
-    protected ITreeIndex treeIndex;
-    protected int indexFileId = -1;
-    protected int partition;
-
-    protected ITreeIndexOperatorDescriptorHelper opDesc;
-    protected IHyracksStageletContext ctx;
-
-    protected IndexHelperOpenMode mode;
-
-    public TreeIndexOpHelper(ITreeIndexOperatorDescriptorHelper opDesc, final IHyracksStageletContext ctx,
-            int partition, IndexHelperOpenMode mode) {
-        this.opDesc = opDesc;
-        this.ctx = ctx;
-        this.mode = mode;
-        this.partition = partition;
-    }
-
-    public void init() throws HyracksDataException {
-        IBufferCache bufferCache = opDesc.getStorageManager().getBufferCache(ctx);
-        IFileMapProvider fileMapProvider = opDesc.getStorageManager().getFileMapProvider(ctx);
-        IFileSplitProvider fileSplitProvider = opDesc.getTreeIndexFileSplitProvider();
-
-        FileReference f = fileSplitProvider.getFileSplits()[partition].getLocalFile();
-        boolean fileIsMapped = fileMapProvider.isMapped(f);
-        if (!fileIsMapped) {
-            bufferCache.createFile(f);
-        }
-        int fileId = fileMapProvider.lookupFileId(f);
-        try {
-            bufferCache.openFile(fileId);
-        } catch (HyracksDataException e) {
-            // Revert state of buffer cache since file failed to open.
-            if (!fileIsMapped) {
-                bufferCache.deleteFile(fileId);
-            }
-            throw e;
-        }
-
-        // Only set indexFileId member when openFile() succeeds,
-        // otherwise deinit() will try to close the file that failed to open
-        indexFileId = fileId;
-
-        interiorFrame = opDesc.getTreeIndexInteriorFactory().createFrame();
-        leafFrame = opDesc.getTreeIndexLeafFactory().createFrame();
-
-        IndexRegistry<ITreeIndex> treeIndexRegistry = opDesc.getTreeIndexRegistryProvider().getRegistry(ctx);
-        // Create new tree and register it.
-        treeIndexRegistry.lock();
-        try {
-            // Check if tree has already been registered by another thread.
-            treeIndex = treeIndexRegistry.get(indexFileId);
-            if (treeIndex != null) {
-                return;
-            }
-            IBinaryComparator[] comparators = new IBinaryComparator[opDesc.getTreeIndexComparatorFactories().length];
-            for (int i = 0; i < opDesc.getTreeIndexComparatorFactories().length; i++) {
-                comparators[i] = opDesc.getTreeIndexComparatorFactories()[i].createBinaryComparator();
-            }
-            cmp = createMultiComparator(comparators);
-            treeIndex = createTreeIndex();
-            if (mode == IndexHelperOpenMode.CREATE) {
-                ITreeIndexMetaDataFrame metaFrame = treeIndex.getFreePageManager().getMetaDataFrameFactory()
-                        .createFrame();
-                try {
-                    treeIndex.create(indexFileId, leafFrame, metaFrame);
-                } catch (Exception e) {
-                    throw new HyracksDataException(e);
-                }
-            }
-            treeIndex.open(indexFileId);
-            treeIndexRegistry.register(indexFileId, treeIndex);
-        } finally {
-            treeIndexRegistry.unlock();
-        }
-    }
-
-    // MUST be overridden
-    public ITreeIndex createTreeIndex() throws HyracksDataException {
-        throw new HyracksDataException("createTreeIndex Operation not implemented.");
-    }
-
-    // MUST be overridden
-    public MultiComparator createMultiComparator(IBinaryComparator[] comparators) throws HyracksDataException {
-        throw new HyracksDataException("createComparator Operation not implemented.");
-    }
-
-    public ITreeIndexCursor createDiskOrderScanCursor(ITreeIndexFrame leafFrame) throws HyracksDataException {
-        return new TreeDiskOrderScanCursor(leafFrame);
-    }
-
-    public void deinit() throws HyracksDataException {
-        if (indexFileId != -1) {
-            IBufferCache bufferCache = opDesc.getStorageManager().getBufferCache(ctx);
-            bufferCache.closeFile(indexFileId);
-        }
-    }
-
-    public ITreeIndex getTreeIndex() {
-        return treeIndex;
-    }
-
-    public IHyracksStageletContext getHyracksStageletContext() {
-        return ctx;
-    }
-
-    public ITreeIndexOperatorDescriptorHelper getOperatorDescriptor() {
-        return opDesc;
-    }
-
-    public ITreeIndexFrame getLeafFrame() {
-        return leafFrame;
-    }
-
-    public ITreeIndexFrame getInteriorFrame() {
-        return interiorFrame;
-    }
-
-    public int getIndexFileId() {
-        return indexFileId;
-    }
-}
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java
index 5dce449..4d718a8 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java
@@ -1,34 +1,50 @@
+/*
+ * 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.common.dataflow;
 
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.dataflow.IOperatorNodePushable;
 import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
 import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
-import edu.uci.ics.hyracks.api.job.IOperatorEnvironment;
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
+import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
 import edu.uci.ics.hyracks.api.job.JobSpecification;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.UTF8StringSerializerDeserializer;
 import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
-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.ITreeIndexFrameFactory;
 import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
 
 public class TreeIndexStatsOperatorDescriptor extends AbstractTreeIndexOperatorDescriptor {
 
     private static final long serialVersionUID = 1L;
+    private static final RecordDescriptor recDesc = new RecordDescriptor(
+            new ISerializerDeserializer[] { UTF8StringSerializerDeserializer.INSTANCE });
 
     public TreeIndexStatsOperatorDescriptor(JobSpecification spec, IStorageManagerInterface storageManager,
-            IIndexRegistryProvider<ITreeIndex> treeIndexRegistryProvider, IFileSplitProvider fileSplitProvider,
+            IIndexRegistryProvider<IIndex> indexRegistryProvider, IFileSplitProvider fileSplitProvider,
             ITreeIndexFrameFactory interiorFrameFactory, ITreeIndexFrameFactory leafFrameFactory,
-            ITypeTrait[] typeTraits, IBinaryComparatorFactory[] comparatorFactories,
-            ITreeIndexOpHelperFactory opHelperFactory) {
-        super(spec, 0, 0, null, storageManager, treeIndexRegistryProvider, fileSplitProvider, interiorFrameFactory,
-                leafFrameFactory, typeTraits, comparatorFactories, null, opHelperFactory);
+            ITypeTraits[] typeTraits, IBinaryComparatorFactory[] comparatorFactories,
+            IIndexDataflowHelperFactory dataflowHelperFactory) {
+        super(spec, 0, 1, recDesc, storageManager, indexRegistryProvider, fileSplitProvider, interiorFrameFactory,
+                leafFrameFactory, typeTraits, comparatorFactories, dataflowHelperFactory);
     }
 
     @Override
-    public IOperatorNodePushable createPushRuntime(IHyracksStageletContext ctx, IOperatorEnvironment env,
+    public IOperatorNodePushable createPushRuntime(IHyracksTaskContext ctx,
             IRecordDescriptorProvider recordDescProvider, int partition, int nPartitions) {
         return new TreeIndexStatsOperatorNodePushable(this, ctx, partition);
     }
-}
+}
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java
index f47855f..ff007af 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java
@@ -14,25 +14,31 @@
  */
 package edu.uci.ics.hyracks.storage.am.common.dataflow;
 
+import java.io.DataOutput;
+import java.nio.ByteBuffer;
+
 import edu.uci.ics.hyracks.api.comm.IFrameWriter;
-import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
-import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
-import edu.uci.ics.hyracks.dataflow.std.base.AbstractOperatorNodePushable;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAppender;
+import edu.uci.ics.hyracks.dataflow.common.comm.util.FrameUtils;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.UTF8StringSerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.std.base.AbstractUnaryOutputSourceOperatorNodePushable;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
-import edu.uci.ics.hyracks.storage.am.common.utility.TreeIndexStats;
-import edu.uci.ics.hyracks.storage.am.common.utility.TreeIndexStatsGatherer;
+import edu.uci.ics.hyracks.storage.am.common.util.TreeIndexStats;
+import edu.uci.ics.hyracks.storage.am.common.util.TreeIndexStatsGatherer;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 
-public class TreeIndexStatsOperatorNodePushable extends AbstractOperatorNodePushable {
-    private final TreeIndexOpHelper treeIndexOpHelper;
-    private final IHyracksStageletContext ctx;
+public class TreeIndexStatsOperatorNodePushable extends AbstractUnaryOutputSourceOperatorNodePushable {
+    private final TreeIndexDataflowHelper treeIndexHelper;
+    private final IHyracksTaskContext ctx;
     private TreeIndexStatsGatherer statsGatherer;
 
-    public TreeIndexStatsOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc, IHyracksStageletContext ctx,
+    public TreeIndexStatsOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc, IHyracksTaskContext ctx,
             int partition) {
-        treeIndexOpHelper = opDesc.getTreeIndexOpHelperFactory().createTreeIndexOpHelper(opDesc, ctx, partition,
-                IndexHelperOpenMode.CREATE);
+        treeIndexHelper = (TreeIndexDataflowHelper) opDesc.getIndexDataflowHelperFactory().createIndexDataflowHelper(
+                opDesc, ctx, partition, false);
         this.ctx = ctx;
     }
 
@@ -41,11 +47,6 @@
     }
 
     @Override
-    public int getInputArity() {
-        return 0;
-    }
-
-    @Override
     public IFrameWriter getInputFrameWriter(int index) {
         return null;
     }
@@ -53,26 +54,36 @@
     @Override
     public void initialize() throws HyracksDataException {
         try {
-            treeIndexOpHelper.init();
-            treeIndexOpHelper.getTreeIndex().open(treeIndexOpHelper.getIndexFileId());
-
-            ITreeIndex treeIndex = treeIndexOpHelper.getTreeIndex();
-            IBufferCache bufferCache = treeIndexOpHelper.getOperatorDescriptor().getStorageManager()
-                    .getBufferCache(ctx);
-
+            writer.open();
+            treeIndexHelper.init();
+            ITreeIndex treeIndex = (ITreeIndex) treeIndexHelper.getIndex();
+            IBufferCache bufferCache = treeIndexHelper.getOperatorDescriptor().getStorageManager().getBufferCache(ctx);
             statsGatherer = new TreeIndexStatsGatherer(bufferCache, treeIndex.getFreePageManager(),
-                    treeIndexOpHelper.getIndexFileId(), treeIndex.getRootPageId());
+                    treeIndexHelper.getIndexFileId(), treeIndex.getRootPageId());
             TreeIndexStats stats = statsGatherer.gatherStats(treeIndex.getLeafFrameFactory().createFrame(), treeIndex
                     .getInteriorFrameFactory().createFrame(), treeIndex.getFreePageManager().getMetaDataFrameFactory()
                     .createFrame());
-            System.err.println(stats.toString());
+            // Write the stats output as a single string field.
+            ByteBuffer frame = ctx.allocateFrame();
+            FrameTupleAppender appender = new FrameTupleAppender(ctx.getFrameSize());
+            appender.reset(frame, true);
+            ArrayTupleBuilder tb = new ArrayTupleBuilder(1);
+            DataOutput dos = tb.getDataOutput();
+            tb.reset();
+            UTF8StringSerializerDeserializer.INSTANCE.serialize(stats.toString(), dos);
+            tb.addFieldEndOffset();
+            if (!appender.append(tb.getFieldEndOffsets(), tb.getByteArray(), 0, tb.getSize())) {
+                throw new IllegalStateException();
+            }
+            FrameUtils.flushFrame(frame, writer);
         } catch (Exception e) {
-            treeIndexOpHelper.deinit();
-            throw new HyracksDataException(e);
+            try {
+                treeIndexHelper.deinit();
+            } finally {
+                writer.fail();
+            }
+        } finally {
+            writer.close();
         }
     }
-
-    @Override
-    public void setOutputFrameWriter(int index, IFrameWriter writer, RecordDescriptor recordDesc) {
-    }
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/AbstractSlotManager.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/AbstractSlotManager.java
index 87fea47..a1a38ab 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/AbstractSlotManager.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/AbstractSlotManager.java
@@ -19,42 +19,56 @@
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
 
 public abstract class AbstractSlotManager implements ISlotManager {
+	
+	protected final int GREATEST_KEY_INDICATOR = -1;
+    protected final int ERROR_INDICATOR = -2;
+	
+	protected static final int slotSize = 4;
+	protected ITreeIndexFrame frame;
 
-    protected static final int slotSize = 4;
-    protected ITreeIndexFrame frame;
+	@Override
+	public int getTupleOff(int offset) {
+		return frame.getBuffer().getInt(offset);
+	}
 
-    @Override
-    public int getTupleOff(int offset) {
-        return frame.getBuffer().getInt(offset);
+	@Override
+	public void setSlot(int offset, int value) {
+		frame.getBuffer().putInt(offset, value);
+	}
+
+	@Override
+	public int getSlotEndOff() {
+		return frame.getBuffer().capacity()
+				- (frame.getTupleCount() * slotSize);
+	}
+
+	@Override
+	public int getSlotStartOff() {
+		return frame.getBuffer().capacity() - slotSize;
+	}
+
+	@Override
+	public int getSlotSize() {
+		return slotSize;
+	}
+
+	@Override
+	public void setFrame(ITreeIndexFrame frame) {
+		this.frame = frame;
+	}
+
+	@Override
+	public int getSlotOff(int tupleIndex) {
+		return getSlotStartOff() - tupleIndex * slotSize;
+	}
+	
+	@Override
+    public int getGreatestKeyIndicator() {
+        return GREATEST_KEY_INDICATOR;
     }
 
     @Override
-    public void setSlot(int offset, int value) {
-        frame.getBuffer().putInt(offset, value);
-    }
-
-    @Override
-    public int getSlotEndOff() {
-        return frame.getBuffer().capacity() - (frame.getTupleCount() * slotSize);
-    }
-
-    @Override
-    public int getSlotStartOff() {
-        return frame.getBuffer().capacity() - slotSize;
-    }
-
-    @Override
-    public int getSlotSize() {
-        return slotSize;
-    }
-
-    @Override
-    public void setFrame(ITreeIndexFrame frame) {
-        this.frame = frame;
-    }
-
-    @Override
-    public int getSlotOff(int tupleIndex) {
-        return getSlotStartOff() - tupleIndex * slotSize;
+    public int getErrorIndicator() {
+        return ERROR_INDICATOR;
     }
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/FrameOpSpaceStatus.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/FrameOpSpaceStatus.java
index 97a4730..da9c815 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/FrameOpSpaceStatus.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/FrameOpSpaceStatus.java
@@ -16,5 +16,5 @@
 package edu.uci.ics.hyracks.storage.am.common.frames;
 
 public enum FrameOpSpaceStatus {
-    INSUFFICIENT_SPACE, SUFFICIENT_CONTIGUOUS_SPACE, SUFFICIENT_SPACE
+    INSUFFICIENT_SPACE, SUFFICIENT_CONTIGUOUS_SPACE, SUFFICIENT_SPACE, SUFFICIENT_INPLACE_SPACE
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java
index b621b89..c87b84a 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java
@@ -27,89 +27,89 @@
 
 public class LIFOMetaDataFrame implements ITreeIndexMetaDataFrame {
 
-    protected static final int tupleCountOff = 0;
-    protected static final int freeSpaceOff = tupleCountOff + 4;
-    protected static final int maxPageOff = freeSpaceOff + 4;
-    protected static final int dummyFieldOff = maxPageOff + 4;
-    protected static final byte levelOff = dummyFieldOff + 4;
-    protected static final byte nextPageOff = levelOff + 1;
+	protected static final int tupleCountOff = 0; //0
+	protected static final int freeSpaceOff = tupleCountOff + 4; //4
+	protected static final int maxPageOff = freeSpaceOff + 4; //8
+	protected static final int levelOff = maxPageOff + 12; //20
+	protected static final int nextPageOff = levelOff + 1; // 21
 
-    protected ICachedPage page = null;
-    protected ByteBuffer buf = null;
+	protected ICachedPage page = null;
+	protected ByteBuffer buf = null;
 
-    public int getMaxPage() {
-        return buf.getInt(maxPageOff);
-    }
+	public int getMaxPage() {
+		return buf.getInt(maxPageOff);
+	}
 
-    public void setMaxPage(int maxPage) {
-        buf.putInt(maxPageOff, maxPage);
-    }
+	public void setMaxPage(int maxPage) {
+		buf.putInt(maxPageOff, maxPage);
+	}
 
-    public int getFreePage() {
-        int tupleCount = buf.getInt(tupleCountOff);
-        if (tupleCount > 0) {
-            // return the last page from the linked list of free pages
-            // TODO: this is a dumb policy, but good enough for now
-            int lastPageOff = buf.getInt(freeSpaceOff) - 4;
-            buf.putInt(freeSpaceOff, lastPageOff);
-            buf.putInt(tupleCountOff, tupleCount - 1);
-            return buf.getInt(lastPageOff);
-        } else {
-            return -1;
-        }
-    }
+	public int getFreePage() {
+		int tupleCount = buf.getInt(tupleCountOff);
+		if (tupleCount > 0) {
+			// return the last page from the linked list of free pages
+			// TODO: this is a dumb policy, but good enough for now
+			int lastPageOff = buf.getInt(freeSpaceOff) - 4;
+			buf.putInt(freeSpaceOff, lastPageOff);
+			buf.putInt(tupleCountOff, tupleCount - 1);
+			return buf.getInt(lastPageOff);
+		} else {
+			return -1;
+		}
+	}
 
-    // must be checked before adding free page
-    // user of this class is responsible for getting a free page as a new meta
-    // page, latching it, etc. if there is no space on this page
-    public boolean hasSpace() {
-        return buf.getInt(freeSpaceOff) + 4 < buf.capacity();
-    }
+	// must be checked before adding free page
+	// user of this class is responsible for getting a free page as a new meta
+	// page, latching it, etc. if there is no space on this page
+	public boolean hasSpace() {
+		return buf.getInt(freeSpaceOff) + 4 < buf.capacity();
+	}
 
-    // on bounds checking is done, there must be free space
-    public void addFreePage(int freePage) {
-        int freeSpace = buf.getInt(freeSpaceOff);
-        buf.putInt(freeSpace, freePage);
-        buf.putInt(freeSpaceOff, freeSpace + 4);
-        buf.putInt(tupleCountOff, buf.getInt(tupleCountOff) + 1);
-    }
+	// on bounds checking is done, there must be free space
+	public void addFreePage(int freePage) {
+		int freeSpace = buf.getInt(freeSpaceOff);
+		buf.putInt(freeSpace, freePage);
+		buf.putInt(freeSpaceOff, freeSpace + 4);
+		buf.putInt(tupleCountOff, buf.getInt(tupleCountOff) + 1);
+	}
 
-    @Override
-    public byte getLevel() {
-        return buf.get(levelOff);
-    }
+	@Override
+	public byte getLevel() {
+		return buf.get(levelOff);
+	}
 
-    @Override
-    public void setLevel(byte level) {
-        buf.put(levelOff, level);
-    }
+	@Override
+	public void setLevel(byte level) {
+		buf.put(levelOff, level);
+	}
 
-    @Override
-    public ICachedPage getPage() {
-        return page;
-    }
+	@Override
+	public ICachedPage getPage() {
+		return page;
+	}
 
-    @Override
-    public void setPage(ICachedPage page) {
-        this.page = page;
-        this.buf = page.getBuffer();
-    }
+	@Override
+	public void setPage(ICachedPage page) {
+		this.page = page;
+		this.buf = page.getBuffer();
+	}
 
-    @Override
-    public void initBuffer(int level) {
-        buf.putInt(freeSpaceOff, nextPageOff + 4);
-        buf.putInt(tupleCountOff, 0);
-        buf.putInt(levelOff, level);
-        buf.putInt(nextPageOff, -1);
-    }
+	@Override
+	public void initBuffer(byte level) {
+		buf.putInt(tupleCountOff, 0);
+		buf.putInt(freeSpaceOff, nextPageOff + 4);
+		//buf.putInt(maxPageOff, -1);
+		buf.put(levelOff, level);
+		buf.putInt(nextPageOff, -1);
+	}
 
-    @Override
-    public int getNextPage() {
-        return buf.getInt(nextPageOff);
-    }
+	@Override
+	public int getNextPage() {
+		return buf.getInt(nextPageOff);
+	}
 
-    @Override
-    public void setNextPage(int nextPage) {
-        buf.putInt(nextPageOff, nextPage);
-    }
+	@Override
+	public void setNextPage(int nextPage) {
+		buf.putInt(nextPageOff, nextPage);
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java
index 409c8b2..68d1ee3 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java
@@ -19,8 +19,8 @@
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrameFactory;
 
 public class LIFOMetaDataFrameFactory implements ITreeIndexMetaDataFrameFactory {
-    @Override
-    public ITreeIndexMetaDataFrame createFrame() {
-        return new LIFOMetaDataFrame();
-    }
+	@Override
+	public ITreeIndexMetaDataFrame createFrame() {
+		return new LIFOMetaDataFrame();
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java
index e6e08ef..e2e28fd 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java
@@ -15,35 +15,26 @@
 
 package edu.uci.ics.hyracks.storage.am.common.frames;
 
-import java.io.ByteArrayInputStream;
-import java.io.DataInput;
-import java.io.DataInputStream;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
 
-import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
-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.ISlotManager;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleReference;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleWriter;
-import edu.uci.ics.hyracks.storage.am.common.api.TreeIndexException;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.FindTupleMode;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.FindTupleNoExactMatchPolicy;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.SlotOffTupleOff;
 import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
 
 public abstract class TreeIndexNSMFrame implements ITreeIndexFrame {
 
     protected static final int pageLsnOff = 0; // 0
-    protected static final int tupleCountOff = pageLsnOff + 4; // 4
-    protected static final int freeSpaceOff = tupleCountOff + 4; // 8
+    protected static final int tupleCountOff = pageLsnOff + 8; // 8
+    protected static final int freeSpaceOff = tupleCountOff + 4; // 12
     protected static final int totalFreeSpaceOff = freeSpaceOff + 4; // 16
-    protected static final byte levelOff = totalFreeSpaceOff + 4;
-    protected static final byte smFlagOff = levelOff + 1;
+    protected static final int levelOff = totalFreeSpaceOff + 4; // 20
+    protected static final int smFlagOff = levelOff + 1; // 21
 
     protected ICachedPage page = null;
     protected ByteBuffer buf = null;
@@ -56,11 +47,12 @@
         this.tupleWriter = tupleWriter;
         this.frameTuple = tupleWriter.createTupleReference();
         this.slotManager = slotManager;
+        this.slotManager.setFrame(this);
     }
 
     @Override
     public void initBuffer(byte level) {
-        buf.putInt(pageLsnOff, 0); // TODO: might to set to a different lsn
+        buf.putLong(pageLsnOff, 0); // TODO: might to set to a different lsn
         // during creation
         buf.putInt(tupleCountOff, 0);
         resetSpaceParams();
@@ -89,19 +81,6 @@
     }
 
     @Override
-    public boolean getSmFlag() {
-        return buf.get(smFlagOff) != 0;
-    }
-
-    @Override
-    public void setSmFlag(boolean smFlag) {
-        if (smFlag)
-            buf.put(smFlagOff, (byte) 1);
-        else
-            buf.put(smFlagOff, (byte) 0);
-    }
-
-    @Override
     public int getFreeSpaceOff() {
         return buf.getInt(freeSpaceOff);
     }
@@ -115,7 +94,6 @@
     public void setPage(ICachedPage page) {
         this.page = page;
         this.buf = page.getBuffer();
-        slotManager.setFrame(this);
     }
 
     @Override
@@ -129,13 +107,11 @@
     }
 
     @Override
-    public boolean compact(MultiComparator cmp) {
+    public boolean compact() {
         resetSpaceParams();
-        frameTuple.setFieldCount(cmp.getFieldCount());
-
         int tupleCount = buf.getInt(tupleCountOff);
         int freeSpace = buf.getInt(freeSpaceOff);
-
+		// Sort the slots by the tuple offset they point to.
         ArrayList<SlotOffTupleOff> sortedTupleOffs = new ArrayList<SlotOffTupleOff>();
         sortedTupleOffs.ensureCapacity(tupleCount);
         for (int i = 0; i < tupleCount; i++) {
@@ -144,80 +120,75 @@
             sortedTupleOffs.add(new SlotOffTupleOff(i, slotOff, tupleOff));
         }
         Collections.sort(sortedTupleOffs);
-
+        // Iterate over the sorted slots, and move their corresponding tuples to
+     	// the left, reclaiming free space.
         for (int i = 0; i < sortedTupleOffs.size(); i++) {
             int tupleOff = sortedTupleOffs.get(i).tupleOff;
             frameTuple.resetByTupleOffset(buf, tupleOff);
-
             int tupleEndOff = frameTuple.getFieldStart(frameTuple.getFieldCount() - 1)
                     + frameTuple.getFieldLength(frameTuple.getFieldCount() - 1);
             int tupleLength = tupleEndOff - tupleOff;
             System.arraycopy(buf.array(), tupleOff, buf.array(), freeSpace, tupleLength);
-
             slotManager.setSlot(sortedTupleOffs.get(i).slotOff, freeSpace);
             freeSpace += tupleLength;
         }
-
+		// Update contiguous free space pointer and total free space indicator.
         buf.putInt(freeSpaceOff, freeSpace);
         buf.putInt(totalFreeSpaceOff, buf.capacity() - freeSpace - tupleCount * slotManager.getSlotSize());
-
         return false;
     }
 
     @Override
-    public void delete(ITupleReference tuple, MultiComparator cmp, boolean exactDelete) throws Exception {
-
-        frameTuple.setFieldCount(cmp.getFieldCount());
-        int tupleIndex = slotManager.findTupleIndex(tuple, frameTuple, cmp, FindTupleMode.FTM_EXACT,
-                FindTupleNoExactMatchPolicy.FTP_HIGHER_KEY);
+    public void delete(ITupleReference tuple, int tupleIndex) {
         int slotOff = slotManager.getSlotOff(tupleIndex);
-        if (tupleIndex < 0) {
-            throw new TreeIndexException("Key to be deleted does not exist.");
-        } else {
-            if (exactDelete) {
-                // check the non-key columns for equality by byte-by-byte
-                // comparison
-                int tupleOff = slotManager.getTupleOff(slotOff);
-                frameTuple.resetByTupleOffset(buf, tupleOff);
+        int tupleOff = slotManager.getTupleOff(slotOff);
+        frameTuple.resetByTupleOffset(buf, tupleOff);
+        int tupleSize = tupleWriter.bytesRequired(frameTuple);
 
-                int comparison = cmp.fieldRangeCompare(tuple, frameTuple, cmp.getKeyFieldCount() - 1,
-                        cmp.getFieldCount() - cmp.getKeyFieldCount());
-                if (comparison != 0) {
-                    throw new TreeIndexException(
-                            "Cannot delete tuple. Byte-by-byte comparison failed to prove equality.");
-                }
-            }
+        // perform deletion (we just do a memcpy to overwrite the slot)
+        int slotStartOff = slotManager.getSlotEndOff();
+        int length = slotOff - slotStartOff;
+        System.arraycopy(buf.array(), slotStartOff, buf.array(), slotStartOff + slotManager.getSlotSize(), length);
 
-            int tupleOff = slotManager.getTupleOff(slotOff);
-            frameTuple.resetByTupleOffset(buf, tupleOff);
-            int tupleSize = tupleWriter.bytesRequired(frameTuple);
-
-            // perform deletion (we just do a memcpy to overwrite the slot)
-            int slotStartOff = slotManager.getSlotEndOff();
-            int length = slotOff - slotStartOff;
-            System.arraycopy(buf.array(), slotStartOff, buf.array(), slotStartOff + slotManager.getSlotSize(), length);
-
-            // maintain space information
-            buf.putInt(tupleCountOff, buf.getInt(tupleCountOff) - 1);
-            buf.putInt(totalFreeSpaceOff, buf.getInt(totalFreeSpaceOff) + tupleSize + slotManager.getSlotSize());
-        }
+        // maintain space information
+        buf.putInt(tupleCountOff, buf.getInt(tupleCountOff) - 1);
+        buf.putInt(totalFreeSpaceOff, buf.getInt(totalFreeSpaceOff) + tupleSize + slotManager.getSlotSize());
     }
 
     @Override
-    public FrameOpSpaceStatus hasSpaceInsert(ITupleReference tuple, MultiComparator cmp) {
+    public FrameOpSpaceStatus hasSpaceInsert(ITupleReference tuple) {
         int bytesRequired = tupleWriter.bytesRequired(tuple);
-        if (bytesRequired + slotManager.getSlotSize() <= buf.capacity() - buf.getInt(freeSpaceOff)
-                - (buf.getInt(tupleCountOff) * slotManager.getSlotSize()))
+        // Enough space in the contiguous space region?
+        if (bytesRequired + slotManager.getSlotSize() <= buf.capacity() - buf.getInt(freeSpaceOff) 
+                - (buf.getInt(tupleCountOff) * slotManager.getSlotSize())) {
             return FrameOpSpaceStatus.SUFFICIENT_CONTIGUOUS_SPACE;
-        else if (bytesRequired + slotManager.getSlotSize() <= buf.getInt(totalFreeSpaceOff))
+        }
+        // Enough space after compaction?
+        if (bytesRequired + slotManager.getSlotSize() <= buf.getInt(totalFreeSpaceOff)) {
             return FrameOpSpaceStatus.SUFFICIENT_SPACE;
-        else
-            return FrameOpSpaceStatus.INSUFFICIENT_SPACE;
+        }
+        return FrameOpSpaceStatus.INSUFFICIENT_SPACE;
     }
 
     @Override
-    public FrameOpSpaceStatus hasSpaceUpdate(int rid, ITupleReference tuple, MultiComparator cmp) {
-        // TODO Auto-generated method stub
+    public FrameOpSpaceStatus hasSpaceUpdate(ITupleReference newTuple, int oldTupleIndex) {
+    	frameTuple.resetByTupleIndex(this, oldTupleIndex);
+    	int oldTupleBytes = frameTuple.getTupleSize();
+    	int newTupleBytes = tupleWriter.bytesRequired(newTuple);
+    	int additionalBytesRequired = newTupleBytes - oldTupleBytes;
+    	// Enough space for an in-place update?
+    	if (additionalBytesRequired <= 0) {
+    		return FrameOpSpaceStatus.SUFFICIENT_INPLACE_SPACE;
+    	}
+    	// Enough space if we delete the old tuple and insert the new one without compaction? 
+    	if (newTupleBytes <= buf.capacity() - buf.getInt(freeSpaceOff)
+                - (buf.getInt(tupleCountOff) * slotManager.getSlotSize())) {
+    		return FrameOpSpaceStatus.SUFFICIENT_CONTIGUOUS_SPACE;
+    	}
+    	// Enough space if we delete the old tuple and compact?
+    	if (additionalBytesRequired <= buf.getInt(totalFreeSpaceOff)) {
+    		return FrameOpSpaceStatus.SUFFICIENT_SPACE;
+    	}
         return FrameOpSpaceStatus.INSUFFICIENT_SPACE;
     }
 
@@ -227,14 +198,7 @@
     }
 
     @Override
-    public int findTupleIndex(ITupleReference tuple, MultiComparator cmp) throws Exception {
-        frameTuple.setFieldCount(cmp.getFieldCount());
-        return slotManager.findTupleIndex(tuple, frameTuple, cmp, FindTupleMode.FTM_INCLUSIVE,
-                FindTupleNoExactMatchPolicy.FTP_HIGHER_KEY);
-    }
-
-    @Override
-    public void insert(ITupleReference tuple, MultiComparator cmp, int tupleIndex) throws Exception {
+    public void insert(ITupleReference tuple, int tupleIndex) {
         slotManager.insertSlot(tupleIndex, buf.getInt(freeSpaceOff));
         int bytesWritten = tupleWriter.writeTuple(tuple, buf.array(), buf.getInt(freeSpaceOff));
         buf.putInt(tupleCountOff, buf.getInt(tupleCountOff) + 1);
@@ -243,15 +207,36 @@
     }
 
     @Override
-    public void update(int rid, ITupleReference tuple) throws Exception {
-        // TODO Auto-generated method stub
-
+    public void update(ITupleReference newTuple, int oldTupleIndex, boolean inPlace) {
+    	frameTuple.resetByTupleIndex(this, oldTupleIndex);
+		int oldTupleBytes = frameTuple.getTupleSize();
+		int slotOff = slotManager.getSlotOff(oldTupleIndex);
+		int bytesWritten = 0;
+    	if (inPlace) {    		
+    		// Overwrite the old tuple in place.
+    		bytesWritten = tupleWriter.writeTuple(newTuple, buf.array(), buf.getInt(slotOff));
+    	} else {
+    		// Insert the new tuple at the end of the free space, and change the slot value (effectively "deleting" the old tuple).
+    		int newTupleOff = buf.getInt(freeSpaceOff);
+    		bytesWritten = tupleWriter.writeTuple(newTuple, buf.array(), newTupleOff);
+    		// Update slot value.
+    		buf.putInt(slotOff, newTupleOff);
+    		// Update contiguous free space pointer.
+    		buf.putInt(freeSpaceOff, newTupleOff + bytesWritten);
+    	}
+    	buf.putInt(totalFreeSpaceOff, buf.getInt(totalFreeSpaceOff) + oldTupleBytes - bytesWritten);
     }
 
     @Override
-    public void printHeader() {
-        // TODO Auto-generated method stub
-
+    public String printHeader() {
+    	StringBuilder strBuilder = new StringBuilder();
+    	strBuilder.append("pageLsnOff:        " + pageLsnOff + "\n");
+    	strBuilder.append("tupleCountOff:     " + tupleCountOff + "\n");
+    	strBuilder.append("freeSpaceOff:      " + freeSpaceOff + "\n");
+    	strBuilder.append("totalFreeSpaceOff: " + totalFreeSpaceOff + "\n");
+    	strBuilder.append("levelOff:          " + levelOff + "\n");
+    	strBuilder.append("smFlagOff:         " + smFlagOff + "\n");
+    	return strBuilder.toString();
     }
 
     @Override
@@ -264,38 +249,18 @@
     }
 
     @Override
-    public String printKeys(MultiComparator cmp, ISerializerDeserializer[] fields) throws HyracksDataException {
-        StringBuilder strBuilder = new StringBuilder();
-        int tupleCount = buf.getInt(tupleCountOff);
-        frameTuple.setFieldCount(fields.length);
-        for (int i = 0; i < tupleCount; i++) {
-            frameTuple.resetByTupleIndex(this, i);
-            for (int j = 0; j < cmp.getKeyFieldCount(); j++) {
-                ByteArrayInputStream inStream = new ByteArrayInputStream(frameTuple.getFieldData(j),
-                        frameTuple.getFieldStart(j), frameTuple.getFieldLength(j));
-                DataInput dataIn = new DataInputStream(inStream);
-                Object o = fields[j].deserialize(dataIn);
-                strBuilder.append(o.toString() + " ");
-            }
-            strBuilder.append(" | ");
-        }
-        strBuilder.append("\n");
-        return strBuilder.toString();
-    }
-
-    @Override
     public int getTupleOffset(int slotNum) {
         return slotManager.getTupleOff(slotManager.getSlotStartOff() - slotNum * slotManager.getSlotSize());
     }
 
     @Override
-    public int getPageLsn() {
-        return buf.getInt(pageLsnOff);
+    public long getPageLsn() {
+        return buf.getLong(pageLsnOff);
     }
 
     @Override
-    public void setPageLsn(int pageLsn) {
-        buf.putInt(pageLsnOff, pageLsn);
+    public void setPageLsn(long pageLsn) {
+        buf.putLong(pageLsnOff, pageLsn);
     }
 
     @Override
@@ -304,7 +269,7 @@
     }
 
     @Override
-    public boolean compress(MultiComparator cmp) {
+    public boolean compress() {
         return false;
     }
 
@@ -314,11 +279,17 @@
     }
 
     @Override
-    public void setPageTupleFieldCount(int fieldCount) {
-        frameTuple.setFieldCount(fieldCount);
-    }
-
     public ITreeIndexTupleWriter getTupleWriter() {
         return tupleWriter;
     }
+    
+    @Override
+    public ITreeIndexTupleReference createTupleReference() {
+    	return tupleWriter.createTupleReference();
+    }
+    
+	public int getFreeContiguousSpace() {
+		return buf.capacity() - getFreeSpaceOff()
+				- (getTupleCount() * slotManager.getSlotSize());
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/freepage/LinkedListFreePageManager.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/freepage/LinkedListFreePageManager.java
index 42bf70f..f7e2e3b 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/freepage/LinkedListFreePageManager.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/freepage/LinkedListFreePageManager.java
@@ -10,178 +10,193 @@
 
 public class LinkedListFreePageManager implements IFreePageManager {
 
-    private static final byte META_PAGE_LEVEL_INDICATOR = -1;
-    private static final byte FREE_PAGE_LEVEL_INDICATOR = -2;
-    private final IBufferCache bufferCache;
-    private final int fileId;
-    private final int headPage;
-    private final ITreeIndexMetaDataFrameFactory metaDataFrameFactory;
+	private static final byte META_PAGE_LEVEL_INDICATOR = -1;
+	private static final byte FREE_PAGE_LEVEL_INDICATOR = -2;
+	private final IBufferCache bufferCache;
+	private final int fileId;
+	private final int headPage;
+	private final ITreeIndexMetaDataFrameFactory metaDataFrameFactory;
 
-    public LinkedListFreePageManager(IBufferCache bufferCache, int fileId, int headPage,
-            ITreeIndexMetaDataFrameFactory metaDataFrameFactory) {
-        this.bufferCache = bufferCache;
-        this.fileId = fileId;
-        this.headPage = headPage;
-        this.metaDataFrameFactory = metaDataFrameFactory;
-    }
+	public LinkedListFreePageManager(IBufferCache bufferCache, int fileId,
+			int headPage, ITreeIndexMetaDataFrameFactory metaDataFrameFactory) {
+		this.bufferCache = bufferCache;
+		this.fileId = fileId;
+		this.headPage = headPage;
+		this.metaDataFrameFactory = metaDataFrameFactory;
+	}
 
-    @Override
-    public void addFreePage(ITreeIndexMetaDataFrame metaFrame, int freePage) throws HyracksDataException {
+	@Override
+	public void addFreePage(ITreeIndexMetaDataFrame metaFrame, int freePage)
+			throws HyracksDataException {
 
-        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, headPage), false);
-        metaNode.acquireWriteLatch();
+		ICachedPage metaNode = bufferCache.pin(
+				BufferedFileHandle.getDiskPageId(fileId, headPage), false);
+		metaNode.acquireWriteLatch();
 
-        try {
-            metaFrame.setPage(metaNode);
+		try {
+			metaFrame.setPage(metaNode);
 
-            if (metaFrame.hasSpace()) {
-                metaFrame.addFreePage(freePage);
-            } else {
-                // allocate a new page in the chain of meta pages
-                int newPage = metaFrame.getFreePage();
-                if (newPage < 0) {
-                    throw new Exception("Inconsistent Meta Page State. It has no space, but it also has no entries.");
-                }
+			if (metaFrame.hasSpace()) {
+				metaFrame.addFreePage(freePage);
+			} else {
+				// allocate a new page in the chain of meta pages
+				int newPage = metaFrame.getFreePage();
+				if (newPage < 0) {
+					throw new Exception(
+							"Inconsistent Meta Page State. It has no space, but it also has no entries.");
+				}
 
-                ICachedPage newNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, newPage), false);
-                newNode.acquireWriteLatch();
+				ICachedPage newNode = bufferCache.pin(
+						BufferedFileHandle.getDiskPageId(fileId, newPage),
+						false);
+				newNode.acquireWriteLatch();
 
-                try {
-                    int metaMaxPage = metaFrame.getMaxPage();
+				try {
+					int metaMaxPage = metaFrame.getMaxPage();
 
-                    // copy metaDataPage to newNode
-                    System.arraycopy(metaNode.getBuffer().array(), 0, newNode.getBuffer().array(), 0, metaNode
-                            .getBuffer().capacity());
+					// copy metaDataPage to newNode
+					System.arraycopy(metaNode.getBuffer().array(), 0, newNode
+							.getBuffer().array(), 0, metaNode.getBuffer()
+							.capacity());
 
-                    metaFrame.initBuffer(META_PAGE_LEVEL_INDICATOR);
-                    metaFrame.setNextPage(newPage);
-                    metaFrame.setMaxPage(metaMaxPage);
-                    metaFrame.addFreePage(freePage);
-                } finally {
-                    newNode.releaseWriteLatch();
-                    bufferCache.unpin(newNode);
-                }
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        } finally {
-            metaNode.releaseWriteLatch();
-            bufferCache.unpin(metaNode);
-        }
-    }
+					metaFrame.initBuffer(META_PAGE_LEVEL_INDICATOR);
+					metaFrame.setNextPage(newPage);
+					metaFrame.setMaxPage(metaMaxPage);
+					metaFrame.addFreePage(freePage);
+				} finally {
+					newNode.releaseWriteLatch();
+					bufferCache.unpin(newNode);
+				}
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			metaNode.releaseWriteLatch();
+			bufferCache.unpin(metaNode);
+		}
+	}
 
-    @Override
-    public int getFreePage(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
-        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, headPage), false);
+	@Override
+	public int getFreePage(ITreeIndexMetaDataFrame metaFrame)
+			throws HyracksDataException {
+		ICachedPage metaNode = bufferCache.pin(
+				BufferedFileHandle.getDiskPageId(fileId, headPage), false);
 
-        metaNode.acquireWriteLatch();
+		metaNode.acquireWriteLatch();
 
-        int freePage = -1;
-        try {
-            metaFrame.setPage(metaNode);
-            freePage = metaFrame.getFreePage();
-            if (freePage < 0) { // no free page entry on this page
-                int nextPage = metaFrame.getNextPage();
-                if (nextPage > 0) { // sibling may have free pages
-                    ICachedPage nextNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, nextPage), false);
+		int freePage = -1;
+		try {
+			metaFrame.setPage(metaNode);
+			freePage = metaFrame.getFreePage();
+			if (freePage < 0) { // no free page entry on this page
+				int nextPage = metaFrame.getNextPage();
+				if (nextPage > 0) { // sibling may have free pages
+					ICachedPage nextNode = bufferCache.pin(
+							BufferedFileHandle.getDiskPageId(fileId, nextPage),
+							false);
 
-                    nextNode.acquireWriteLatch();
-                    // we copy over the free space entries of nextpage into the
-                    // first meta page (metaDataPage)
-                    // we need to link the first page properly to the next page
-                    // of nextpage
-                    try {
-                        // remember entries that remain unchanged
-                        int maxPage = metaFrame.getMaxPage();
+					nextNode.acquireWriteLatch();
+					// we copy over the free space entries of nextpage into the
+					// first meta page (metaDataPage)
+					// we need to link the first page properly to the next page
+					// of nextpage
+					try {
+						// remember entries that remain unchanged
+						int maxPage = metaFrame.getMaxPage();
 
-                        // copy entire page (including sibling pointer, free
-                        // page entries, and all other info)
-                        // after this copy nextPage is considered a free page
-                        System.arraycopy(nextNode.getBuffer().array(), 0, metaNode.getBuffer().array(), 0, nextNode
-                                .getBuffer().capacity());
+						// copy entire page (including sibling pointer, free
+						// page entries, and all other info)
+						// after this copy nextPage is considered a free page
+						System.arraycopy(nextNode.getBuffer().array(), 0,
+								metaNode.getBuffer().array(), 0, nextNode
+										.getBuffer().capacity());
 
-                        // reset unchanged entry
-                        metaFrame.setMaxPage(maxPage);
+						// reset unchanged entry
+						metaFrame.setMaxPage(maxPage);
 
-                        freePage = metaFrame.getFreePage();
-                        // sibling also has no free pages, this "should" not
-                        // happen, but we deal with it anyway just to be safe
-                        if (freePage < 0) {
-                            freePage = nextPage;
-                        } else {
-                            metaFrame.addFreePage(nextPage);
-                        }
-                    } finally {
-                        nextNode.releaseWriteLatch();
-                        bufferCache.unpin(nextNode);
-                    }
-                } else {
-                    freePage = metaFrame.getMaxPage();
-                    freePage++;
-                    metaFrame.setMaxPage(freePage);
-                }
-            }
-        } finally {
-            metaNode.releaseWriteLatch();
-            bufferCache.unpin(metaNode);
-        }
+						freePage = metaFrame.getFreePage();
+						// sibling also has no free pages, this "should" not
+						// happen, but we deal with it anyway just to be safe
+						if (freePage < 0) {
+							freePage = nextPage;
+						} else {
+							metaFrame.addFreePage(nextPage);
+						}
+					} finally {
+						nextNode.releaseWriteLatch();
+						bufferCache.unpin(nextNode);
+					}
+				} else {
+					freePage = metaFrame.getMaxPage();
+					freePage++;
+					metaFrame.setMaxPage(freePage);
+				}
+			}
+		} finally {
+			metaNode.releaseWriteLatch();
+			bufferCache.unpin(metaNode);
+		}
 
-        return freePage;
-    }
+		return freePage;
+	}
 
-    @Override
-    public int getMaxPage(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
-        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, headPage), false);
-        metaNode.acquireWriteLatch();
-        int maxPage = -1;
-        try {
-            metaFrame.setPage(metaNode);
-            maxPage = metaFrame.getMaxPage();
-        } finally {
-            metaNode.releaseWriteLatch();
-            bufferCache.unpin(metaNode);
-        }
-        return maxPage;
-    }
+	@Override
+	public int getMaxPage(ITreeIndexMetaDataFrame metaFrame)
+			throws HyracksDataException {
+		ICachedPage metaNode = bufferCache.pin(
+				BufferedFileHandle.getDiskPageId(fileId, headPage), false);
+		metaNode.acquireWriteLatch();
+		int maxPage = -1;
+		try {
+			metaFrame.setPage(metaNode);
+			maxPage = metaFrame.getMaxPage();
+		} finally {
+			metaNode.releaseWriteLatch();
+			bufferCache.unpin(metaNode);
+		}
+		return maxPage;
+	}
 
-    @Override
-    public void init(ITreeIndexMetaDataFrame metaFrame, int currentMaxPage) throws HyracksDataException {
-        // initialize meta data page
-        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, headPage), true);
+	@Override
+	public void init(ITreeIndexMetaDataFrame metaFrame, int currentMaxPage)
+			throws HyracksDataException {
+		// initialize meta data page
+		ICachedPage metaNode = bufferCache.pin(
+				BufferedFileHandle.getDiskPageId(fileId, headPage), true);
 
-        metaNode.acquireWriteLatch();
-        try {
-            metaFrame.setPage(metaNode);
-            metaFrame.initBuffer(META_PAGE_LEVEL_INDICATOR);
-            metaFrame.setMaxPage(currentMaxPage);
-        } finally {
-            metaNode.releaseWriteLatch();
-            bufferCache.unpin(metaNode);
-        }
-    }
+		metaNode.acquireWriteLatch();
+		try {
+			metaFrame.setPage(metaNode);
+			metaFrame.initBuffer(META_PAGE_LEVEL_INDICATOR);
+			metaFrame.setMaxPage(currentMaxPage);
+		} finally {
+			metaNode.releaseWriteLatch();
+			bufferCache.unpin(metaNode);
+		}
+	}
 
-    @Override
-    public ITreeIndexMetaDataFrameFactory getMetaDataFrameFactory() {
-        return metaDataFrameFactory;
-    }
+	@Override
+	public ITreeIndexMetaDataFrameFactory getMetaDataFrameFactory() {
+		return metaDataFrameFactory;
+	}
 
-    @Override
-    public byte getFreePageLevelIndicator() {
-        return FREE_PAGE_LEVEL_INDICATOR;
-    }
+	@Override
+	public byte getFreePageLevelIndicator() {
+		return FREE_PAGE_LEVEL_INDICATOR;
+	}
 
-    @Override
-    public byte getMetaPageLevelIndicator() {
-        return META_PAGE_LEVEL_INDICATOR;
-    }
+	@Override
+	public byte getMetaPageLevelIndicator() {
+		return META_PAGE_LEVEL_INDICATOR;
+	}
 
-    @Override
-    public boolean isFreePage(ITreeIndexMetaDataFrame metaFrame) {
-        return metaFrame.getLevel() == FREE_PAGE_LEVEL_INDICATOR;
-    }
+	@Override
+	public boolean isFreePage(ITreeIndexMetaDataFrame metaFrame) {
+		return metaFrame.getLevel() == FREE_PAGE_LEVEL_INDICATOR;
+	}
 
-    @Override
-    public boolean isMetaPage(ITreeIndexMetaDataFrame metaFrame) {
-        return metaFrame.getLevel() == META_PAGE_LEVEL_INDICATOR;
-    }
+	@Override
+	public boolean isMetaPage(ITreeIndexMetaDataFrame metaFrame) {
+		return metaFrame.getLevel() == META_PAGE_LEVEL_INDICATOR;
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/TreeDiskOrderScanCursor.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/TreeDiskOrderScanCursor.java
index 2c2cb5e..1a81c3f 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/TreeDiskOrderScanCursor.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/TreeDiskOrderScanCursor.java
@@ -21,130 +21,133 @@
 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.ITreeIndexTupleReference;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
 import edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle;
 
 public class TreeDiskOrderScanCursor implements ITreeIndexCursor {
 
-    private int tupleIndex = 0;
-    private int fileId = -1;
-    int currentPageId = -1;
-    int maxPageId = -1;
-    private ICachedPage page = null;
-    private ITreeIndexFrame frame = null;
-    private IBufferCache bufferCache = null;
+	private int tupleIndex = 0;
+	private int fileId = -1;
+	private int currentPageId = -1;
+	private int maxPageId = -1;
+	private ICachedPage page = null;	
+	private IBufferCache bufferCache = null;
+	
+	private final ITreeIndexFrame frame;
+	private final ITreeIndexTupleReference frameTuple;
+	
+	public TreeDiskOrderScanCursor(ITreeIndexFrame frame) {
+		this.frame = frame;		
+		this.frameTuple = frame.createTupleReference();
+	}
 
-    private ITreeIndexTupleReference frameTuple;
+	@Override
+	public void close() throws Exception {
+		page.releaseReadLatch();
+		bufferCache.unpin(page);
+		page = null;
+	}
 
-    public TreeDiskOrderScanCursor(ITreeIndexFrame frame) {
-        this.frame = frame;
-        this.frameTuple = frame.getTupleWriter().createTupleReference();
-    }
+	@Override
+	public ITreeIndexTupleReference getTuple() {
+		return frameTuple;
+	}
 
-    @Override
-    public void close() throws Exception {
-        page.releaseReadLatch();
-        bufferCache.unpin(page);
-        page = null;
-    }
+	@Override
+	public ICachedPage getPage() {
+		return page;
+	}
 
-    @Override
-    public ITreeIndexTupleReference getTuple() {
-        return frameTuple;
-    }
+	private boolean positionToNextLeaf(boolean skipCurrent)
+			throws HyracksDataException {
+		while ((frame.getLevel() != 0 || skipCurrent) && (currentPageId <= maxPageId)) {
+			currentPageId++;
 
-    @Override
-    public ICachedPage getPage() {
-        return page;
-    }
+			ICachedPage nextPage = bufferCache.pin(
+					BufferedFileHandle.getDiskPageId(fileId, currentPageId),
+					false);
+			nextPage.acquireReadLatch();
 
-    private boolean positionToNextLeaf(boolean skipCurrent) throws HyracksDataException {
-        while ((frame.getLevel() != 0 || skipCurrent) && (currentPageId <= maxPageId) || (frame.getTupleCount() == 0)) {
-            currentPageId++;
+			page.releaseReadLatch();
+			bufferCache.unpin(page);
 
-            ICachedPage nextPage = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, currentPageId), false);
-            nextPage.acquireReadLatch();
+			page = nextPage;
+			frame.setPage(page);
+			tupleIndex = 0;
+			skipCurrent = false;
+		}
+		if (currentPageId <= maxPageId)
+			return true;
+		else
+			return false;
+	}
 
-            page.releaseReadLatch();
-            bufferCache.unpin(page);
+	@Override
+	public boolean hasNext() throws Exception {		
+		if (currentPageId > maxPageId) {
+			return false;
+		}
+		if (tupleIndex >= frame.getTupleCount()) {
+			boolean nextLeafExists = positionToNextLeaf(true);
+			if (nextLeafExists) {
+				frameTuple.resetByTupleIndex(frame, tupleIndex);
+				return true;
+			} else {
+				return false;
+			}
+		}		
+		frameTuple.resetByTupleIndex(frame, tupleIndex);		
+		return true;
+	}
 
-            page = nextPage;
-            frame.setPage(page);
-            tupleIndex = 0;
-            skipCurrent = false;
-        }
-        if (currentPageId <= maxPageId)
-            return true;
-        else
-            return false;
-    }
+	@Override
+	public void next() throws Exception {
+		tupleIndex++;
+	}
 
-    @Override
-    public boolean hasNext() throws Exception {
-        if (tupleIndex >= frame.getTupleCount()) {
-            boolean nextLeafExists = positionToNextLeaf(true);
-            if (nextLeafExists) {
-                frameTuple.resetByTupleIndex(frame, tupleIndex);
-                return true;
-            } else {
-                return false;
-            }
-        }
+	@Override
+	public void open(ICursorInitialState initialState,
+			ISearchPredicate searchPred) throws HyracksDataException {
+		// in case open is called multiple times without closing
+		if (page != null) {
+			page.releaseReadLatch();
+			bufferCache.unpin(page);
+		}
+		page = initialState.getPage();
+		tupleIndex = 0;		
+		frame.setPage(page);
+		positionToNextLeaf(false);
+	}
 
-        frameTuple.resetByTupleIndex(frame, tupleIndex);
-        return true;
-    }
+	@Override
+	public void reset() {
+		tupleIndex = 0;
+		currentPageId = -1;
+		maxPageId = -1;
+		page = null;
+	}
 
-    @Override
-    public void next() throws Exception {
-        tupleIndex++;
-    }
+	@Override
+	public void setBufferCache(IBufferCache bufferCache) {
+		this.bufferCache = bufferCache;
+	}
 
-    @Override
-    public void open(ICursorInitialState initialState, ISearchPredicate searchPred) throws HyracksDataException {
-        // in case open is called multiple times without closing
-        if (page != null) {
-            page.releaseReadLatch();
-            bufferCache.unpin(page);
-        }
+	@Override
+	public void setFileId(int fileId) {
+		this.fileId = fileId;
+	}
 
-        page = initialState.getPage();
-        tupleIndex = 0;
-        frame.setPage(page);
-        MultiComparator lowKeyCmp = searchPred.getLowKeyComparator();
-        frameTuple.setFieldCount(lowKeyCmp.getFieldCount());
-        boolean leafExists = positionToNextLeaf(false);
-        if (!leafExists) {
-            throw new HyracksDataException(
-                    "Failed to open disk-order scan cursor for tree index. Traget tree index has no leaves.");
-        }
-    }
+	public void setCurrentPageId(int currentPageId) {
+		this.currentPageId = currentPageId;
+	}
 
-    @Override
-    public void reset() {
-        tupleIndex = 0;
-        currentPageId = -1;
-        maxPageId = -1;
-        page = null;
-    }
+	public void setMaxPageId(int maxPageId) {
+		this.maxPageId = maxPageId;
+	}
 
-    @Override
-    public void setBufferCache(IBufferCache bufferCache) {
-        this.bufferCache = bufferCache;
-    }
-
-    @Override
-    public void setFileId(int fileId) {
-        this.fileId = fileId;
-    }
-
-    public void setCurrentPageId(int currentPageId) {
-        this.currentPageId = currentPageId;
-    }
-
-    public void setMaxPageId(int maxPageId) {
-        this.maxPageId = maxPageId;
-    }
+	@Override
+	public boolean exclusiveLatchNodes() {
+		return false;
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleMode.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleMode.java
index cea2500..5002189 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleMode.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleMode.java
@@ -16,5 +16,5 @@
 package edu.uci.ics.hyracks.storage.am.common.ophelpers;
 
 public enum FindTupleMode {
-    FTM_INCLUSIVE, FTM_EXCLUSIVE, FTM_EXACT
+	INCLUSIVE, EXCLUSIVE, EXCLUSIVE_ERROR_IF_EXISTS, EXACT
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleNoExactMatchPolicy.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleNoExactMatchPolicy.java
index 0d534ed..8b3f7f5 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleNoExactMatchPolicy.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleNoExactMatchPolicy.java
@@ -16,5 +16,5 @@
 package edu.uci.ics.hyracks.storage.am.common.ophelpers;
 
 public enum FindTupleNoExactMatchPolicy {
-    FTP_LOWER_KEY, FTP_HIGHER_KEY
+	LOWER_KEY, HIGHER_KEY, NONE
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IndexOp.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IndexOp.java
index e40c5c8..780acd8 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IndexOp.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IndexOp.java
@@ -16,5 +16,5 @@
 package edu.uci.ics.hyracks.storage.am.common.ophelpers;
 
 public enum IndexOp {
-    INSERT, DELETE, UPDATE, SEARCH, DISKORDERSCAN
+	INSERT, DELETE, UPDATE, SEARCH, DISKORDERSCAN
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IndexOpContext.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IndexOpContext.java
deleted file mode 100644
index 4f6e656..0000000
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IndexOpContext.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package edu.uci.ics.hyracks.storage.am.common.ophelpers;
-
-public interface IndexOpContext {
-    void reset();
-}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IntArrayList.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IntArrayList.java
index 46551dd..d888aa0 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IntArrayList.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IntArrayList.java
@@ -16,74 +16,74 @@
 package edu.uci.ics.hyracks.storage.am.common.ophelpers;
 
 public class IntArrayList {
-    private int[] data;
-    private int size;
-    private int first;
-    private final int growth;
+	private int[] data;
+	private int size;
+	private int first;
+	private final int growth;
 
-    public IntArrayList(int initialCapacity, int growth) {
-        data = new int[initialCapacity];
-        size = 0;
-        first = 0;
-        this.growth = growth;
-    }
+	public IntArrayList(int initialCapacity, int growth) {
+		data = new int[initialCapacity];
+		size = 0;
+		first = 0;
+		this.growth = growth;
+	}
 
-    public int size() {
-        return size;
-    }
+	public int size() {
+		return size;
+	}
 
-    public int first() {
-        return first;
-    }
+	public int first() {
+		return first;
+	}
 
-    public void add(int i) {
-        if (size == data.length) {
-            int[] newData = new int[data.length + growth];
-            System.arraycopy(data, 0, newData, 0, data.length);
-            data = newData;
-        }
+	public void add(int i) {
+		if (size == data.length) {
+			int[] newData = new int[data.length + growth];
+			System.arraycopy(data, 0, newData, 0, data.length);
+			data = newData;
+		}
 
-        data[size++] = i;
-    }
+		data[size++] = i;
+	}
 
-    public void removeLast() {
-        if (size > 0)
-            size--;
-    }
+	public void removeLast() {
+		if (size > 0)
+			size--;
+	}
 
-    // WARNING: caller is responsible for checking size > 0
-    public int getLast() {
-        return data[size - 1];
-    }
+	// WARNING: caller is responsible for checking size > 0
+	public int getLast() {
+		return data[size - 1];
+	}
 
-    public int get(int i) {
-        return data[i];
-    }
+	public int get(int i) {
+		return data[i];
+	}
 
-    // WARNING: caller is responsible for checking i < size
-    public void set(int i, int value) {
-        data[i] = value;
+	// WARNING: caller is responsible for checking i < size
+	public void set(int i, int value) {
+		data[i] = value;
 
-    }
+	}
 
-    public int getFirst() {
-        return data[first];
-    }
+	public int getFirst() {
+		return data[first];
+	}
 
-    public void moveFirst() {
-        first++;
-    }
+	public void moveFirst() {
+		first++;
+	}
 
-    public void clear() {
-        size = 0;
-        first = 0;
-    }
+	public void clear() {
+		size = 0;
+		first = 0;
+	}
 
-    public boolean isLast() {
-        return size == first;
-    }
+	public boolean isLast() {
+		return size == first;
+	}
 
-    public boolean isEmpty() {
-        return size == 0;
-    }
+	public boolean isEmpty() {
+		return size == 0;
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/LongArrayList.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/LongArrayList.java
new file mode 100644
index 0000000..4dd1b5f
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/LongArrayList.java
@@ -0,0 +1,89 @@
+/*
+ * 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.common.ophelpers;
+
+public class LongArrayList {
+	private long[] data;
+	private int size;
+	private int first;
+	private final int growth;
+
+	public LongArrayList(int initialCapacity, int growth) {
+		data = new long[initialCapacity];
+		size = 0;
+		first = 0;
+		this.growth = growth;
+	}
+
+	public int size() {
+		return size;
+	}
+
+	public int first() {
+		return first;
+	}
+
+	public void add(long i) {
+		if (size == data.length) {
+			long[] newData = new long[data.length + growth];
+			System.arraycopy(data, 0, newData, 0, data.length);
+			data = newData;
+		}
+
+		data[size++] = i;
+	}
+
+	public void removeLast() {
+		if (size > 0)
+			size--;
+	}
+
+	// WARNING: caller is responsible for checking size > 0
+	public long getLast() {
+		return data[size - 1];
+	}
+
+	public long get(int i) {
+		return data[i];
+	}
+
+	// WARNING: caller is responsible for checking i < size
+	public void set(int i, long value) {
+		data[i] = value;
+
+	}
+
+	public long getFirst() {
+		return data[first];
+	}
+
+	public void moveFirst() {
+		first++;
+	}
+
+	public void clear() {
+		size = 0;
+		first = 0;
+	}
+
+	public boolean isLast() {
+		return size == first;
+	}
+
+	public boolean isEmpty() {
+		return size == 0;
+	}
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/MultiComparator.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/MultiComparator.java
index 07e3dfe..df24484 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/MultiComparator.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/MultiComparator.java
@@ -15,101 +15,51 @@
 
 package edu.uci.ics.hyracks.storage.am.common.ophelpers;
 
-import java.io.ByteArrayInputStream;
-import java.io.DataInput;
-import java.io.DataInputStream;
-
 import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparator;
-import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
-import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
-import edu.uci.ics.hyracks.dataflow.common.data.comparators.IntegerBinaryComparatorFactory;
-import edu.uci.ics.hyracks.storage.am.common.api.IPrimitiveValueProvider;
 
 public class MultiComparator {
 
-    private static final long serialVersionUID = 1L;
+	private final IBinaryComparator[] cmps;
 
-    private IBinaryComparator[] cmps = null;
-    private ITypeTrait[] typeTraits;
-    private IPrimitiveValueProvider[] valueProviders = null;
+	public MultiComparator(IBinaryComparator[] cmps) {
+		this.cmps = cmps;
+	}
 
-    private IBinaryComparator intCmp = IntegerBinaryComparatorFactory.INSTANCE.createBinaryComparator();
+	public int compare(ITupleReference tupleA, ITupleReference tupleB) {
+		for (int i = 0; i < cmps.length; i++) {
+			int cmp = cmps[i].compare(tupleA.getFieldData(i),
+					tupleA.getFieldStart(i), tupleA.getFieldLength(i),
+					tupleB.getFieldData(i), tupleB.getFieldStart(i),
+					tupleB.getFieldLength(i));
+			if (cmp < 0)
+				return -1;
+			else if (cmp > 0)
+				return 1;
+		}
+		return 0;
+	}
 
-    public IBinaryComparator getIntCmp() {
-        return intCmp;
-    }
+	public int fieldRangeCompare(ITupleReference tupleA,
+			ITupleReference tupleB, int startFieldIndex, int numFields) {
+		for (int i = startFieldIndex; i < startFieldIndex + numFields; i++) {
+			int cmp = cmps[i].compare(tupleA.getFieldData(i),
+					tupleA.getFieldStart(i), tupleA.getFieldLength(i),
+					tupleB.getFieldData(i), tupleB.getFieldStart(i),
+					tupleB.getFieldLength(i));
+			if (cmp < 0)
+				return -1;
+			else if (cmp > 0)
+				return 1;
+		}
+		return 0;
+	}
 
-    public MultiComparator(ITypeTrait[] typeTraits, IBinaryComparator[] cmps) {
-        this.typeTraits = typeTraits;
-        this.cmps = cmps;
-    }
+	public IBinaryComparator[] getComparators() {
+		return cmps;
+	}
 
-    public MultiComparator(ITypeTrait[] typeTraits, IBinaryComparator[] cmps, IPrimitiveValueProvider[] valueProviders) {
-        this.typeTraits = typeTraits;
-        this.cmps = cmps;
-        this.valueProviders = valueProviders;
-    }
-
-    public int compare(ITupleReference tupleA, ITupleReference tupleB) {
-        for (int i = 0; i < cmps.length; i++) {
-            int cmp = cmps[i].compare(tupleA.getFieldData(i), tupleA.getFieldStart(i), tupleA.getFieldLength(i),
-                    tupleB.getFieldData(i), tupleB.getFieldStart(i), tupleB.getFieldLength(i));
-            if (cmp < 0)
-                return -1;
-            else if (cmp > 0)
-                return 1;
-        }
-        return 0;
-    }
-
-    public int fieldRangeCompare(ITupleReference tupleA, ITupleReference tupleB, int startFieldIndex, int numFields) {
-        for (int i = startFieldIndex; i < startFieldIndex + numFields; i++) {
-            int cmp = cmps[i].compare(tupleA.getFieldData(i), tupleA.getFieldStart(i), tupleA.getFieldLength(i),
-                    tupleB.getFieldData(i), tupleB.getFieldStart(i), tupleB.getFieldLength(i));
-            if (cmp < 0)
-                return -1;
-            else if (cmp > 0)
-                return 1;
-        }
-        return 0;
-    }
-
-    public String printTuple(ITupleReference tuple, ISerializerDeserializer[] fields) throws HyracksDataException {
-        StringBuilder strBuilder = new StringBuilder();
-        for (int i = 0; i < tuple.getFieldCount(); i++) {
-            ByteArrayInputStream inStream = new ByteArrayInputStream(tuple.getFieldData(i), tuple.getFieldStart(i),
-                    tuple.getFieldLength(i));
-            DataInput dataIn = new DataInputStream(inStream);
-            Object o = fields[i].deserialize(dataIn);
-            strBuilder.append(o.toString() + " ");
-        }
-        return strBuilder.toString();
-    }
-
-    public IBinaryComparator[] getComparators() {
-        return cmps;
-    }
-
-    public int getKeyFieldCount() {
-        return cmps.length;
-    }
-
-    public void setComparators(IBinaryComparator[] cmps) {
-        this.cmps = cmps;
-    }
-
-    public int getFieldCount() {
-        return typeTraits.length;
-    }
-
-    public ITypeTrait[] getTypeTraits() {
-        return typeTraits;
-    }
-
-    public IPrimitiveValueProvider[] getValueProviders() {
-        return valueProviders;
-    }
-
-}
+	public int getKeyFieldCount() {
+		return cmps.length;
+	}
+}
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/SlotOffTupleOff.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/SlotOffTupleOff.java
index 4fc1861..7e9042c 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/SlotOffTupleOff.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/SlotOffTupleOff.java
@@ -16,18 +16,23 @@
 package edu.uci.ics.hyracks.storage.am.common.ophelpers;
 
 public class SlotOffTupleOff implements Comparable<SlotOffTupleOff> {
-    public int tupleIndex;
-    public int slotOff;
-    public int tupleOff;
+	public int tupleIndex;
+	public int slotOff;
+	public int tupleOff;
 
-    public SlotOffTupleOff(int tupleIndex, int slotOff, int recOff) {
-        this.tupleIndex = tupleIndex;
-        this.slotOff = slotOff;
-        this.tupleOff = recOff;
-    }
+	public SlotOffTupleOff(int tupleIndex, int slotOff, int recOff) {
+		this.tupleIndex = tupleIndex;
+		this.slotOff = slotOff;
+		this.tupleOff = recOff;
+	}
 
-    @Override
-    public int compareTo(SlotOffTupleOff o) {
-        return tupleOff - o.tupleOff;
-    }
+	@Override
+	public int compareTo(SlotOffTupleOff o) {
+		return tupleOff - o.tupleOff;
+	}
+	
+	@Override 
+	public String toString() {
+		return tupleIndex + " " + slotOff + " " + tupleOff;
+	}
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleReference.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleReference.java
index f9e00ac..a470d04 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleReference.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleReference.java
@@ -91,4 +91,9 @@
     protected int getFieldSlotsBytes() {
         return fieldCount * 2;
     }
+
+	@Override
+	public int getTupleSize() {
+		return nullFlagsBytes + fieldSlotsBytes + buf.getShort(tupleStartOff + nullFlagsBytes + (fieldCount-1) * 2);
+	}
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriter.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriter.java
index a47b6c3..831247e 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriter.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriter.java
@@ -23,6 +23,18 @@
 
 public class SimpleTupleWriter implements ITreeIndexTupleWriter {
 
+	// Write short in little endian to target byte array at given offset.
+	private static void writeShortL(short s, byte[] buf, int targetOff) {
+		buf[targetOff] = (byte)(s >> 8);
+		buf[targetOff + 1] = (byte)(s >> 0);
+	}
+	
+	// Write short in big endian to target byte array at given offset.
+	private static void writeShortB(short s, byte[] buf, int targetOff) {
+		buf[targetOff] = (byte) (s >> 0);
+		buf[targetOff + 1] = (byte) (s >> 8);
+	}
+	
     @Override
     public int bytesRequired(ITupleReference tuple) {
         int bytes = getNullFlagsBytes(tuple) + getFieldSlotsBytes(tuple);
@@ -48,31 +60,27 @@
 
     @Override
     public int writeTuple(ITupleReference tuple, ByteBuffer targetBuf, int targetOff) {
-        int runner = targetOff;
-        int nullFlagsBytes = getNullFlagsBytes(tuple);
-        int fieldSlotsBytes = getFieldSlotsBytes(tuple);
-        for (int i = 0; i < nullFlagsBytes; i++) {
-            targetBuf.put(runner++, (byte) 0);
-        }
-        runner += fieldSlotsBytes;
-
-        int fieldEndOff = 0;
-        for (int i = 0; i < tuple.getFieldCount(); i++) {
-            System.arraycopy(tuple.getFieldData(i), tuple.getFieldStart(i), targetBuf.array(), runner,
-                    tuple.getFieldLength(i));
-            fieldEndOff += tuple.getFieldLength(i);
-            runner += tuple.getFieldLength(i);
-            targetBuf.putShort(targetOff + nullFlagsBytes + i * 2, (short) fieldEndOff);
-        }
-
-        return runner - targetOff;
+        return writeTuple(tuple, targetBuf.array(), targetOff);
     }
     
     @Override
 	public int writeTuple(ITupleReference tuple, byte[] targetBuf, int targetOff) {
-		// TODO Implement this.
-    	System.out.println("IN HERE HUHUHU");
-		return -1;
+    	int runner = targetOff;
+        int nullFlagsBytes = getNullFlagsBytes(tuple);
+        int fieldSlotsBytes = getFieldSlotsBytes(tuple);
+        for (int i = 0; i < nullFlagsBytes; i++) {
+            targetBuf[runner++] = (byte) 0;
+        }
+        runner += fieldSlotsBytes;
+        int fieldEndOff = 0;
+        for (int i = 0; i < tuple.getFieldCount(); i++) {
+            System.arraycopy(tuple.getFieldData(i), tuple.getFieldStart(i), targetBuf, runner,
+                    tuple.getFieldLength(i));
+            fieldEndOff += tuple.getFieldLength(i);
+            runner += tuple.getFieldLength(i);
+            writeShortL((short) fieldEndOff, targetBuf, targetOff + nullFlagsBytes + i * 2);
+        }
+        return runner - targetOff;
 	}
 
     @Override
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriterFactory.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriterFactory.java
index ebb2905..10d4c3a 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriterFactory.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriterFactory.java
@@ -20,11 +20,11 @@
 
 public class SimpleTupleWriterFactory implements ITreeIndexTupleWriterFactory {
 
-    private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = 1L;
 
-    @Override
-    public ITreeIndexTupleWriter createTupleWriter() {
-        return new SimpleTupleWriter();
-    }
+	@Override
+	public ITreeIndexTupleWriter createTupleWriter() {
+		return new SimpleTupleWriter();
+	}
 
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleReference.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleReference.java
index 91ceee1..4776bdd 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleReference.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleReference.java
@@ -17,7 +17,7 @@
 
 import java.nio.ByteBuffer;
 
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleReference;
 
@@ -29,11 +29,11 @@
     protected int nullFlagsBytes;
     protected int dataStartOff;
 
-    protected ITypeTrait[] typeTraits;
+    protected ITypeTraits[] typeTraits;
     protected VarLenIntEncoderDecoder encDec = new VarLenIntEncoderDecoder();
     protected int[] decodedFieldSlots;
 
-    public TypeAwareTupleReference(ITypeTrait[] typeTraits) {
+    public TypeAwareTupleReference(ITypeTraits[] typeTraits) {
         this.typeTraits = typeTraits;
         this.fieldStartIndex = 0;
         setFieldCount(typeTraits.length);
@@ -50,12 +50,11 @@
         int end = fieldStartIndex + fieldCount;
         encDec.reset(buf.array(), tupleStartOff + nullFlagsBytes);
         for (int i = fieldStartIndex; i < end; i++) {
-            int staticDataLen = typeTraits[i].getStaticallyKnownDataLength();
-            if (staticDataLen == ITypeTrait.VARIABLE_LENGTH) {
+            if (!typeTraits[i].isFixedLength()) {
                 cumul += encDec.decode();
                 decodedFieldSlots[field++] = cumul;
             } else {
-                cumul += staticDataLen;
+                cumul += typeTraits[i].getFixedLength();
                 decodedFieldSlots[field++] = cumul;
             }
         }
@@ -118,4 +117,9 @@
     protected int getNullFlagsBytes() {
         return (int) Math.ceil(fieldCount / 8.0);
     }
+
+    @Override
+    public int getTupleSize() {
+        return dataStartOff - tupleStartOff + decodedFieldSlots[fieldCount - 1];
+    }
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriter.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriter.java
index 56c4d10..fe52608 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriter.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriter.java
@@ -17,17 +17,17 @@
 
 import java.nio.ByteBuffer;
 
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleReference;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleWriter;
 
 public class TypeAwareTupleWriter implements ITreeIndexTupleWriter {
 
-    protected ITypeTrait[] typeTraits;
+    protected ITypeTraits[] typeTraits;
     protected VarLenIntEncoderDecoder encDec = new VarLenIntEncoderDecoder();
 
-    public TypeAwareTupleWriter(ITypeTrait[] typeTraits) {
+    public TypeAwareTupleWriter(ITypeTraits[] typeTraits) {
         this.typeTraits = typeTraits;
     }
 
@@ -65,13 +65,13 @@
         int nullFlagsBytes = getNullFlagsBytes(tuple);
         // write null indicator bits
         for (int i = 0; i < nullFlagsBytes; i++) {
-        	targetBuf[runner++] = (byte) 0;
+            targetBuf[runner++] = (byte) 0;
         }
 
         // write field slots for variable length fields
         encDec.reset(targetBuf, runner);
         for (int i = 0; i < tuple.getFieldCount(); i++) {
-            if (typeTraits[i].getStaticallyKnownDataLength() == ITypeTrait.VARIABLE_LENGTH) {
+            if (!typeTraits[i].isFixedLength()) {
                 encDec.encode(tuple.getFieldLength(i));
             }
         }
@@ -79,14 +79,15 @@
 
         // write data fields
         for (int i = 0; i < tuple.getFieldCount(); i++) {
-            System.arraycopy(tuple.getFieldData(i), tuple.getFieldStart(i), targetBuf, runner,
-                    tuple.getFieldLength(i));
+            int s = tuple.getFieldStart(i);
+            int l = tuple.getFieldLength(i);
+            System.arraycopy(tuple.getFieldData(i), tuple.getFieldStart(i), targetBuf, runner, tuple.getFieldLength(i));
             runner += tuple.getFieldLength(i);
         }
 
         return runner - targetOff;
     }
-    
+
     @Override
     public int writeTupleFields(ITupleReference tuple, int startField, int numFields, ByteBuffer targetBuf,
             int targetOff) {
@@ -100,7 +101,7 @@
         // write field slots for variable length fields
         encDec.reset(targetBuf.array(), runner);
         for (int i = startField; i < startField + numFields; i++) {
-            if (typeTraits[i].getStaticallyKnownDataLength() == ITypeTrait.VARIABLE_LENGTH) {
+            if (!typeTraits[i].isFixedLength()) {
                 encDec.encode(tuple.getFieldLength(i));
             }
         }
@@ -122,7 +123,7 @@
     protected int getFieldSlotsBytes(ITupleReference tuple) {
         int fieldSlotBytes = 0;
         for (int i = 0; i < tuple.getFieldCount(); i++) {
-            if (typeTraits[i].getStaticallyKnownDataLength() == ITypeTrait.VARIABLE_LENGTH) {
+            if (!typeTraits[i].isFixedLength()) {
                 fieldSlotBytes += encDec.getBytesRequired(tuple.getFieldLength(i));
             }
         }
@@ -136,18 +137,18 @@
     protected int getFieldSlotsBytes(ITupleReference tuple, int startField, int numFields) {
         int fieldSlotBytes = 0;
         for (int i = startField; i < startField + numFields; i++) {
-            if (typeTraits[i].getStaticallyKnownDataLength() == ITypeTrait.VARIABLE_LENGTH) {
+            if (!typeTraits[i].isFixedLength()) {
                 fieldSlotBytes += encDec.getBytesRequired(tuple.getFieldLength(i));
             }
         }
         return fieldSlotBytes;
     }
 
-    public ITypeTrait[] getTypeTraits() {
+    public ITypeTraits[] getTypeTraits() {
         return typeTraits;
     }
 
-    public void setTypeTraits(ITypeTrait[] typeTraits) {
+    public void setTypeTraits(ITypeTraits[] typeTraits) {
         this.typeTraits = typeTraits;
     }
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriterFactory.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriterFactory.java
index 82072ae..9e6ba6f 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriterFactory.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriterFactory.java
@@ -15,22 +15,23 @@
 
 package edu.uci.ics.hyracks.storage.am.common.tuples;
 
-import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTraits;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleWriter;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleWriterFactory;
 
-public class TypeAwareTupleWriterFactory implements ITreeIndexTupleWriterFactory {
+public class TypeAwareTupleWriterFactory implements
+		ITreeIndexTupleWriterFactory {
 
-    private static final long serialVersionUID = 1L;
-    private ITypeTrait[] typeTraits;
+	private static final long serialVersionUID = 1L;
+	private ITypeTraits[] typeTraits;
 
-    public TypeAwareTupleWriterFactory(ITypeTrait[] typeTraits) {
-        this.typeTraits = typeTraits;
-    }
+	public TypeAwareTupleWriterFactory(ITypeTraits[] typeTraits) {
+		this.typeTraits = typeTraits;
+	}
 
-    @Override
-    public ITreeIndexTupleWriter createTupleWriter() {
-        return new TypeAwareTupleWriter(typeTraits);
-    }
+	@Override
+	public ITreeIndexTupleWriter createTupleWriter() {
+		return new TypeAwareTupleWriter(typeTraits);
+	}
 
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/VarLenIntEncoderDecoder.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/VarLenIntEncoderDecoder.java
index d266d41..979bbd3 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/VarLenIntEncoderDecoder.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/VarLenIntEncoderDecoder.java
@@ -18,71 +18,71 @@
 // encodes positive integers in a variable-byte format
 
 public class VarLenIntEncoderDecoder {
-    public static final int ENCODE_MASK = 0x0000007F;
-    public static final byte CONTINUE_CHUNK = (byte) 0x80;
-    public static final byte DECODE_MASK = (byte) 0x7F;
+	public static final int ENCODE_MASK = 0x0000007F;
+	public static final byte CONTINUE_CHUNK = (byte) 0x80;
+	public static final byte DECODE_MASK = (byte) 0x7F;
 
-    private byte[] encTmp = new byte[5];
+	private byte[] encTmp = new byte[5];
 
-    private int pos;
-    private byte[] bytes;
+	private int pos;
+	private byte[] bytes;
 
-    public void reset(byte[] bytes, int pos) {
-        this.bytes = bytes;
-        this.pos = pos;
-    }
+	public void reset(byte[] bytes, int pos) {
+		this.bytes = bytes;
+		this.pos = pos;
+	}
 
-    public int encode(int val) {
-        int origPos = 0;
-        int tmpPos = 0;
-        while (val > ENCODE_MASK) {
-            encTmp[tmpPos++] = (byte) (val & ENCODE_MASK);
-            val = val >>> 7;
-        }
-        encTmp[tmpPos++] = (byte) (val);
+	public int encode(int val) {
+		int origPos = 0;
+		int tmpPos = 0;
+		while (val > ENCODE_MASK) {
+			encTmp[tmpPos++] = (byte) (val & ENCODE_MASK);
+			val = val >>> 7;
+		}
+		encTmp[tmpPos++] = (byte) (val);
 
-        // reverse order to optimize for decoding speed
-        for (int i = 0; i < tmpPos - 1; i++) {
-            bytes[pos++] = (byte) (encTmp[tmpPos - 1 - i] | CONTINUE_CHUNK);
-        }
-        bytes[pos++] = encTmp[0];
+		// reverse order to optimize for decoding speed
+		for (int i = 0; i < tmpPos - 1; i++) {
+			bytes[pos++] = (byte) (encTmp[tmpPos - 1 - i] | CONTINUE_CHUNK);
+		}
+		bytes[pos++] = encTmp[0];
 
-        return pos - origPos;
-    }
+		return pos - origPos;
+	}
 
-    public int decode() {
-        int sum = 0;
-        while ((bytes[pos] & CONTINUE_CHUNK) == CONTINUE_CHUNK) {
-            sum = (sum + (bytes[pos] & DECODE_MASK)) << 7;
-            pos++;
-        }
-        sum += bytes[pos++];
-        return sum;
-    }
+	public int decode() {
+		int sum = 0;
+		while ((bytes[pos] & CONTINUE_CHUNK) == CONTINUE_CHUNK) {
+			sum = (sum + (bytes[pos] & DECODE_MASK)) << 7;
+			pos++;
+		}
+		sum += bytes[pos++];
+		return sum;
+	}
 
-    // calculate the number of bytes needed for encoding
-    public int getBytesRequired(int val) {
-        int byteCount = 0;
-        while (val > ENCODE_MASK) {
-            val = val >>> 7;
-            byteCount++;
-        }
-        return byteCount + 1;
-    }
+	// calculate the number of bytes needed for encoding
+	public int getBytesRequired(int val) {
+		int byteCount = 0;
+		while (val > ENCODE_MASK) {
+			val = val >>> 7;
+			byteCount++;
+		}
+		return byteCount + 1;
+	}
 
-    public int getPos() {
-        return pos;
-    }
+	public int getPos() {
+		return pos;
+	}
 
-    // fast encoding, slow decoding version
-    /*
-     * public void encode(int val) { while(val > ENCODE_MASK) { bytes[pos++] =
-     * (byte)(((byte)(val & ENCODE_MASK)) | CONTINUE_CHUNK); val = val >>> 7; }
-     * bytes[pos++] = (byte)(val); }
-     * 
-     * public int decode() { int sum = 0; int shift = 0; while( (bytes[pos] &
-     * CONTINUE_CHUNK) == CONTINUE_CHUNK) { sum = (sum + (bytes[pos] &
-     * DECODE_MASK)) << 7 * shift++; pos++; } sum += bytes[pos++] << 7 * shift;
-     * return sum; }
-     */
+	// fast encoding, slow decoding version
+	/*
+	 * public void encode(int val) { while(val > ENCODE_MASK) { bytes[pos++] =
+	 * (byte)(((byte)(val & ENCODE_MASK)) | CONTINUE_CHUNK); val = val >>> 7; }
+	 * bytes[pos++] = (byte)(val); }
+	 * 
+	 * public int decode() { int sum = 0; int shift = 0; while( (bytes[pos] &
+	 * CONTINUE_CHUNK) == CONTINUE_CHUNK) { sum = (sum + (bytes[pos] &
+	 * DECODE_MASK)) << 7 * shift++; pos++; } sum += bytes[pos++] << 7 * shift;
+	 * return sum; }
+	 */
 }
\ No newline at end of file
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/IndexUtils.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/IndexUtils.java
new file mode 100644
index 0000000..389855f
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/IndexUtils.java
@@ -0,0 +1,29 @@
+/*
+ * 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.common.util;
+
+import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparator;
+import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
+
+public class IndexUtils {
+	public static MultiComparator createMultiComparator(IBinaryComparatorFactory[] cmpFactories) {
+    	IBinaryComparator[] cmps = new IBinaryComparator[cmpFactories.length];
+    	for (int i = 0; i < cmpFactories.length; i++) {
+    		cmps[i] = cmpFactories[i].createBinaryComparator(); 
+    	}
+    	return new MultiComparator(cmps);
+    }
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexBufferCacheWarmup.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexBufferCacheWarmup.java
new file mode 100644
index 0000000..65ea8de
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexBufferCacheWarmup.java
@@ -0,0 +1,88 @@
+package edu.uci.ics.hyracks.storage.am.common.util;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.IntArrayList;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
+import edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle;
+
+public class TreeIndexBufferCacheWarmup {
+	private final IBufferCache bufferCache;
+	private final IFreePageManager freePageManager;
+	private final int fileId;
+	private final ArrayList<IntArrayList> pagesByLevel = new ArrayList<IntArrayList>();
+	private final Random rnd = new Random();
+
+	public TreeIndexBufferCacheWarmup(IBufferCache bufferCache,
+			IFreePageManager freePageManager, int fileId) {
+		this.bufferCache = bufferCache;
+		this.freePageManager = freePageManager;
+		this.fileId = fileId;
+	}
+
+	public void warmup(ITreeIndexFrame frame,
+			ITreeIndexMetaDataFrame metaFrame, int[] warmupTreeLevels,
+			int[] warmupRepeats) throws HyracksDataException {
+		bufferCache.openFile(fileId);
+
+		// scan entire file to determine pages in each level
+		int maxPageId = freePageManager.getMaxPage(metaFrame);
+		for (int pageId = 0; pageId <= maxPageId; pageId++) {
+			ICachedPage page = bufferCache.pin(
+					BufferedFileHandle.getDiskPageId(fileId, pageId), false);
+			page.acquireReadLatch();
+			try {
+				frame.setPage(page);
+				byte level = frame.getLevel();
+				while (level >= pagesByLevel.size()) {
+					pagesByLevel.add(new IntArrayList(100, 100));
+				}
+				if (level >= 0) {
+					// System.out.println("ADDING: " + level + " " + pageId);
+					pagesByLevel.get(level).add(pageId);
+				}
+			} finally {
+				page.releaseReadLatch();
+				bufferCache.unpin(page);
+			}
+		}
+
+		// pin certain pages again to simulate frequent access
+		for (int i = 0; i < warmupTreeLevels.length; i++) {
+			if (warmupTreeLevels[i] < pagesByLevel.size()) {
+				int repeats = warmupRepeats[i];
+				IntArrayList pageIds = pagesByLevel.get(warmupTreeLevels[i]);
+				int[] remainingPageIds = new int[pageIds.size()];
+				for (int r = 0; r < repeats; r++) {
+					for (int j = 0; j < pageIds.size(); j++) {
+						remainingPageIds[j] = pageIds.get(j);
+					}
+
+					int remainingLength = pageIds.size();
+					for (int j = 0; j < pageIds.size(); j++) {
+						int index = Math.abs(rnd.nextInt()) % remainingLength;
+						int pageId = remainingPageIds[index];
+
+						// pin & latch then immediately unlatch & unpin
+						ICachedPage page = bufferCache.pin(BufferedFileHandle
+								.getDiskPageId(fileId, pageId), false);
+						page.acquireReadLatch();
+						page.releaseReadLatch();
+						bufferCache.unpin(page);
+
+						remainingPageIds[index] = remainingPageIds[remainingLength - 1];
+						remainingLength--;
+					}
+				}
+			}
+		}
+
+		bufferCache.closeFile(fileId);
+	}
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexStats.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexStats.java
new file mode 100644
index 0000000..d5d9b5d
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexStats.java
@@ -0,0 +1,147 @@
+package edu.uci.ics.hyracks.storage.am.common.util;
+
+import java.text.DecimalFormat;
+
+import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
+
+public class TreeIndexStats {
+
+	private TreeIndexNodeTypeStats rootStats = new TreeIndexNodeTypeStats();
+	private TreeIndexNodeTypeStats interiorStats = new TreeIndexNodeTypeStats();
+	private TreeIndexNodeTypeStats leafStats = new TreeIndexNodeTypeStats();
+
+	private int freePages = 0;
+	private int metaPages = 0;
+	private int treeLevels = 0;
+
+	public void begin() {
+		rootStats.clear();
+		interiorStats.clear();
+		leafStats.clear();
+		freePages = 0;
+		metaPages = 0;
+		treeLevels = 0;
+	}
+
+	public void addRoot(ITreeIndexFrame frame) {
+		treeLevels = frame.getLevel() + 1;
+		rootStats.add(frame);
+	}
+
+	public void add(ITreeIndexFrame frame) {
+		if (frame.isLeaf()) {
+			leafStats.add(frame);
+		} else if (frame.isInterior()) {
+			interiorStats.add(frame);
+		}
+	}
+
+	public void add(ITreeIndexMetaDataFrame metaFrame,
+			IFreePageManager freePageManager) {
+		if (freePageManager.isFreePage(metaFrame)) {
+			freePages++;
+		} else if (freePageManager.isMetaPage(metaFrame)) {
+			metaPages++;
+		}
+	}
+
+	public void end() {
+		// nothing here currently
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder strBuilder = new StringBuilder();
+		DecimalFormat df = new DecimalFormat("#####.##");
+
+		strBuilder.append("TREE LEVELS:  " + treeLevels + "\n");
+		strBuilder.append("FREE PAGES :  " + freePages + "\n");
+		strBuilder.append("META PAGES :  " + metaPages + "\n");
+		long totalPages = interiorStats.getNumPages() + leafStats.getNumPages()
+				+ freePages + metaPages;
+		strBuilder.append("TOTAL PAGES : " + totalPages + "\n");
+
+		strBuilder.append("\n");
+		strBuilder.append("ROOT STATS" + "\n");
+		strBuilder
+				.append("NUM TUPLES:      " + rootStats.getNumTuples() + "\n");
+		strBuilder.append("FILL FACTOR    : "
+				+ df.format(rootStats.getAvgFillFactor()) + "\n");
+
+		if (interiorStats.getNumPages() > 0) {
+			strBuilder.append("\n");
+			strBuilder.append("INTERIOR STATS" + "\n");
+			strBuilder.append("NUM PAGES:       " + interiorStats.getNumPages()
+					+ "\n");
+			strBuilder.append("NUM TUPLES:      "
+					+ interiorStats.getNumTuples() + "\n");
+			strBuilder.append("AVG TUPLES/PAGE: "
+					+ df.format(interiorStats.getAvgNumTuples()) + "\n");
+			strBuilder.append("AVG FILL FACTOR: "
+					+ df.format(interiorStats.getAvgFillFactor()) + "\n");
+		}
+
+		if (leafStats.getNumPages() > 0) {
+			strBuilder.append("\n");
+			strBuilder.append("LEAF STATS" + "\n");
+			strBuilder.append("NUM PAGES:       "
+					+ df.format(leafStats.getNumPages()) + "\n");
+			strBuilder.append("NUM TUPLES:      "
+					+ df.format(leafStats.getNumTuples()) + "\n");
+			strBuilder.append("AVG TUPLES/PAGE: "
+					+ df.format(leafStats.getAvgNumTuples()) + "\n");
+			strBuilder.append("AVG FILL FACTOR: "
+					+ df.format(leafStats.getAvgFillFactor()) + "\n");
+		}
+
+		return strBuilder.toString();
+	}
+
+	public class TreeIndexNodeTypeStats {
+		private long numTuples;
+		private long sumTuplesSizes;
+		private long numPages;
+		private double sumFillFactors;
+
+		public void clear() {
+			numTuples = 0;
+			sumTuplesSizes = 0;
+			numPages = 0;
+		}
+
+		public void add(ITreeIndexFrame frame) {
+			numPages++;
+			numTuples += frame.getTupleCount();
+			sumFillFactors += (double) (frame.getBuffer().capacity() - frame
+					.getTotalFreeSpace())
+					/ (double) frame.getBuffer().capacity();
+		}
+
+		public long getNumTuples() {
+			return numTuples;
+		}
+
+		public long getSumTupleSizes() {
+			return sumTuplesSizes;
+		}
+
+		public long getNumPages() {
+			return numPages;
+		}
+
+		public double getAvgNumTuples() {
+			return (double) numTuples / (double) numPages;
+		}
+
+		public double getAvgTupleSize() {
+			return (double) sumTuplesSizes / (double) numTuples;
+		}
+
+		public double getAvgFillFactor() {
+			return sumFillFactors / numPages;
+		}
+	}
+
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexStatsGatherer.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexStatsGatherer.java
new file mode 100644
index 0000000..eeacccd
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexStatsGatherer.java
@@ -0,0 +1,73 @@
+package edu.uci.ics.hyracks.storage.am.common.util;
+
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
+import edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle;
+
+public class TreeIndexStatsGatherer {
+
+	private final TreeIndexStats treeIndexStats = new TreeIndexStats();
+	private final IBufferCache bufferCache;
+	private final IFreePageManager freePageManager;
+	private final int fileId;
+	private final int rootPage;
+
+	public TreeIndexStatsGatherer(IBufferCache bufferCache,
+			IFreePageManager freePageManager, int fileId, int rootPage) {
+		this.bufferCache = bufferCache;
+		this.freePageManager = freePageManager;
+		this.fileId = fileId;
+		this.rootPage = rootPage;
+	}
+
+	public TreeIndexStats gatherStats(ITreeIndexFrame leafFrame,
+			ITreeIndexFrame interiorFrame, ITreeIndexMetaDataFrame metaFrame)
+			throws HyracksDataException {
+
+		bufferCache.openFile(fileId);
+
+		treeIndexStats.begin();
+
+		int maxPageId = freePageManager.getMaxPage(metaFrame);
+		for (int pageId = 0; pageId <= maxPageId; pageId++) {
+			ICachedPage page = bufferCache.pin(
+					BufferedFileHandle.getDiskPageId(fileId, pageId), false);
+			page.acquireReadLatch();
+			try {
+				metaFrame.setPage(page);
+				leafFrame.setPage(page);
+				interiorFrame.setPage(page);
+
+				if (leafFrame.isLeaf()) {
+					if (pageId == rootPage) {
+						treeIndexStats.addRoot(leafFrame);
+					} else {
+						treeIndexStats.add(leafFrame);
+					}
+				} else if (interiorFrame.isInterior()) {
+					if (pageId == rootPage) {
+						treeIndexStats.addRoot(interiorFrame);
+					} else {
+						treeIndexStats.add(interiorFrame);
+					}
+				} else {
+					treeIndexStats.add(metaFrame, freePageManager);
+				}
+
+			} finally {
+				page.releaseReadLatch();
+				bufferCache.unpin(page);
+			}
+		}
+
+		treeIndexStats.end();
+
+		bufferCache.closeFile(fileId);
+
+		return treeIndexStats;
+	}
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexUtils.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexUtils.java
new file mode 100644
index 0000000..a1e493d
--- /dev/null
+++ b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexUtils.java
@@ -0,0 +1,39 @@
+/*
+ * 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.common.util;
+
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.dataflow.common.util.TupleUtils;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleReference;
+
+@SuppressWarnings("rawtypes") 
+public class TreeIndexUtils {
+	public static String printFrameTuples(ITreeIndexFrame frame, ISerializerDeserializer[] fieldSerdes) throws HyracksDataException {		
+		StringBuilder strBuilder = new StringBuilder();
+		ITreeIndexTupleReference tuple = frame.createTupleReference();
+		for (int i = 0; i < frame.getTupleCount(); i++) {
+			tuple.resetByTupleIndex(frame, i);
+			String tupleString = TupleUtils.printTuple(tuple, fieldSerdes);
+			strBuilder.append(tupleString);
+			if (i != frame.getTupleCount() - 1) {
+				strBuilder.append(" | ");
+			}
+		}
+		return strBuilder.toString();
+    }
+}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexBufferCacheWarmup.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexBufferCacheWarmup.java
deleted file mode 100644
index eb261da..0000000
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexBufferCacheWarmup.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package edu.uci.ics.hyracks.storage.am.common.utility;
-
-import java.util.ArrayList;
-import java.util.Random;
-
-import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
-import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
-import edu.uci.ics.hyracks.storage.am.common.ophelpers.IntArrayList;
-import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
-import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
-import edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle;
-
-public class TreeIndexBufferCacheWarmup {
-    private final IBufferCache bufferCache;
-    private final IFreePageManager freePageManager;
-    private final int fileId;
-    private final ArrayList<IntArrayList> pagesByLevel = new ArrayList<IntArrayList>();
-    private final Random rnd = new Random();
-
-    public TreeIndexBufferCacheWarmup(IBufferCache bufferCache, IFreePageManager freePageManager, int fileId) {
-        this.bufferCache = bufferCache;
-        this.freePageManager = freePageManager;
-        this.fileId = fileId;
-    }
-
-    public void warmup(ITreeIndexFrame frame, ITreeIndexMetaDataFrame metaFrame, int[] warmupTreeLevels,
-            int[] warmupRepeats) throws HyracksDataException {
-        bufferCache.openFile(fileId);
-
-        // scan entire file to determine pages in each level
-        int maxPageId = freePageManager.getMaxPage(metaFrame);
-        for (int pageId = 0; pageId <= maxPageId; pageId++) {
-            ICachedPage page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, pageId), false);
-            page.acquireReadLatch();
-            try {
-                frame.setPage(page);
-                byte level = frame.getLevel();
-                while (level >= pagesByLevel.size()) {
-                    pagesByLevel.add(new IntArrayList(100, 100));
-                }
-                if (level >= 0) {
-                    // System.out.println("ADDING: " + level + " " + pageId);
-                    pagesByLevel.get(level).add(pageId);
-                }
-            } finally {
-                page.releaseReadLatch();
-                bufferCache.unpin(page);
-            }
-        }
-
-        // pin certain pages again to simulate frequent access
-        for (int i = 0; i < warmupTreeLevels.length; i++) {
-            if (warmupTreeLevels[i] < pagesByLevel.size()) {
-                int repeats = warmupRepeats[i];
-                IntArrayList pageIds = pagesByLevel.get(warmupTreeLevels[i]);
-                int[] remainingPageIds = new int[pageIds.size()];
-                for (int r = 0; r < repeats; r++) {
-                    for (int j = 0; j < pageIds.size(); j++) {
-                        remainingPageIds[j] = pageIds.get(j);
-                    }
-
-                    int remainingLength = pageIds.size();
-                    for (int j = 0; j < pageIds.size(); j++) {
-                        int index = Math.abs(rnd.nextInt()) % remainingLength;
-                        int pageId = remainingPageIds[index];
-
-                        // pin & latch then immediately unlatch & unpin
-                        ICachedPage page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, pageId), false);
-                        page.acquireReadLatch();
-                        page.releaseReadLatch();
-                        bufferCache.unpin(page);
-
-                        remainingPageIds[index] = remainingPageIds[remainingLength - 1];
-                        remainingLength--;
-                    }
-                }
-            }
-        }
-
-        bufferCache.closeFile(fileId);
-    }
-}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexStats.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexStats.java
deleted file mode 100644
index 5b01b2d..0000000
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexStats.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package edu.uci.ics.hyracks.storage.am.common.utility;
-
-import java.text.DecimalFormat;
-
-import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
-
-public class TreeIndexStats {
-
-    private TreeIndexNodeTypeStats rootStats = new TreeIndexNodeTypeStats();
-    private TreeIndexNodeTypeStats interiorStats = new TreeIndexNodeTypeStats();
-    private TreeIndexNodeTypeStats leafStats = new TreeIndexNodeTypeStats();
-
-    private int freePages = 0;
-    private int metaPages = 0;
-    private int treeLevels = 0;
-
-    public void begin() {
-        rootStats.clear();
-        interiorStats.clear();
-        leafStats.clear();
-        freePages = 0;
-        metaPages = 0;
-        treeLevels = 0;
-    }
-
-    public void addRoot(ITreeIndexFrame frame) {
-        treeLevels = frame.getLevel() + 1;
-        rootStats.add(frame);
-    }
-
-    public void add(ITreeIndexFrame frame) {
-        if (frame.isLeaf()) {
-            leafStats.add(frame);
-        } else if (frame.isInterior()) {
-            interiorStats.add(frame);
-        }
-    }
-
-    public void add(ITreeIndexMetaDataFrame metaFrame, IFreePageManager freePageManager) {
-        if (freePageManager.isFreePage(metaFrame)) {
-            freePages++;
-        } else if (freePageManager.isMetaPage(metaFrame)) {
-            metaPages++;
-        }
-    }
-
-    public void end() {
-        // nothing here currently
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder strBuilder = new StringBuilder();
-        DecimalFormat df = new DecimalFormat("#####.##");
-
-        strBuilder.append("TREE LEVELS:  " + treeLevels + "\n");
-        strBuilder.append("FREE PAGES :  " + freePages + "\n");
-        strBuilder.append("META PAGES :  " + metaPages + "\n");
-        long totalPages = interiorStats.getNumPages() + leafStats.getNumPages() + freePages + metaPages;
-        strBuilder.append("TOTAL PAGES : " + totalPages + "\n");
-
-        strBuilder.append("\n");
-        strBuilder.append("ROOT STATS" + "\n");
-        strBuilder.append("NUM TUPLES:      " + rootStats.getNumTuples() + "\n");
-        strBuilder.append("FILL FACTOR    : " + df.format(rootStats.getAvgFillFactor()) + "\n");
-
-        if (interiorStats.getNumPages() > 0) {
-            strBuilder.append("\n");
-            strBuilder.append("INTERIOR STATS" + "\n");
-            strBuilder.append("NUM PAGES:       " + interiorStats.getNumPages() + "\n");
-            strBuilder.append("NUM TUPLES:      " + interiorStats.getNumTuples() + "\n");
-            strBuilder.append("AVG TUPLES/PAGE: " + df.format(interiorStats.getAvgNumTuples()) + "\n");
-            strBuilder.append("AVG FILL FACTOR: " + df.format(interiorStats.getAvgFillFactor()) + "\n");
-        }
-
-        if (leafStats.getNumPages() > 0) {
-            strBuilder.append("\n");
-            strBuilder.append("LEAF STATS" + "\n");
-            strBuilder.append("NUM PAGES:       " + df.format(leafStats.getNumPages()) + "\n");
-            strBuilder.append("NUM TUPLES:      " + df.format(leafStats.getNumTuples()) + "\n");
-            strBuilder.append("AVG TUPLES/PAGE: " + df.format(leafStats.getAvgNumTuples()) + "\n");
-            strBuilder.append("AVG FILL FACTOR: " + df.format(leafStats.getAvgFillFactor()) + "\n");
-        }
-
-        return strBuilder.toString();
-    }
-
-    public class TreeIndexNodeTypeStats {
-        private long numTuples;
-        private long sumTuplesSizes;
-        private long numPages;
-        private double sumFillFactors;
-
-        public void clear() {
-            numTuples = 0;
-            sumTuplesSizes = 0;
-            numPages = 0;
-        }
-
-        public void add(ITreeIndexFrame frame) {
-            numPages++;
-            numTuples += frame.getTupleCount();
-            sumFillFactors += (double) (frame.getBuffer().capacity() - frame.getTotalFreeSpace())
-                    / (double) frame.getBuffer().capacity();
-        }
-
-        public long getNumTuples() {
-            return numTuples;
-        }
-
-        public long getSumTupleSizes() {
-            return sumTuplesSizes;
-        }
-
-        public long getNumPages() {
-            return numPages;
-        }
-
-        public double getAvgNumTuples() {
-            return (double) numTuples / (double) numPages;
-        }
-
-        public double getAvgTupleSize() {
-            return (double) sumTuplesSizes / (double) numTuples;
-        }
-
-        public double getAvgFillFactor() {
-            return sumFillFactors / numPages;
-        }
-    }
-
-}
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexStatsGatherer.java b/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexStatsGatherer.java
deleted file mode 100644
index fc0ab5e..0000000
--- a/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexStatsGatherer.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package edu.uci.ics.hyracks.storage.am.common.utility;
-
-import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
-import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
-import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
-import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
-import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
-import edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle;
-
-public class TreeIndexStatsGatherer {
-
-    private final TreeIndexStats treeIndexStats = new TreeIndexStats();
-    private final IBufferCache bufferCache;
-    private final IFreePageManager freePageManager;
-    private final int fileId;
-    private final int rootPage;
-
-    public TreeIndexStatsGatherer(IBufferCache bufferCache, IFreePageManager freePageManager, int fileId, int rootPage) {
-        this.bufferCache = bufferCache;
-        this.freePageManager = freePageManager;
-        this.fileId = fileId;
-        this.rootPage = rootPage;
-    }
-
-    public TreeIndexStats gatherStats(ITreeIndexFrame leafFrame, ITreeIndexFrame interiorFrame,
-            ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
-
-        bufferCache.openFile(fileId);
-
-        treeIndexStats.begin();
-
-        int maxPageId = freePageManager.getMaxPage(metaFrame);
-        for (int pageId = 0; pageId <= maxPageId; pageId++) {
-            ICachedPage page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, pageId), false);
-            page.acquireReadLatch();
-            try {
-                metaFrame.setPage(page);
-                leafFrame.setPage(page);
-                interiorFrame.setPage(page);
-
-                if (leafFrame.isLeaf()) {
-                    if (pageId == rootPage) {
-                        treeIndexStats.addRoot(leafFrame);
-                    } else {
-                        treeIndexStats.add(leafFrame);
-                    }
-                } else if (interiorFrame.isInterior()) {
-                    if (pageId == rootPage) {
-                        treeIndexStats.addRoot(interiorFrame);
-                    } else {
-                        treeIndexStats.add(interiorFrame);
-                    }
-                } else {
-                    treeIndexStats.add(metaFrame, freePageManager);
-                }
-
-            } finally {
-                page.releaseReadLatch();
-                bufferCache.unpin(page);
-            }
-        }
-
-        treeIndexStats.end();
-
-        bufferCache.closeFile(fileId);
-
-        return treeIndexStats;
-    }
-}