Merged fullstack_staging branch into trunk

git-svn-id: https://hyracks.googlecode.com/svn/trunk@2372 123451ca-8445-de46-9d55-352943316053
diff --git a/fullstack/hyracks/hyracks-storage-am-common/pom.xml b/fullstack/hyracks/hyracks-storage-am-common/pom.xml
new file mode 100644
index 0000000..f793bd6
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/pom.xml
@@ -0,0 +1,57 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>edu.uci.ics.hyracks</groupId>
+  <artifactId>hyracks-storage-am-common</artifactId>
+  <version>0.2.2-SNAPSHOT</version>
+  <name>hyracks-storage-am-common</name>
+
+  <parent>
+    <groupId>edu.uci.ics.hyracks</groupId>
+    <artifactId>hyracks</artifactId>
+    <version>0.2.2-SNAPSHOT</version>
+  </parent>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.0.2</version>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+  	<dependency>
+  		<groupId>edu.uci.ics.hyracks</groupId>
+  		<artifactId>hyracks-api</artifactId>
+  		<version>0.2.2-SNAPSHOT</version>
+  		<type>jar</type>
+  		<scope>compile</scope>
+  	</dependency>
+  	<dependency>
+  		<groupId>edu.uci.ics.hyracks</groupId>
+  		<artifactId>hyracks-storage-common</artifactId>
+  		<version>0.2.2-SNAPSHOT</version>
+  		<type>jar</type>
+  		<scope>compile</scope>
+  	</dependency>
+  	<dependency>
+  		<groupId>edu.uci.ics.hyracks</groupId>
+  		<artifactId>hyracks-dataflow-common</artifactId>
+  		<version>0.2.2-SNAPSHOT</version>
+  		<type>jar</type>
+  		<scope>compile</scope>
+  	</dependency>
+  	<dependency>
+  		<groupId>edu.uci.ics.hyracks</groupId>
+  		<artifactId>hyracks-dataflow-std</artifactId>
+  		<version>0.2.2-SNAPSHOT</version>
+  		<type>jar</type>
+  		<scope>compile</scope>
+  	</dependency>
+  </dependencies>
+</project>
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ICursorInitialState.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ICursorInitialState.java
new file mode 100644
index 0000000..60e8ba9
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ICursorInitialState.java
@@ -0,0 +1,23 @@
+/*
+ * 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.common.buffercache.ICachedPage;
+
+public interface ICursorInitialState {
+	public ICachedPage getPage();
+	public void setPage(ICachedPage page);
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IFreePageManager.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IFreePageManager.java
new file mode 100644
index 0000000..98b9a7e
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IFreePageManager.java
@@ -0,0 +1,35 @@
+package edu.uci.ics.hyracks.storage.am.common.api;
+
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+
+public interface IFreePageManager {
+	public void open(int fileId);
+	
+	public void close();
+	
+	public int getFreePage(ITreeIndexMetaDataFrame metaFrame)
+			throws HyracksDataException;
+
+	public void addFreePage(ITreeIndexMetaDataFrame metaFrame, int freePage)
+			throws HyracksDataException;
+
+	public int getMaxPage(ITreeIndexMetaDataFrame metaFrame)
+			throws HyracksDataException;
+
+	public void init(ITreeIndexMetaDataFrame metaFrame, int currentMaxPage)
+			throws HyracksDataException;
+
+	public ITreeIndexMetaDataFrameFactory getMetaDataFrameFactory();
+
+	// required to return negative values
+	public byte getMetaPageLevelIndicator();
+
+	public byte getFreePageLevelIndicator();
+
+	// determined by examining level indicator
+	public boolean isMetaPage(ITreeIndexMetaDataFrame metaFrame);
+
+	public boolean isFreePage(ITreeIndexMetaDataFrame metaFrame);
+	
+	public int getFirstMetadataPage();		
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexAccessor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexAccessor.java
new file mode 100644
index 0000000..202769f
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexAccessor.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) on an
+ * IIndex. An IIndexAccessor is not thread safe, but different IIndexAccessors
+ * can concurrently operate on the same IIndex (i.e., the IIndex must allow
+ * concurrent operations).
+ */
+public interface IIndexAccessor {
+    /**
+     * Inserts the given tuple.
+     * 
+     * @param tuple
+     *            Tuple to be inserted.
+     * @throws HyracksDataException
+     *             If the BufferCache throws while un/pinning or un/latching.
+     * @throws IndexException
+     *             If an index-specific constraint is violated, e.g., the key
+     *             already exists.
+     */
+    public void insert(ITupleReference tuple) throws HyracksDataException, IndexException;
+
+    /**
+     * 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 IndexException
+     *             If there is no matching tuple in the index.
+     */
+    public void update(ITupleReference tuple) throws HyracksDataException, IndexException;
+
+    /**
+     * 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 IndexException
+     *             If there is no matching tuple in the index.
+     */
+    public void delete(ITupleReference tuple) throws HyracksDataException, IndexException;
+
+    /**
+     * This operation is only supported by indexes with the notion of a unique key.
+     * If tuple's key already exists, then this operation performs an update.
+     * Otherwise, it performs an insert.
+     * 
+     * @param tuple
+     *            Tuple to be deleted.
+     * @throws HyracksDataException
+     *             If the BufferCache throws while un/pinning or un/latching.
+     * @throws IndexException
+     *             If there is no matching tuple in the index.
+     * 
+     */
+    public void upsert(ITupleReference tuple) throws HyracksDataException, IndexException;
+    
+    /**
+     * Creates a cursor appropriate for passing into search().
+     * 
+     */
+    public IIndexCursor createSearchCursor();
+
+    /**
+     * 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 IndexException
+     */
+    public void search(IIndexCursor cursor, ISearchPredicate searchPred) throws HyracksDataException, IndexException;
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexBulkLoadContext.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexBulkLoadContext.java
new file mode 100644
index 0000000..a896d80
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexBulkLoadContext.java
@@ -0,0 +1,4 @@
+package edu.uci.ics.hyracks.storage.am.common.api;
+
+public interface IIndexBulkLoadContext {
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexCursor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexCursor.java
new file mode 100644
index 0000000..d29fd73
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexCursor.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+public interface IIndexCursor {
+    public void open(ICursorInitialState initialState,
+            ISearchPredicate searchPred) throws HyracksDataException;      
+
+    public boolean hasNext() throws HyracksDataException;
+
+    public void next() throws HyracksDataException;
+
+    public void close() throws HyracksDataException;
+
+    public void reset();
+
+    public ITupleReference getTuple();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IIndexOpContext.java b/fullstack/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/fullstack/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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IOperationCallback.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IOperationCallback.java
new file mode 100644
index 0000000..9e66b43
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IOperationCallback.java
@@ -0,0 +1,9 @@
+package edu.uci.ics.hyracks.storage.am.common.api;
+
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+
+public interface IOperationCallback {
+    public void pre(ITupleReference tuple);
+
+    public void post(ITupleReference tuple);
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IOperationCallbackProvider.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IOperationCallbackProvider.java
new file mode 100644
index 0000000..974ef1a
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IOperationCallbackProvider.java
@@ -0,0 +1,7 @@
+package edu.uci.ics.hyracks.storage.am.common.api;
+
+import java.io.Serializable;
+
+public interface IOperationCallbackProvider extends Serializable {
+    public IOperationCallback getOperationCallback();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProvider.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProvider.java
new file mode 100644
index 0000000..4696e68
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProvider.java
@@ -0,0 +1,20 @@
+/*
+ * 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 interface IPrimitiveValueProvider {
+	public double getValue(byte[] bytes, int offset);
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProviderFactory.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProviderFactory.java
new file mode 100644
index 0000000..8e45d0c
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IPrimitiveValueProviderFactory.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 IPrimitiveValueProviderFactory extends Serializable {
+	public IPrimitiveValueProvider createPrimitiveValueProvider();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISearchPredicate.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISearchPredicate.java
new file mode 100644
index 0000000..a96db28
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISearchPredicate.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
+
+public interface ISearchPredicate extends Serializable {
+	public MultiComparator getLowKeyComparator();
+
+	public MultiComparator getHighKeyComparator();
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISlotManager.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISlotManager.java
new file mode 100644
index 0000000..2619493
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISlotManager.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.api;
+
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+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;
+
+public interface ISlotManager {
+	public int findTupleIndex(ITupleReference searchKey,
+			ITreeIndexTupleReference frameTuple, MultiComparator multiCmp,
+			FindTupleMode mode, FindTupleNoExactMatchPolicy matchPolicy);
+
+	public int getGreatestKeyIndicator();
+	
+	public int getErrorIndicator();
+
+	public void setFrame(ITreeIndexFrame frame);
+	
+	public int insertSlot(int tupleIndex, int tupleOff);
+
+	public int getSlotStartOff();
+
+	public int getSlotEndOff();
+
+	public int getTupleOff(int slotOff);
+
+	public void setSlot(int slotOff, int value);
+
+	public int getSlotOff(int tupleIndex);
+
+	public int getSlotSize();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISplitKey.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISplitKey.java
new file mode 100644
index 0000000..3a1c8a1
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ISplitKey.java
@@ -0,0 +1,25 @@
+package edu.uci.ics.hyracks.storage.am.common.api;
+
+import java.nio.ByteBuffer;
+
+public interface ISplitKey {
+	public void initData(int keySize);
+
+	public void reset();
+
+	public ByteBuffer getBuffer();
+
+	public ITreeIndexTupleReference getTuple();
+
+	public int getLeftPage();
+
+	public int getRightPage();
+
+	public void setLeftPage(int leftPage);
+
+	public void setRightPage(int rightPage);
+
+	public void setPages(int leftPage, int rightPage);
+
+	public ISplitKey duplicate(ITreeIndexTupleReference copyTuple);
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java
new file mode 100644
index 0000000..52626cf
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndex.java
@@ -0,0 +1,62 @@
+/*
+ * 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.dataflow.value.IBinaryComparatorFactory;
+import edu.uci.ics.hyracks.storage.am.common.dataflow.IIndex;
+
+/**
+ * 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 {
+    /**
+     * @return The index's leaf frame factory.
+     */
+    public ITreeIndexFrameFactory getLeafFrameFactory();
+
+    /**
+     * @return The index's interior frame factory.
+     */
+    public ITreeIndexFrameFactory getInteriorFrameFactory();
+
+    /**
+     * @return The index's free page manager.
+     */
+    public IFreePageManager getFreePageManager();
+
+    /**
+     * @return The number of fields tuples of this index have.
+     */
+    public int getFieldCount();
+
+    /**
+     * @return The current root page id of this index.
+     */
+    public int getRootPageId();
+
+    /**
+     * @return The file id of this index.
+     */
+    public int getFileId();
+
+    /**
+     * @return Comparator factories.
+     */
+    public IBinaryComparatorFactory[] getComparatorFactories();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexAccessor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexAccessor.java
new file mode 100644
index 0000000..da8fc3b
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexAccessor.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+/**
+ * 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 extends IIndexAccessor {
+	/**
+	 * Creates a cursor appropriate for passing into diskOrderScan().
+	 * 
+	 */
+	public ITreeIndexCursor createDiskOrderScanCursor();
+	
+	/**
+	 * 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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexCursor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexCursor.java
new file mode 100644
index 0000000..229613c
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexCursor.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.api;
+
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
+
+public interface ITreeIndexCursor extends IIndexCursor {
+
+	public ICachedPage getPage();
+
+	public void setBufferCache(IBufferCache bufferCache);
+
+	public void setFileId(int fileId);
+
+	// For allowing updates.
+	public boolean exclusiveLatchNodes();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrame.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrame.java
new file mode 100644
index 0000000..c33a8d8
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrame.java
@@ -0,0 +1,92 @@
+/*
+ * 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.nio.ByteBuffer;
+
+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.common.buffercache.ICachedPage;
+
+public interface ITreeIndexFrame {
+
+	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();
+
+    // returns true if compressed.
+    public boolean compress() throws HyracksDataException;
+
+    public int getTupleCount();
+
+    public int getTupleOffset(int slotNum);
+
+    public int getTotalFreeSpace();
+
+    public void setPageLsn(long pageLsn);
+
+    public long getPageLsn();
+
+    public void setPage(ICachedPage page);
+
+    public ICachedPage getPage();
+
+    public ByteBuffer getBuffer();
+    
+    // for debugging
+    public String printHeader();
+
+    public void split(ITreeIndexFrame rightFrame, ITupleReference tuple, ISplitKey splitKey) throws TreeIndexException;
+
+    public ISlotManager getSlotManager();
+
+    // ATTENTION: in b-tree operations it may not always be possible to
+    // determine whether an ICachedPage is a leaf or interior node
+    // a compatible interior and leaf implementation MUST return identical
+    // values when given the same ByteBuffer for the functions below
+    public boolean isLeaf();
+
+    public boolean isInterior();
+
+    public byte getLevel();
+
+    public void setLevel(byte level);
+
+    public int getSlotSize();
+
+    // for debugging
+    public int getFreeSpaceOff();
+
+    public void setFreeSpaceOff(int freeSpace);
+
+    public ITreeIndexTupleWriter getTupleWriter();
+
+    public int getPageHeaderSize();
+    
+    public ITreeIndexTupleReference createTupleReference();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrameCompressor.java b/fullstack/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/fullstack/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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrameFactory.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrameFactory.java
new file mode 100644
index 0000000..32c77be
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexFrameFactory.java
@@ -0,0 +1,8 @@
+package edu.uci.ics.hyracks.storage.am.common.api;
+
+import java.io.Serializable;
+
+public interface ITreeIndexFrameFactory extends Serializable {
+    public ITreeIndexFrame createFrame();
+    public ITreeIndexTupleWriterFactory getTupleWriterFactory();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrame.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrame.java
new file mode 100644
index 0000000..9e95970
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrame.java
@@ -0,0 +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.api;
+
+import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
+
+public interface ITreeIndexMetaDataFrame {
+	public void initBuffer(byte level);
+
+	public void setPage(ICachedPage page);
+
+	public ICachedPage getPage();
+
+	public byte getLevel();
+
+	public void setLevel(byte level);
+
+	public int getNextPage();
+
+	public void setNextPage(int nextPage);
+
+	public int getMaxPage();
+
+	public void setMaxPage(int maxPage);
+
+	public int getFreePage();
+
+	public boolean hasSpace();
+
+	public void addFreePage(int freePage);
+	
+	// Special flag for LSM-Components to mark whether they are valid or not. 
+	public boolean isValid();
+	
+	// Set special validity flag.
+	public void setValid(boolean isValid);
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrameFactory.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrameFactory.java
new file mode 100644
index 0000000..d5625b4
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexMetaDataFrameFactory.java
@@ -0,0 +1,20 @@
+/*
+ * 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 interface ITreeIndexMetaDataFrameFactory {
+	public ITreeIndexMetaDataFrame createFrame();
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleReference.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleReference.java
new file mode 100644
index 0000000..b989dd9
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleReference.java
@@ -0,0 +1,32 @@
+/*
+ * 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.nio.ByteBuffer;
+
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+
+public interface ITreeIndexTupleReference extends ITupleReference {
+    public void setFieldCount(int fieldCount);
+
+    public void setFieldCount(int fieldStartIndex, int fieldCount);
+
+    public void resetByTupleOffset(ByteBuffer buf, int tupleStartOffset);
+
+    public void resetByTupleIndex(ITreeIndexFrame frame, int tupleIndex);
+    
+    public int getTupleSize();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleWriter.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleWriter.java
new file mode 100644
index 0000000..30e8f39
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleWriter.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.api;
+
+import java.nio.ByteBuffer;
+
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+
+public interface ITreeIndexTupleWriter {
+    public int writeTuple(ITupleReference tuple, ByteBuffer targetBuf, int targetOff);
+    
+    public int writeTuple(ITupleReference tuple, byte[] targetBuf, int targetOff);
+
+    public int bytesRequired(ITupleReference tuple);
+
+    public int writeTupleFields(ITupleReference tuple, int startField, int numFields, byte[] targetBuf,
+            int targetOff);
+
+    public int bytesRequired(ITupleReference tuple, int startField, int numFields);
+
+    // return a tuplereference instance that can read the tuple written by this
+    // writer
+    // the main idea is that the format of the written tuple may not be the same
+    // as the format written by this writer
+    public ITreeIndexTupleReference createTupleReference();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleWriterFactory.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleWriterFactory.java
new file mode 100644
index 0000000..ea5e740
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITreeIndexTupleWriterFactory.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 ITreeIndexTupleWriterFactory extends Serializable {
+	public ITreeIndexTupleWriter createTupleWriter();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleFilter.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleFilter.java
new file mode 100644
index 0000000..41f0f4d
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleFilter.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.dataflow.common.data.accessors.IFrameTupleReference;
+
+public interface ITupleFilter {
+	public boolean accept(IFrameTupleReference tuple) throws Exception;
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleFilterFactory.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleFilterFactory.java
new file mode 100644
index 0000000..602902d
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleFilterFactory.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
+
+public interface ITupleFilterFactory extends Serializable {
+    public ITupleFilter createTupleFilter(IHyracksTaskContext ctx) throws Exception;
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleUpdater.java b/fullstack/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/fullstack/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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/ITupleUpdaterFactory.java b/fullstack/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/fullstack/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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IndexException.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IndexException.java
new file mode 100644
index 0000000..0aeaf82
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IndexException.java
@@ -0,0 +1,28 @@
+/*
+ * 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 IndexException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public IndexException(Exception e) {        
+        super(e);
+    }
+
+    public IndexException(String message) {
+        super(message);
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IndexType.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IndexType.java
new file mode 100644
index 0000000..6f83e0b
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/IndexType.java
@@ -0,0 +1,5 @@
+package edu.uci.ics.hyracks.storage.am.common.api;
+
+public enum IndexType {
+	BTREE, RTREE, INVERTED
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/TreeIndexException.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/TreeIndexException.java
new file mode 100644
index 0000000..c3f3f1a
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/api/TreeIndexException.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.api;
+
+public class TreeIndexException extends IndexException {
+
+	private static final long serialVersionUID = 1L;
+	private boolean handled = false;
+
+	public TreeIndexException(Exception e) {		
+		super(e);
+	}
+
+	public TreeIndexException(String message) {
+		super(message);
+	}
+
+	public void setHandled(boolean handled) {
+		this.handled = handled;
+	}
+
+	public boolean getHandled() {
+		return handled;
+	}
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/data/PointablePrimitiveValueProviderFactory.java b/fullstack/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/fullstack/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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/AbstractTreeIndexOperatorDescriptor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/AbstractTreeIndexOperatorDescriptor.java
new file mode 100644
index 0000000..9f0fbc9
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/AbstractTreeIndexOperatorDescriptor.java
@@ -0,0 +1,122 @@
+/*
+ * 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.api.dataflow.value.RecordDescriptor;
+import edu.uci.ics.hyracks.api.job.IOperatorDescriptorRegistry;
+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.IOperationCallbackProvider;
+import edu.uci.ics.hyracks.storage.am.common.api.ITupleFilterFactory;
+import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
+
+public abstract class AbstractTreeIndexOperatorDescriptor extends
+		AbstractSingleActivityOperatorDescriptor implements
+		ITreeIndexOperatorDescriptor {
+
+	private static final long serialVersionUID = 1L;
+
+	protected final IFileSplitProvider fileSplitProvider;
+
+	protected final IBinaryComparatorFactory[] comparatorFactories;
+
+	protected final IStorageManagerInterface storageManager;
+	protected final IIndexRegistryProvider<IIndex> indexRegistryProvider;
+
+	protected final ITypeTraits[] typeTraits;
+	protected final IIndexDataflowHelperFactory dataflowHelperFactory;
+	protected final ITupleFilterFactory tupleFilterFactory;
+	
+	protected final boolean retainInput;
+    protected final IOperationCallbackProvider opCallbackProvider;
+
+	public AbstractTreeIndexOperatorDescriptor(IOperatorDescriptorRegistry spec,
+			int inputArity, int outputArity, RecordDescriptor recDesc,
+			IStorageManagerInterface storageManager,
+			IIndexRegistryProvider<IIndex> indexRegistryProvider,
+			IFileSplitProvider fileSplitProvider,
+			ITypeTraits[] typeTraits,
+			IBinaryComparatorFactory[] comparatorFactories,
+			IIndexDataflowHelperFactory dataflowHelperFactory,
+			ITupleFilterFactory tupleFilterFactory,
+			boolean retainInput, IOperationCallbackProvider opCallbackProvider) {
+		super(spec, inputArity, outputArity);
+		this.fileSplitProvider = fileSplitProvider;
+		this.storageManager = storageManager;
+		this.indexRegistryProvider = indexRegistryProvider;
+		this.typeTraits = typeTraits;
+		this.comparatorFactories = comparatorFactories;
+		this.dataflowHelperFactory = dataflowHelperFactory;
+		this.retainInput = retainInput;
+		this.tupleFilterFactory = tupleFilterFactory;
+        this.opCallbackProvider = opCallbackProvider;
+		if (outputArity > 0) {
+			recordDescriptors[0] = recDesc;
+		}
+	}
+
+	@Override
+	public IFileSplitProvider getFileSplitProvider() {
+		return fileSplitProvider;
+	}
+
+	@Override
+	public IBinaryComparatorFactory[] getTreeIndexComparatorFactories() {
+		return comparatorFactories;
+	}
+
+	@Override
+	public ITypeTraits[] getTreeIndexTypeTraits() {
+		return typeTraits;
+	}
+
+	@Override
+	public IStorageManagerInterface getStorageManager() {
+		return storageManager;
+	}
+
+	@Override
+	public IIndexRegistryProvider<IIndex> getIndexRegistryProvider() {
+		return indexRegistryProvider;
+	}
+
+	@Override
+	public RecordDescriptor getRecordDescriptor() {
+		return recordDescriptors[0];
+	}
+
+	@Override
+	public IIndexDataflowHelperFactory getIndexDataflowHelperFactory() {
+		return dataflowHelperFactory;
+	}
+	
+	@Override
+	public boolean getRetainInput() {
+		return retainInput;
+	}
+	
+	@Override
+	public IOperationCallbackProvider getOpCallbackProvider() {
+	    return opCallbackProvider;
+	}
+	
+	@Override
+	public ITupleFilterFactory getTupleFilterFactory() {
+		return tupleFilterFactory;
+	}
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndex.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndex.java
new file mode 100644
index 0000000..64cbd58
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndex.java
@@ -0,0 +1,112 @@
+/*
+ * 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;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexAccessor;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexBulkLoadContext;
+import edu.uci.ics.hyracks.storage.am.common.api.IndexException;
+import edu.uci.ics.hyracks.storage.am.common.api.IndexType;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+
+/**
+ * Interface describing the operations common to all index structures. Indexes
+ * implementing this interface can easily reuse existing index operators for
+ * dataflow. Users must perform operations on an IIndex via an IIndexAccessor.
+ */
+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) throws HyracksDataException;
+
+    /**
+     * Closes the index.
+     */
+    public void close() throws HyracksDataException;
+
+    /**
+     * Creates an index accessor for performing operations on this index.
+     * (insert/delete/update/search/diskorderscan). An IIndexAccessor is not
+     * thread safe, but different IIndexAccessors can concurrently operate
+     * on the same IIndex
+     * 
+     * @returns IIndexAccessor An accessor for this tree.
+     */
+    public IIndexAccessor createAccessor();
+
+    /**
+     * Prepares the index for bulk loading, returning a bulk load context. The
+     * index may require to be empty for bulk loading.
+     * 
+     * @param fillFactor
+     *            Desired fill factor in [0, 1.0].
+     * @throws HyracksDataException
+     *             If the BufferCache throws while un/pinning or un/latching.
+     * @throws IndexException
+     *             For example, if the index was already loaded and only
+     *             supports a single load.
+     * @returns A new context for bulk loading, required for appending tuples.
+     */
+    public IIndexBulkLoadContext beginBulkLoad(float fillFactor) throws IndexException, HyracksDataException;
+
+    /**
+     * Append a tuple to the index in the context of a bulk load.
+     * 
+     * @param tuple
+     *            Tuple to be inserted.
+     * @param ictx
+     *            Existing bulk load context.
+     * @throws HyracksDataException
+     *             If the BufferCache throws while un/pinning or un/latching.
+     */
+    public void bulkLoadAddTuple(ITupleReference tuple, IIndexBulkLoadContext ictx) throws HyracksDataException;
+
+    /**
+     * Finalize the bulk loading operation in the given context.
+     * 
+     * @param ictx
+     *            Existing bulk load context to be finalized.
+     * @throws HyracksDataException
+     *             If the BufferCache throws while un/pinning or un/latching.
+     */
+    public void endBulkLoad(IIndexBulkLoadContext ictx) throws HyracksDataException;
+
+    /**
+     * @return BufferCache underlying this index.
+     */
+    public IBufferCache getBufferCache();
+
+    /**
+     * @return An enum of the concrete type of this index.
+     */
+    public IndexType getIndexType();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexDataflowHelperFactory.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexDataflowHelperFactory.java
new file mode 100644
index 0000000..ddca470
--- /dev/null
+++ b/fullstack/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);
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.java
new file mode 100644
index 0000000..e37d374
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.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.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.am.common.api.IOperationCallbackProvider;
+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();
+    
+    public boolean getRetainInput();
+    
+    public IOperationCallbackProvider getOpCallbackProvider();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexRegistryProvider.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexRegistryProvider.java
new file mode 100644
index 0000000..ed20de0
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IIndexRegistryProvider.java
@@ -0,0 +1,24 @@
+/*
+ * 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 IIndexRegistryProvider<IndexType> extends Serializable {
+	public IndexRegistry<IndexType> getRegistry(IHyracksTaskContext ctx);
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOperatorDescriptor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOperatorDescriptor.java
new file mode 100644
index 0000000..7fba22b
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/ITreeIndexOperatorDescriptor.java
@@ -0,0 +1,28 @@
+/*
+ * 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.ITupleFilterFactory;
+
+public interface ITreeIndexOperatorDescriptor extends IIndexOperatorDescriptor {
+	public IBinaryComparatorFactory[] getTreeIndexComparatorFactories();
+	
+	public ITypeTraits[] getTreeIndexTypeTraits();
+	
+	public ITupleFilterFactory getTupleFilterFactory();
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
new file mode 100644
index 0000000..fa95ce4
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
@@ -0,0 +1,119 @@
+/*
+ * 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.am.common.api.IOperationCallbackProvider;
+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 final int partition;
+    protected final IIndexOperatorDescriptor opDesc;
+    protected final IHyracksTaskContext ctx;
+
+    public IndexDataflowHelper(IIndexOperatorDescriptor opDesc, final IHyracksTaskContext ctx, int partition) {
+        this.opDesc = opDesc;
+        this.ctx = ctx;
+        this.partition = partition;
+    }
+
+    public void init(boolean forceCreate) throws HyracksDataException {
+        IBufferCache bufferCache = opDesc.getStorageManager().getBufferCache(ctx);
+        IFileMapProvider fileMapProvider = opDesc.getStorageManager().getFileMapProvider(ctx);
+        IndexRegistry<IIndex> indexRegistry = opDesc.getIndexRegistryProvider().getRegistry(ctx);
+        FileReference fileRef = getFilereference();
+        int fileId = -1;
+        boolean fileIsMapped = false;
+        synchronized (fileMapProvider) {
+            fileIsMapped = fileMapProvider.isMapped(fileRef);
+            if (!fileIsMapped) {
+                bufferCache.createFile(fileRef);
+            }
+            fileId = fileMapProvider.lookupFileId(fileRef);
+            try {
+                // Also creates the file if it doesn't exist yet.
+                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 after openFile() succeeds.
+        indexFileId = fileId;
+        // Create new index instance and register it.
+        synchronized (indexRegistry) {
+            // Check if the index has already been registered.
+            boolean register = false;
+            index = indexRegistry.get(indexFileId);
+            if (index == null) {
+                index = createIndexInstance();
+                register = true;
+            }
+            if (forceCreate) {
+                index.create(indexFileId);
+            }
+            index.open(indexFileId);
+            if (register) {
+                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);
+            indexFileId = -1;
+        }
+    }
+
+    public IIndex getIndex() {
+        return index;
+    }
+
+    public IHyracksTaskContext getHyracksTaskContext() {
+        return ctx;
+    }
+
+    public IIndexOperatorDescriptor getOperatorDescriptor() {
+        return opDesc;
+    }
+
+    public int getIndexFileId() {
+        return indexFileId;
+    }
+
+    public IOperationCallbackProvider getOpCallbackProvider() {
+        return opDesc.getOpCallbackProvider();
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.java
new file mode 100644
index 0000000..9aba0be
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/IndexRegistry.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.dataflow;
+
+import java.util.HashMap;
+
+public class IndexRegistry<IndexType> {
+
+    private HashMap<Integer, IndexType> map = new HashMap<Integer, IndexType>();
+
+    public IndexType get(int indexId) {
+        return map.get(indexId);
+    }
+
+    public void register(int indexId, IndexType index) {
+        map.put(indexId, index);
+    }
+
+    public void unregister(int indexId) {
+        map.remove(indexId);
+    }
+
+    public int size() {
+        return map.size();
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/PermutingFrameTupleReference.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/PermutingFrameTupleReference.java
new file mode 100644
index 0000000..0b296f0
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/PermutingFrameTupleReference.java
@@ -0,0 +1,65 @@
+/*
+ * 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.IFrameTupleAccessor;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class PermutingFrameTupleReference implements IFrameTupleReference {
+	private IFrameTupleAccessor fta;
+	private int tIndex;
+	private int[] fieldPermutation;
+
+	public void setFieldPermutation(int[] fieldPermutation) {
+		this.fieldPermutation = fieldPermutation;
+	}
+
+	public void reset(IFrameTupleAccessor fta, int tIndex) {
+		this.fta = fta;
+		this.tIndex = tIndex;
+	}
+
+	@Override
+	public IFrameTupleAccessor getFrameTupleAccessor() {
+		return fta;
+	}
+
+	@Override
+	public int getTupleIndex() {
+		return tIndex;
+	}
+
+	@Override
+	public int getFieldCount() {
+		return fieldPermutation.length;
+	}
+
+	@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 getFieldLength(int fIdx) {
+		return fta.getFieldLength(tIndex, fieldPermutation[fIdx]);
+	}
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java
new file mode 100644
index 0000000..0020089
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java
@@ -0,0 +1,52 @@
+/*
+ * 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.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.ITypeTraits;
+import edu.uci.ics.hyracks.api.job.IOperatorDescriptorRegistry;
+import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
+import edu.uci.ics.hyracks.storage.am.common.api.IOperationCallbackProvider;
+import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
+
+public class TreeIndexBulkLoadOperatorDescriptor extends AbstractTreeIndexOperatorDescriptor {
+
+    private static final long serialVersionUID = 1L;
+
+    private final int[] fieldPermutation;
+    private final float fillFactor;
+
+    public TreeIndexBulkLoadOperatorDescriptor(IOperatorDescriptorRegistry spec, IStorageManagerInterface storageManager,
+            IIndexRegistryProvider<IIndex> indexRegistryProvider, IFileSplitProvider fileSplitProvider,
+            ITypeTraits[] typeTraits, IBinaryComparatorFactory[] comparatorFactories, int[] fieldPermutation,
+            float fillFactor, IIndexDataflowHelperFactory dataflowHelperFactory,
+            IOperationCallbackProvider opCallbackProvider) {
+        super(spec, 1, 0, null, storageManager, indexRegistryProvider, fileSplitProvider, typeTraits,
+                comparatorFactories, dataflowHelperFactory, null, false, opCallbackProvider);
+        this.fieldPermutation = fieldPermutation;
+        this.fillFactor = fillFactor;
+    }
+
+    @Override
+    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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java
new file mode 100644
index 0000000..a2d78a4
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorNodePushable.java
@@ -0,0 +1,90 @@
+/*
+ * 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.nio.ByteBuffer;
+
+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.ITreeIndex;
+
+public class TreeIndexBulkLoadOperatorNodePushable extends AbstractUnaryInputSinkOperatorNodePushable {
+    private float fillFactor;
+    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, IHyracksTaskContext ctx,
+            int partition, int[] fieldPermutation, float fillFactor, IRecordDescriptorProvider recordDescProvider) {
+        treeIndexHelper = (TreeIndexDataflowHelper) opDesc.getIndexDataflowHelperFactory().createIndexDataflowHelper(
+                opDesc, ctx, partition);
+        this.fillFactor = fillFactor;
+        this.recordDescProvider = recordDescProvider;
+        tuple.setFieldPermutation(fieldPermutation);
+    }
+
+    @Override
+    public void open() throws HyracksDataException {
+        AbstractTreeIndexOperatorDescriptor opDesc = (AbstractTreeIndexOperatorDescriptor) treeIndexHelper
+                .getOperatorDescriptor();
+        RecordDescriptor recDesc = recordDescProvider.getInputRecordDescriptor(opDesc.getActivityId(), 0);
+        accessor = new FrameTupleAccessor(treeIndexHelper.getHyracksTaskContext().getFrameSize(), recDesc);
+        try {
+            treeIndexHelper.init(false);
+            treeIndex = (ITreeIndex) treeIndexHelper.getIndex();
+            treeIndex.open(treeIndexHelper.getIndexFileId());
+            bulkLoadCtx = treeIndex.beginBulkLoad(fillFactor);
+        } catch (Exception e) {
+            // cleanup in case of failure
+            treeIndexHelper.deinit();
+            throw new HyracksDataException(e);
+        }
+    }
+
+    @Override
+    public void nextFrame(ByteBuffer buffer) throws HyracksDataException {
+        accessor.reset(buffer);
+        int tupleCount = accessor.getTupleCount();
+        for (int i = 0; i < tupleCount; i++) {
+            tuple.reset(accessor, i);
+            treeIndex.bulkLoadAddTuple(tuple, bulkLoadCtx);
+        }
+    }
+
+    @Override
+    public void close() throws HyracksDataException {
+        try {
+            treeIndex.endBulkLoad(bulkLoadCtx);
+        } catch (Exception e) {
+            throw new HyracksDataException(e);
+        } finally {
+            treeIndexHelper.deinit();
+        }
+    }
+
+    @Override
+    public void fail() throws HyracksDataException {
+    }
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorDescriptor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorDescriptor.java
new file mode 100644
index 0000000..075a6a4
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorDescriptor.java
@@ -0,0 +1,45 @@
+/*
+ * 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.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.ITypeTraits;
+import edu.uci.ics.hyracks.api.job.IOperatorDescriptorRegistry;
+import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
+import edu.uci.ics.hyracks.storage.am.common.api.IOperationCallbackProvider;
+import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
+
+public class TreeIndexCreateOperatorDescriptor extends AbstractTreeIndexOperatorDescriptor {
+
+    private static final long serialVersionUID = 1L;
+
+    public TreeIndexCreateOperatorDescriptor(IOperatorDescriptorRegistry spec, IStorageManagerInterface storageManager,
+            IIndexRegistryProvider<IIndex> indexRegistryProvider, IFileSplitProvider fileSplitProvider,
+            ITypeTraits[] typeTraits, IBinaryComparatorFactory[] comparatorFactories,
+            IIndexDataflowHelperFactory dataflowHelperFactory, IOperationCallbackProvider opCallbackProvider) {
+        super(spec, 0, 0, null, storageManager, indexRegistryProvider, fileSplitProvider, typeTraits,
+                comparatorFactories, dataflowHelperFactory, null, false, opCallbackProvider);
+    }
+
+    @Override
+    public IOperatorNodePushable createPushRuntime(IHyracksTaskContext ctx,
+            IRecordDescriptorProvider recordDescProvider, int partition, int nPartitions) {
+        return new TreeIndexCreateOperatorNodePushable(this, ctx, partition);
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorNodePushable.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorNodePushable.java
new file mode 100644
index 0000000..21348a0
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorNodePushable.java
@@ -0,0 +1,59 @@
+/*
+ * 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.IHyracksTaskContext;
+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 TreeIndexCreateOperatorNodePushable extends AbstractOperatorNodePushable {
+    protected final TreeIndexDataflowHelper treeIndexHelper;
+
+    public TreeIndexCreateOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc, IHyracksTaskContext ctx,
+            int partition) {
+        treeIndexHelper = (TreeIndexDataflowHelper) opDesc.getIndexDataflowHelperFactory().createIndexDataflowHelper(
+                opDesc, ctx, partition);
+    }
+
+    @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 {
+        	treeIndexHelper.init(true);
+        } finally {
+        	treeIndexHelper.deinit();
+        }
+    }
+
+    @Override
+    public void setOutputFrameWriter(int index, IFrameWriter writer, RecordDescriptor recordDesc) {
+    }
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDataflowHelper.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDataflowHelper.java
new file mode 100644
index 0000000..10d1077
--- /dev/null
+++ b/fullstack/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) {
+        super(opDesc, ctx, partition);
+        this.treeOpDesc = (ITreeIndexOperatorDescriptor) opDesc;
+    }
+
+    public abstract ITreeIndex createIndexInstance() throws HyracksDataException;
+
+    public ITreeIndexCursor createDiskOrderScanCursor(ITreeIndexFrame leafFrame) throws HyracksDataException {
+        return new TreeDiskOrderScanCursor(leafFrame);
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java
new file mode 100644
index 0000000..324485e
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java
@@ -0,0 +1,45 @@
+/*
+ * 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.dataflow.IOperatorNodePushable;
+import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
+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.IOperatorDescriptorRegistry;
+import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
+import edu.uci.ics.hyracks.storage.am.common.api.IOperationCallbackProvider;
+import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
+
+public class TreeIndexDiskOrderScanOperatorDescriptor extends AbstractTreeIndexOperatorDescriptor {
+
+    private static final long serialVersionUID = 1L;
+
+    public TreeIndexDiskOrderScanOperatorDescriptor(IOperatorDescriptorRegistry spec, RecordDescriptor recDesc,
+            IStorageManagerInterface storageManager, IIndexRegistryProvider<IIndex> indexRegistryProvider,
+            IFileSplitProvider fileSplitProvider, ITypeTraits[] typeTraits,
+            IIndexDataflowHelperFactory dataflowHelperFactory, IOperationCallbackProvider opCallbackProvider) {
+        super(spec, 0, 1, recDesc, storageManager, indexRegistryProvider, fileSplitProvider, typeTraits, null,
+                dataflowHelperFactory, null, false, opCallbackProvider);
+    }
+
+    @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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java
new file mode 100644
index 0000000..d02a570
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorNodePushable.java
@@ -0,0 +1,99 @@
+/*
+ * 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.DataOutput;
+import java.nio.ByteBuffer;
+
+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;
+
+public class TreeIndexDiskOrderScanOperatorNodePushable extends AbstractUnaryOutputSourceOperatorNodePushable {
+    private final TreeIndexDataflowHelper treeIndexHelper;
+    private ITreeIndex treeIndex;
+
+    public TreeIndexDiskOrderScanOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc,
+            IHyracksTaskContext ctx, int partition) {
+        treeIndexHelper = (TreeIndexDataflowHelper) opDesc.getIndexDataflowHelperFactory().createIndexDataflowHelper(
+                opDesc, ctx, partition);
+    }
+
+    @Override
+    public void initialize() throws HyracksDataException {
+        try {
+            treeIndexHelper.init(false);
+            treeIndex = (ITreeIndex) treeIndexHelper.getIndex();
+            ITreeIndexFrame cursorFrame = treeIndex.getLeafFrameFactory().createFrame();
+            ITreeIndexCursor cursor = treeIndexHelper.createDiskOrderScanCursor(cursorFrame);
+            ITreeIndexAccessor indexAccessor = (ITreeIndexAccessor) treeIndex.createAccessor();
+            writer.open();
+            try {
+                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);
+                DataOutput dos = tb.getDataOutput();
+
+                while (cursor.hasNext()) {
+                    tb.reset();
+                    cursor.next();
+
+                    ITupleReference frameTuple = cursor.getTuple();
+                    for (int i = 0; i < frameTuple.getFieldCount(); i++) {
+                        dos.write(frameTuple.getFieldData(i), frameTuple.getFieldStart(i), frameTuple.getFieldLength(i));
+                        tb.addFieldEndOffset();
+                    }
+
+                    if (!appender.append(tb.getFieldEndOffsets(), tb.getByteArray(), 0, tb.getSize())) {
+                        FrameUtils.flushFrame(frame, writer);
+                        appender.reset(frame, true);
+                        if (!appender.append(tb.getFieldEndOffsets(), tb.getByteArray(), 0, tb.getSize())) {
+                            throw new IllegalStateException();
+                        }
+                    }
+                }
+                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);
+        }
+    }
+
+    @Override
+    public void deinitialize() throws HyracksDataException {
+        treeIndexHelper.deinit();
+    }
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorDescriptor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorDescriptor.java
new file mode 100644
index 0000000..7c58031
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorDescriptor.java
@@ -0,0 +1,52 @@
+/*
+ * 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.dataflow.IOperatorNodePushable;
+import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
+import edu.uci.ics.hyracks.api.job.IOperatorDescriptorRegistry;
+import edu.uci.ics.hyracks.dataflow.std.base.AbstractSingleActivityOperatorDescriptor;
+import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
+import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
+
+public class TreeIndexDropOperatorDescriptor extends
+		AbstractSingleActivityOperatorDescriptor {
+
+	private static final long serialVersionUID = 1L;
+
+	private IStorageManagerInterface storageManager;
+	private IIndexRegistryProvider<IIndex> treeIndexRegistryProvider;
+	private IFileSplitProvider fileSplitProvider;
+
+	public TreeIndexDropOperatorDescriptor(IOperatorDescriptorRegistry 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(IHyracksTaskContext ctx,
+			IRecordDescriptorProvider recordDescProvider,
+			int partition, int nPartitions) {
+		return new TreeIndexDropOperatorNodePushable(ctx, storageManager,
+				treeIndexRegistryProvider, fileSplitProvider, partition);
+	}
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java
new file mode 100644
index 0000000..5f3c0b5
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexDropOperatorNodePushable.java
@@ -0,0 +1,103 @@
+/*
+ * 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.util.logging.Level;
+import java.util.logging.Logger;
+
+import edu.uci.ics.hyracks.api.comm.IFrameWriter;
+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.common.IStorageManagerInterface;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
+
+public class TreeIndexDropOperatorNodePushable extends AbstractOperatorNodePushable {
+    private static final Logger LOGGER = Logger.getLogger(TreeIndexDropOperatorNodePushable.class.getName());
+
+    private final IHyracksTaskContext ctx;
+    private IIndexRegistryProvider<IIndex> treeIndexRegistryProvider;
+    private IStorageManagerInterface storageManager;
+    private IFileSplitProvider fileSplitProvider;
+    private int partition;
+
+    public TreeIndexDropOperatorNodePushable(IHyracksTaskContext ctx, IStorageManagerInterface storageManager,
+            IIndexRegistryProvider<IIndex> treeIndexRegistryProvider, IFileSplitProvider fileSplitProvider,
+            int partition) {
+        this.ctx = ctx;
+        this.storageManager = storageManager;
+        this.treeIndexRegistryProvider = treeIndexRegistryProvider;
+        this.fileSplitProvider = fileSplitProvider;
+        this.partition = partition;
+    }
+
+    @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 {
+            IndexRegistry<IIndex> treeIndexRegistry = treeIndexRegistryProvider.getRegistry(ctx);
+            IBufferCache bufferCache = storageManager.getBufferCache(ctx);
+            IFileMapProvider fileMapProvider = storageManager.getFileMapProvider(ctx);
+
+            FileReference f = fileSplitProvider.getFileSplits()[partition].getLocalFile();
+            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);
+            }
+            // Unregister tree instance.
+            synchronized (treeIndexRegistry) {
+                treeIndexRegistry.unregister(indexFileId);
+            }
+
+            // remove name to id mapping
+            bufferCache.deleteFile(indexFileId, false);
+        }
+        // TODO: for the time being we don't throw,
+        // with proper exception handling (no hanging job problem) we should
+        // throw
+        catch (Exception e) {
+            if (LOGGER.isLoggable(Level.WARNING)) {
+                LOGGER.warning("Tree Drop Operator Failed Due To Exception: " + e.getMessage());
+            }
+        }
+    }
+
+    @Override
+    public void setOutputFrameWriter(int index, IFrameWriter writer, RecordDescriptor recordDesc) {
+    }
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java
new file mode 100644
index 0000000..a615386
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.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.ITypeTraits;
+import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
+import edu.uci.ics.hyracks.api.job.IOperatorDescriptorRegistry;
+import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
+import edu.uci.ics.hyracks.storage.am.common.api.IOperationCallbackProvider;
+import edu.uci.ics.hyracks.storage.am.common.api.ITupleFilterFactory;
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
+import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
+
+public class TreeIndexInsertUpdateDeleteOperatorDescriptor extends AbstractTreeIndexOperatorDescriptor {
+
+    private static final long serialVersionUID = 1L;
+
+    private final int[] fieldPermutation;
+
+    private IndexOp op;
+
+    public TreeIndexInsertUpdateDeleteOperatorDescriptor(IOperatorDescriptorRegistry spec, RecordDescriptor recDesc,
+            IStorageManagerInterface storageManager, IIndexRegistryProvider<IIndex> indexRegistryProvider,
+            IFileSplitProvider fileSplitProvider, ITypeTraits[] typeTraits,
+            IBinaryComparatorFactory[] comparatorFactories, int[] fieldPermutation, IndexOp op,
+            IIndexDataflowHelperFactory dataflowHelperFactory, ITupleFilterFactory tupleFilterFactory, IOperationCallbackProvider opCallbackProvider) {
+        super(spec, 1, 1, recDesc, storageManager, indexRegistryProvider, fileSplitProvider, typeTraits,
+                comparatorFactories, dataflowHelperFactory, tupleFilterFactory, false, opCallbackProvider);
+        this.fieldPermutation = fieldPermutation;
+        this.op = 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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java
new file mode 100644
index 0000000..e05568f
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorNodePushable.java
@@ -0,0 +1,137 @@
+/*
+ * 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.nio.ByteBuffer;
+
+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.common.comm.util.FrameUtils;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.FrameTupleReference;
+import edu.uci.ics.hyracks.dataflow.std.base.AbstractUnaryInputUnaryOutputOperatorNodePushable;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexAccessor;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
+import edu.uci.ics.hyracks.storage.am.common.api.ITupleFilter;
+import edu.uci.ics.hyracks.storage.am.common.api.ITupleFilterFactory;
+import edu.uci.ics.hyracks.storage.am.common.ophelpers.IndexOp;
+
+public class TreeIndexInsertUpdateDeleteOperatorNodePushable extends AbstractUnaryInputUnaryOutputOperatorNodePushable {
+    private final TreeIndexDataflowHelper treeIndexHelper;
+    private FrameTupleAccessor accessor;
+    private final IRecordDescriptorProvider recordDescProvider;
+    private final IndexOp op;
+    private final PermutingFrameTupleReference tuple = new PermutingFrameTupleReference();
+    private FrameTupleReference frameTuple;
+    private ByteBuffer writeBuffer;
+    private IIndexAccessor indexAccessor;
+    private ITupleFilter tupleFilter;
+
+    public TreeIndexInsertUpdateDeleteOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc,
+            IHyracksTaskContext ctx, int partition, int[] fieldPermutation,
+            IRecordDescriptorProvider recordDescProvider, IndexOp op) {
+        treeIndexHelper = (TreeIndexDataflowHelper) opDesc.getIndexDataflowHelperFactory().createIndexDataflowHelper(
+                opDesc, ctx, partition);
+        this.recordDescProvider = recordDescProvider;
+        this.op = op;
+        tuple.setFieldPermutation(fieldPermutation);
+    }
+
+    @Override
+    public void open() throws HyracksDataException {
+        AbstractTreeIndexOperatorDescriptor opDesc = (AbstractTreeIndexOperatorDescriptor) treeIndexHelper
+                .getOperatorDescriptor();
+        RecordDescriptor inputRecDesc = recordDescProvider.getInputRecordDescriptor(opDesc.getActivityId(), 0);
+        accessor = new FrameTupleAccessor(treeIndexHelper.getHyracksTaskContext().getFrameSize(), inputRecDesc);
+        writeBuffer = treeIndexHelper.getHyracksTaskContext().allocateFrame();
+        writer.open();
+        try {
+            treeIndexHelper.init(false);
+            ITreeIndex treeIndex = (ITreeIndex) treeIndexHelper.getIndex();
+            indexAccessor = treeIndex.createAccessor();
+            ITupleFilterFactory tupleFilterFactory = opDesc.getTupleFilterFactory();
+            if (tupleFilterFactory != null) {
+                tupleFilter = tupleFilterFactory.createTupleFilter(treeIndexHelper.ctx);
+                frameTuple = new FrameTupleReference();
+            }
+        } catch (Exception e) {
+            // cleanup in case of failure
+            treeIndexHelper.deinit();
+            throw new HyracksDataException(e);
+        }
+    }
+
+    @Override
+    public void nextFrame(ByteBuffer buffer) throws HyracksDataException {
+        accessor.reset(buffer);
+        int tupleCount = accessor.getTupleCount();
+        for (int i = 0; i < tupleCount; i++) {
+            try {
+                if (tupleFilter != null) {
+                    frameTuple.reset(accessor, i);
+                    if (!tupleFilter.accept(frameTuple)) {
+                        continue;
+                    }
+                }
+                tuple.reset(accessor, i);
+                switch (op) {
+                    case INSERT: {
+                        indexAccessor.insert(tuple);
+                        break;
+                    }
+                    case UPDATE: {
+                        indexAccessor.update(tuple);
+                        break;
+                    }
+                    case UPSERT: {
+                        indexAccessor.upsert(tuple);
+                        break;
+                    }
+                    case DELETE: {
+                        indexAccessor.delete(tuple);
+                        break;
+                    }
+                    default: {
+                        throw new HyracksDataException("Unsupported operation " + op
+                                + " in tree index InsertUpdateDelete operator");
+                    }
+                }
+            } catch (HyracksDataException e) {
+                throw e;
+            } catch (Exception e) {
+                throw new HyracksDataException(e);
+            }
+        }
+        // Pass a copy of the frame to next op.
+        System.arraycopy(buffer.array(), 0, writeBuffer.array(), 0, buffer.capacity());
+        FrameUtils.flushFrame(writeBuffer, writer);
+    }
+
+    @Override
+    public void close() throws HyracksDataException {
+        try {
+            writer.close();
+        } finally {
+            treeIndexHelper.deinit();
+        }
+    }
+
+    @Override
+    public void fail() throws HyracksDataException {
+        writer.fail();
+    }
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexSearchOperatorNodePushable.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexSearchOperatorNodePushable.java
new file mode 100644
index 0000000..5c19483
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexSearchOperatorNodePushable.java
@@ -0,0 +1,160 @@
+/*
+ * 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.DataOutput;
+import java.nio.ByteBuffer;
+
+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.ArrayTupleBuilder;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAccessor;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.FrameTupleAppender;
+import edu.uci.ics.hyracks.dataflow.common.comm.util.FrameUtils;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.FrameTupleReference;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+import edu.uci.ics.hyracks.dataflow.std.base.AbstractUnaryInputUnaryOutputOperatorNodePushable;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexAccessor;
+import edu.uci.ics.hyracks.storage.am.common.api.IIndexCursor;
+import edu.uci.ics.hyracks.storage.am.common.api.ISearchPredicate;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndex;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
+
+public abstract class TreeIndexSearchOperatorNodePushable extends AbstractUnaryInputUnaryOutputOperatorNodePushable {
+    protected final TreeIndexDataflowHelper treeIndexHelper;
+    protected FrameTupleAccessor accessor;
+
+    protected ByteBuffer writeBuffer;
+    protected FrameTupleAppender appender;
+    protected ArrayTupleBuilder tb;
+    protected DataOutput dos;
+
+    protected ITreeIndex treeIndex;
+    protected ISearchPredicate searchPred;
+    protected IIndexCursor cursor;
+    protected ITreeIndexFrame cursorFrame;
+    protected IIndexAccessor indexAccessor;
+
+    protected final RecordDescriptor inputRecDesc;
+    protected final boolean retainInput;
+    protected FrameTupleReference frameTuple;
+
+    public TreeIndexSearchOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc, IHyracksTaskContext ctx,
+            int partition, IRecordDescriptorProvider recordDescProvider) {
+        treeIndexHelper = (TreeIndexDataflowHelper) opDesc.getIndexDataflowHelperFactory().createIndexDataflowHelper(
+                opDesc, ctx, partition);
+        this.retainInput = treeIndexHelper.getOperatorDescriptor().getRetainInput();
+        inputRecDesc = recordDescProvider.getInputRecordDescriptor(opDesc.getActivityId(), 0);
+    }
+
+    protected abstract ISearchPredicate createSearchPredicate();
+
+    protected abstract void resetSearchPredicate(int tupleIndex);
+
+    protected IIndexCursor createCursor() {
+        return indexAccessor.createSearchCursor();
+    }
+
+    @Override
+    public void open() throws HyracksDataException {
+        accessor = new FrameTupleAccessor(treeIndexHelper.getHyracksTaskContext().getFrameSize(), inputRecDesc);
+        writer.open();
+        try {        	
+            treeIndexHelper.init(false);
+            treeIndex = (ITreeIndex) treeIndexHelper.getIndex();
+            cursorFrame = treeIndex.getLeafFrameFactory().createFrame();
+            searchPred = createSearchPredicate();
+            writeBuffer = treeIndexHelper.getHyracksTaskContext().allocateFrame();
+            tb = new ArrayTupleBuilder(recordDesc.getFieldCount());
+            dos = tb.getDataOutput();
+            appender = new FrameTupleAppender(treeIndexHelper.getHyracksTaskContext().getFrameSize());
+            appender.reset(writeBuffer, true);
+            indexAccessor = treeIndex.createAccessor();
+            cursor = createCursor();
+            if (retainInput) {
+            	frameTuple = new FrameTupleReference();
+            }
+        } catch (Exception e) {
+            treeIndexHelper.deinit();
+            throw new HyracksDataException(e);
+        }
+    }
+
+    protected void writeSearchResults(int tupleIndex) throws Exception {
+        while (cursor.hasNext()) {
+            tb.reset();
+            cursor.next();
+            if (retainInput) {
+            	frameTuple.reset(accessor, tupleIndex);
+                for (int i = 0; i < frameTuple.getFieldCount(); i++) {
+                	dos.write(frameTuple.getFieldData(i), frameTuple.getFieldStart(i), frameTuple.getFieldLength(i));
+                    tb.addFieldEndOffset();
+                }
+            }
+            ITupleReference tuple = cursor.getTuple();
+            for (int i = 0; i < tuple.getFieldCount(); i++) {
+                dos.write(tuple.getFieldData(i), tuple.getFieldStart(i), tuple.getFieldLength(i));
+                tb.addFieldEndOffset();
+            }
+            if (!appender.append(tb.getFieldEndOffsets(), tb.getByteArray(), 0, tb.getSize())) {
+                FrameUtils.flushFrame(writeBuffer, writer);
+                appender.reset(writeBuffer, true);
+                if (!appender.append(tb.getFieldEndOffsets(), tb.getByteArray(), 0, tb.getSize())) {
+                    throw new IllegalStateException();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void nextFrame(ByteBuffer buffer) throws HyracksDataException {
+        accessor.reset(buffer);
+        int tupleCount = accessor.getTupleCount();
+        try {
+            for (int i = 0; i < tupleCount; i++) {
+                resetSearchPredicate(i);
+                cursor.reset();
+                indexAccessor.search(cursor, searchPred);
+                writeSearchResults(i);
+            }
+        } catch (Exception e) {
+            throw new HyracksDataException(e);
+        }
+    }
+
+    @Override
+    public void close() throws HyracksDataException {
+        try {
+            if (appender.getTupleCount() > 0) {
+                FrameUtils.flushFrame(writeBuffer, writer);
+            }
+            writer.close();
+            try {
+                cursor.close();
+            } catch (Exception e) {
+                throw new HyracksDataException(e);
+            }
+        } finally {
+            treeIndexHelper.deinit();
+        }
+    }
+
+    @Override
+    public void fail() throws HyracksDataException {
+        writer.fail();
+    }
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java
new file mode 100644
index 0000000..6bf0983
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java
@@ -0,0 +1,49 @@
+/*
+ * 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.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.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.IOperatorDescriptorRegistry;
+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.IOperationCallbackProvider;
+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(IOperatorDescriptorRegistry spec, IStorageManagerInterface storageManager,
+            IIndexRegistryProvider<IIndex> indexRegistryProvider, IFileSplitProvider fileSplitProvider,
+            ITypeTraits[] typeTraits, IBinaryComparatorFactory[] comparatorFactories,
+            IIndexDataflowHelperFactory dataflowHelperFactory, IOperationCallbackProvider opCallbackProvider) {
+        super(spec, 0, 1, recDesc, storageManager, indexRegistryProvider, fileSplitProvider, typeTraits,
+                comparatorFactories, dataflowHelperFactory, null, false, opCallbackProvider);
+    }
+
+    @Override
+    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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java
new file mode 100644
index 0000000..50486f2
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.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.dataflow;
+
+import java.io.DataOutput;
+import java.nio.ByteBuffer;
+
+import edu.uci.ics.hyracks.api.comm.IFrameWriter;
+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.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.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 AbstractUnaryOutputSourceOperatorNodePushable {
+    private final TreeIndexDataflowHelper treeIndexHelper;
+    private final IHyracksTaskContext ctx;
+    private TreeIndexStatsGatherer statsGatherer;
+
+    public TreeIndexStatsOperatorNodePushable(AbstractTreeIndexOperatorDescriptor opDesc, IHyracksTaskContext ctx,
+            int partition) {
+        treeIndexHelper = (TreeIndexDataflowHelper) opDesc.getIndexDataflowHelperFactory().createIndexDataflowHelper(
+                opDesc, ctx, partition);
+        this.ctx = ctx;
+    }
+
+    @Override
+    public void deinitialize() throws HyracksDataException {
+    }
+
+    @Override
+    public IFrameWriter getInputFrameWriter(int index) {
+        return null;
+    }
+
+    @Override
+    public void initialize() throws HyracksDataException {
+        try {
+            writer.open();
+            treeIndexHelper.init(false);
+            ITreeIndex treeIndex = (ITreeIndex) treeIndexHelper.getIndex();
+            IBufferCache bufferCache = treeIndexHelper.getOperatorDescriptor().getStorageManager().getBufferCache(ctx);
+            statsGatherer = new TreeIndexStatsGatherer(bufferCache, treeIndex.getFreePageManager(),
+                    treeIndexHelper.getIndexFileId(), treeIndex.getRootPageId());
+            TreeIndexStats stats = statsGatherer.gatherStats(treeIndex.getLeafFrameFactory().createFrame(), treeIndex
+                    .getInteriorFrameFactory().createFrame(), treeIndex.getFreePageManager().getMetaDataFrameFactory()
+                    .createFrame());
+            // 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) {
+            try {
+                treeIndexHelper.deinit();
+            } finally {
+                writer.fail();
+            }
+        } finally {
+            writer.close();
+        }
+    }
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/DataGenThread.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/DataGenThread.java
new file mode 100644
index 0000000..e8d3d56
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/DataGenThread.java
@@ -0,0 +1,71 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+import java.io.IOException;
+import java.util.Random;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+
+/**
+ * Quick & dirty data generator for multi-thread testing. 
+ *
+ */
+@SuppressWarnings("rawtypes")
+public class DataGenThread extends Thread {
+    public final BlockingQueue<TupleBatch> tupleBatchQueue;
+    private final int maxNumBatches;
+    private final int maxOutstandingBatches;        
+    private int numBatches = 0;
+    private final Random rnd;
+    
+    // maxOutstandingBatches pre-created tuple-batches for populating the queue.
+    private TupleBatch[] tupleBatches;
+    private int ringPos;
+    
+    public DataGenThread(int numConsumers, int maxNumBatches, int batchSize, ISerializerDeserializer[] fieldSerdes, int payloadSize, int rndSeed, int maxOutstandingBatches, boolean sorted) {
+        this.maxNumBatches = maxNumBatches;
+        this.maxOutstandingBatches = maxOutstandingBatches;
+        rnd = new Random(rndSeed);
+        tupleBatches = new TupleBatch[maxOutstandingBatches];
+        IFieldValueGenerator[] fieldGens = DataGenUtils.getFieldGensFromSerdes(fieldSerdes, rnd, sorted);
+        for (int i = 0; i < maxOutstandingBatches; i++) {
+            tupleBatches[i] = new TupleBatch(batchSize, fieldGens, fieldSerdes, payloadSize);
+        }
+        tupleBatchQueue = new LinkedBlockingQueue<TupleBatch>(maxOutstandingBatches);
+        ringPos = 0;
+    }
+    
+    @Override
+    public void run() {
+        while(numBatches < maxNumBatches) {
+            boolean added = false;
+            try {
+                if (tupleBatches[ringPos].inUse.compareAndSet(false, true)) {                    
+                    tupleBatches[ringPos].generate();
+                    tupleBatchQueue.put(tupleBatches[ringPos]);
+                    added = true;
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            if (added) {
+                numBatches++;
+                ringPos++;
+                if (ringPos >= maxOutstandingBatches) {
+                    ringPos = 0;
+                }
+            }
+        }
+    }
+    
+    public TupleBatch getBatch() throws InterruptedException {
+        return tupleBatchQueue.take();
+    }
+    
+    public void releaseBatch(TupleBatch batch) {
+        batch.inUse.set(false);
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/DataGenUtils.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/DataGenUtils.java
new file mode 100644
index 0000000..fdbaa3e
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/DataGenUtils.java
@@ -0,0 +1,46 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+import java.util.Random;
+
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.DoubleSerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.FloatSerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.IntegerSerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.UTF8StringSerializerDeserializer;
+
+@SuppressWarnings("rawtypes") 
+public class DataGenUtils {
+    public static IFieldValueGenerator getFieldGenFromSerde(ISerializerDeserializer serde, Random rnd, boolean sorted) {
+        if (serde instanceof IntegerSerializerDeserializer) {
+            if (sorted) {
+                return new SortedIntegerFieldValueGenerator();
+            } else {
+                return new IntegerFieldValueGenerator(rnd);
+            }
+        } else if (serde instanceof FloatSerializerDeserializer) {
+            if (sorted) {
+                return new SortedFloatFieldValueGenerator();
+            } else {
+                return new FloatFieldValueGenerator(rnd);
+            }
+        } else if (serde instanceof DoubleSerializerDeserializer) {
+            if (sorted) {
+                return new SortedDoubleFieldValueGenerator();
+            } else {
+                return new DoubleFieldValueGenerator(rnd);
+            }
+        } else if (serde instanceof UTF8StringSerializerDeserializer) {
+            return new StringFieldValueGenerator(20, rnd);
+        }
+        System.out.println("NULL");
+        return null;
+    }
+    
+    public static IFieldValueGenerator[] getFieldGensFromSerdes(ISerializerDeserializer[] serdes, Random rnd, boolean sorted) {
+        IFieldValueGenerator[] fieldValueGens = new IFieldValueGenerator[serdes.length];
+        for (int i = 0; i < serdes.length; i++) {
+            fieldValueGens[i] = getFieldGenFromSerde(serdes[i], rnd, sorted);
+        }
+        return fieldValueGens;
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/DoubleFieldValueGenerator.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/DoubleFieldValueGenerator.java
new file mode 100644
index 0000000..fcac93a
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/DoubleFieldValueGenerator.java
@@ -0,0 +1,16 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+import java.util.Random;
+
+public class DoubleFieldValueGenerator implements IFieldValueGenerator<Double> {
+    protected final Random rnd;
+
+    public DoubleFieldValueGenerator(Random rnd) {
+        this.rnd = rnd;
+    }
+
+    @Override
+    public Double next() {
+        return rnd.nextDouble();
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/FloatFieldValueGenerator.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/FloatFieldValueGenerator.java
new file mode 100644
index 0000000..6f21c77
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/FloatFieldValueGenerator.java
@@ -0,0 +1,16 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+import java.util.Random;
+
+public class FloatFieldValueGenerator implements IFieldValueGenerator<Float> {
+    protected final Random rnd;
+
+    public FloatFieldValueGenerator(Random rnd) {
+        this.rnd = rnd;
+    }
+
+    @Override
+    public Float next() {
+        return rnd.nextFloat();
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/IFieldValueGenerator.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/IFieldValueGenerator.java
new file mode 100644
index 0000000..ee0d30b
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/IFieldValueGenerator.java
@@ -0,0 +1,5 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+public interface IFieldValueGenerator<T> {
+    public T next();
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/IntegerFieldValueGenerator.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/IntegerFieldValueGenerator.java
new file mode 100644
index 0000000..134b1f7
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/IntegerFieldValueGenerator.java
@@ -0,0 +1,16 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+import java.util.Random;
+
+public class IntegerFieldValueGenerator implements IFieldValueGenerator<Integer> {
+    protected final Random rnd;
+
+    public IntegerFieldValueGenerator(Random rnd) {
+        this.rnd = rnd;
+    }
+
+    @Override
+    public Integer next() {
+        return rnd.nextInt();
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/SortedDoubleFieldValueGenerator.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/SortedDoubleFieldValueGenerator.java
new file mode 100644
index 0000000..4193811
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/SortedDoubleFieldValueGenerator.java
@@ -0,0 +1,17 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+public class SortedDoubleFieldValueGenerator implements IFieldValueGenerator<Double> {
+    private double val = 0.0d;
+
+    public SortedDoubleFieldValueGenerator() {
+    }
+    
+    public SortedDoubleFieldValueGenerator(double startVal) {
+        val = startVal;
+    }
+    
+    @Override
+    public Double next() {
+        return val++;
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/SortedFloatFieldValueGenerator.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/SortedFloatFieldValueGenerator.java
new file mode 100644
index 0000000..1f6b315
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/SortedFloatFieldValueGenerator.java
@@ -0,0 +1,17 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+public class SortedFloatFieldValueGenerator implements IFieldValueGenerator<Float> {
+    private float val = 0.0f;
+
+    public SortedFloatFieldValueGenerator() {
+    }
+    
+    public SortedFloatFieldValueGenerator(float startVal) {
+        val = startVal;
+    }
+    
+    @Override
+    public Float next() {
+        return val++;
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/SortedIntegerFieldValueGenerator.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/SortedIntegerFieldValueGenerator.java
new file mode 100644
index 0000000..8f7fdcf
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/SortedIntegerFieldValueGenerator.java
@@ -0,0 +1,17 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+public class SortedIntegerFieldValueGenerator implements IFieldValueGenerator<Integer> {
+    private int val = 0;
+
+    public SortedIntegerFieldValueGenerator() {
+    }
+    
+    public SortedIntegerFieldValueGenerator(int startVal) {
+        val = startVal;
+    }
+    
+    @Override
+    public Integer next() {
+        return val++;
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/StringFieldValueGenerator.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/StringFieldValueGenerator.java
new file mode 100644
index 0000000..0218542
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/StringFieldValueGenerator.java
@@ -0,0 +1,27 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+import java.util.Random;
+
+public class StringFieldValueGenerator implements IFieldValueGenerator<String> {
+    private int maxLen;
+    private final Random rnd;
+    
+    public StringFieldValueGenerator(int maxLen, Random rnd) {
+        this.maxLen = maxLen;
+        this.rnd = rnd;
+    }
+
+    public void setMaxLength(int maxLen) {
+        this.maxLen = maxLen;
+    }
+    
+    @Override
+    public String next() {
+        String s = Long.toHexString(Double.doubleToLongBits(rnd.nextDouble()));
+        StringBuilder strBuilder = new StringBuilder();
+        for (int i = 0; i < s.length() && i < maxLen; i++) {
+            strBuilder.append(s.charAt(Math.abs(rnd.nextInt()) % s.length()));
+        }
+        return strBuilder.toString();
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/TupleBatch.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/TupleBatch.java
new file mode 100644
index 0000000..bfa523f
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/TupleBatch.java
@@ -0,0 +1,36 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+
+@SuppressWarnings("rawtypes")
+public class TupleBatch {
+    private final int size;
+    private final TupleGenerator[] tupleGens;
+    public final AtomicBoolean inUse = new AtomicBoolean(false);
+    
+    public TupleBatch(int size, IFieldValueGenerator[] fieldGens, ISerializerDeserializer[] fieldSerdes, int payloadSize) {        
+        this.size = size;
+        tupleGens = new TupleGenerator[size];
+        for (int i = 0; i < size; i++) {
+            tupleGens[i] = new TupleGenerator(fieldGens, fieldSerdes, payloadSize);
+        }
+    }
+    
+    public void generate() throws IOException {
+        for(TupleGenerator tupleGen : tupleGens) {
+            tupleGen.next();
+        }
+    }
+    
+    public int size() {
+        return size;
+    }
+    
+    public ITupleReference get(int ix) {
+        return tupleGens[ix].get();
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/TupleGenerator.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/TupleGenerator.java
new file mode 100644
index 0000000..2801205
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/datagen/TupleGenerator.java
@@ -0,0 +1,51 @@
+package edu.uci.ics.hyracks.storage.am.common.datagen;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
+import edu.uci.ics.hyracks.dataflow.common.comm.io.ArrayTupleReference;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+
+@SuppressWarnings({"rawtypes", "unchecked" })
+public class TupleGenerator {    
+    protected final ISerializerDeserializer[] fieldSerdes;
+    protected final IFieldValueGenerator[] fieldGens;
+    protected final ArrayTupleBuilder tb;
+    protected final ArrayTupleReference tuple;
+    protected final byte[] payload;
+    protected final DataOutput tbDos;
+    
+    public TupleGenerator(IFieldValueGenerator[] fieldGens, ISerializerDeserializer[] fieldSerdes, int payloadSize) {
+        this.fieldSerdes = fieldSerdes;
+        this.fieldGens = fieldGens;
+        tuple = new ArrayTupleReference();
+        if (payloadSize > 0) {
+            tb = new ArrayTupleBuilder(fieldSerdes.length + 1);
+            payload = new byte[payloadSize];
+        } else {
+            tb = new ArrayTupleBuilder(fieldSerdes.length);
+            payload = null;
+        }        
+        tbDos = tb.getDataOutput();
+    }
+
+    public ITupleReference next() throws IOException {
+        tb.reset();
+        for (int i = 0; i < fieldSerdes.length; i++) {
+            fieldSerdes[i].serialize(fieldGens[i].next(), tbDos);
+            tb.addFieldEndOffset();
+        }
+        if (payload != null) {
+            tbDos.write(payload);
+            tb.addFieldEndOffset();
+        }
+        tuple.reset(tb.getFieldEndOffsets(), tb.getByteArray());
+        return tuple;
+    }
+    
+    public ITupleReference get() {
+        return tuple;
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/AbstractSlotManager.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/AbstractSlotManager.java
new file mode 100644
index 0000000..a1a38ab
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/AbstractSlotManager.java
@@ -0,0 +1,74 @@
+/*
+ * 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.frames;
+
+import edu.uci.ics.hyracks.storage.am.common.api.ISlotManager;
+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;
+
+	@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 int getErrorIndicator() {
+        return ERROR_INDICATOR;
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/FrameOpSpaceStatus.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/FrameOpSpaceStatus.java
new file mode 100644
index 0000000..da9c815
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/FrameOpSpaceStatus.java
@@ -0,0 +1,20 @@
+/*
+ * 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.frames;
+
+public enum FrameOpSpaceStatus {
+    INSUFFICIENT_SPACE, SUFFICIENT_CONTIGUOUS_SPACE, SUFFICIENT_SPACE, SUFFICIENT_INPLACE_SPACE
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java
new file mode 100644
index 0000000..31c674d
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java
@@ -0,0 +1,134 @@
+/*
+ * 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.frames;
+
+import java.nio.ByteBuffer;
+
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
+import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
+
+// all meta pages of this kind have a negative level
+// the first meta page has level -1, all other meta pages have level -2
+// the first meta page is special because it guarantees to have a correct max page
+// other meta pages (i.e., with level -2) have junk in the max page field
+
+public class LIFOMetaDataFrame implements ITreeIndexMetaDataFrame {
+
+    // Arbitrarily chosen magic integer.
+    protected static final int MAGIC_VALID_INT = 0x5bd1e995;
+    
+	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 static final int validOff = nextPageOff + 4; // 25
+
+	protected ICachedPage page = null;
+	protected ByteBuffer buf = null;
+
+	public int getMaxPage() {
+		return buf.getInt(maxPageOff);
+	}
+
+	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;
+		}
+	}
+
+	// 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();
+	}
+
+	// no 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 void setLevel(byte level) {
+		buf.put(levelOff, level);
+	}
+
+	@Override
+	public ICachedPage getPage() {
+		return page;
+	}
+
+	@Override
+	public void setPage(ICachedPage page) {
+		this.page = page;
+		this.buf = page.getBuffer();
+	}
+
+	@Override
+	public void initBuffer(byte level) {
+		buf.putInt(tupleCountOff, 0);
+		buf.putInt(freeSpaceOff, validOff + 4);
+		//buf.putInt(maxPageOff, -1);
+		buf.put(levelOff, level);
+		buf.putInt(nextPageOff, -1);
+		setValid(false);
+	}
+
+	@Override
+	public int getNextPage() {
+		return buf.getInt(nextPageOff);
+	}
+
+	@Override
+	public void setNextPage(int nextPage) {
+		buf.putInt(nextPageOff, nextPage);
+	}
+
+    @Override
+    public boolean isValid() {
+        return buf.getInt(validOff) == MAGIC_VALID_INT;
+    }
+
+    @Override
+    public void setValid(boolean isValid) {
+        if (isValid) {
+            buf.putInt(validOff, MAGIC_VALID_INT);
+        } else {
+            buf.putInt(validOff, 0);
+        }
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java
new file mode 100644
index 0000000..68d1ee3
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java
@@ -0,0 +1,26 @@
+/*
+ * 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.frames;
+
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrameFactory;
+
+public class LIFOMetaDataFrameFactory implements ITreeIndexMetaDataFrameFactory {
+	@Override
+	public ITreeIndexMetaDataFrame createFrame() {
+		return new LIFOMetaDataFrame();
+	}
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java
new file mode 100644
index 0000000..e2e28fd
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java
@@ -0,0 +1,295 @@
+/*
+ * 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.frames;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+
+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.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 + 8; // 8
+    protected static final int freeSpaceOff = tupleCountOff + 4; // 12
+    protected static final int totalFreeSpaceOff = freeSpaceOff + 4; // 16
+    protected static final int levelOff = totalFreeSpaceOff + 4; // 20
+    protected static final int smFlagOff = levelOff + 1; // 21
+
+    protected ICachedPage page = null;
+    protected ByteBuffer buf = null;
+    protected ISlotManager slotManager;
+
+    protected ITreeIndexTupleWriter tupleWriter;
+    protected ITreeIndexTupleReference frameTuple;
+
+    public TreeIndexNSMFrame(ITreeIndexTupleWriter tupleWriter, ISlotManager slotManager) {
+        this.tupleWriter = tupleWriter;
+        this.frameTuple = tupleWriter.createTupleReference();
+        this.slotManager = slotManager;
+        this.slotManager.setFrame(this);
+    }
+
+    @Override
+    public void initBuffer(byte level) {
+        buf.putLong(pageLsnOff, 0); // TODO: might to set to a different lsn
+        // during creation
+        buf.putInt(tupleCountOff, 0);
+        resetSpaceParams();
+        buf.put(levelOff, level);
+        buf.put(smFlagOff, (byte) 0);
+    }
+
+    @Override
+    public boolean isLeaf() {
+        return buf.get(levelOff) == 0;
+    }
+
+    @Override
+    public boolean isInterior() {
+        return buf.get(levelOff) > 0;
+    }
+
+    @Override
+    public byte getLevel() {
+        return buf.get(levelOff);
+    }
+
+    @Override
+    public void setLevel(byte level) {
+        buf.put(levelOff, level);
+    }
+
+    @Override
+    public int getFreeSpaceOff() {
+        return buf.getInt(freeSpaceOff);
+    }
+
+    @Override
+    public void setFreeSpaceOff(int freeSpace) {
+        buf.putInt(freeSpaceOff, freeSpace);
+    }
+
+    @Override
+    public void setPage(ICachedPage page) {
+        this.page = page;
+        this.buf = page.getBuffer();
+    }
+
+    @Override
+    public ByteBuffer getBuffer() {
+        return page.getBuffer();
+    }
+
+    @Override
+    public ICachedPage getPage() {
+        return page;
+    }
+
+    @Override
+    public boolean compact() {
+        resetSpaceParams();
+        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++) {
+            int slotOff = slotManager.getSlotOff(i);
+            int tupleOff = slotManager.getTupleOff(slotOff);
+            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, int tupleIndex) {
+        int slotOff = slotManager.getSlotOff(tupleIndex);
+        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());
+    }
+
+    @Override
+    public FrameOpSpaceStatus hasSpaceInsert(ITupleReference tuple) {
+        int bytesRequired = tupleWriter.bytesRequired(tuple);
+        // 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;
+        }
+        // Enough space after compaction?
+        if (bytesRequired + slotManager.getSlotSize() <= buf.getInt(totalFreeSpaceOff)) {
+            return FrameOpSpaceStatus.SUFFICIENT_SPACE;
+        }
+        return FrameOpSpaceStatus.INSUFFICIENT_SPACE;
+    }
+
+    @Override
+    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;
+    }
+
+    protected void resetSpaceParams() {
+        buf.putInt(freeSpaceOff, smFlagOff + 1);
+        buf.putInt(totalFreeSpaceOff, buf.capacity() - (smFlagOff + 1));
+    }
+
+    @Override
+    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);
+        buf.putInt(freeSpaceOff, buf.getInt(freeSpaceOff) + bytesWritten);
+        buf.putInt(totalFreeSpaceOff, buf.getInt(totalFreeSpaceOff) - bytesWritten - slotManager.getSlotSize());
+    }
+
+    @Override
+    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 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
+    public int getTupleCount() {
+        return buf.getInt(tupleCountOff);
+    }
+
+    public ISlotManager getSlotManager() {
+        return slotManager;
+    }
+
+    @Override
+    public int getTupleOffset(int slotNum) {
+        return slotManager.getTupleOff(slotManager.getSlotStartOff() - slotNum * slotManager.getSlotSize());
+    }
+
+    @Override
+    public long getPageLsn() {
+        return buf.getLong(pageLsnOff);
+    }
+
+    @Override
+    public void setPageLsn(long pageLsn) {
+        buf.putLong(pageLsnOff, pageLsn);
+    }
+
+    @Override
+    public int getTotalFreeSpace() {
+        return buf.getInt(totalFreeSpaceOff);
+    }
+
+    @Override
+    public boolean compress() {
+        return false;
+    }
+
+    @Override
+    public int getSlotSize() {
+        return slotManager.getSlotSize();
+    }
+
+    @Override
+    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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/freepage/LinkedListFreePageManager.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/freepage/LinkedListFreePageManager.java
new file mode 100644
index 0000000..036aa09
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/freepage/LinkedListFreePageManager.java
@@ -0,0 +1,216 @@
+package edu.uci.ics.hyracks.storage.am.common.freepage;
+
+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.ITreeIndexMetaDataFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrameFactory;
+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 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 headPage;	
+	private int fileId = -1;
+	private final ITreeIndexMetaDataFrameFactory metaDataFrameFactory;
+
+	public LinkedListFreePageManager(IBufferCache bufferCache,
+			int headPage, ITreeIndexMetaDataFrameFactory metaDataFrameFactory) {
+		this.bufferCache = bufferCache;
+		this.headPage = headPage;
+		this.metaDataFrameFactory = metaDataFrameFactory;
+	}
+
+	@Override
+	public void addFreePage(ITreeIndexMetaDataFrame metaFrame, int freePage)
+			throws HyracksDataException {
+
+		ICachedPage metaNode = bufferCache.pin(
+				BufferedFileHandle.getDiskPageId(fileId, headPage), false);
+		metaNode.acquireWriteLatch();
+
+		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.");
+				}
+
+				ICachedPage newNode = bufferCache.pin(
+						BufferedFileHandle.getDiskPageId(fileId, newPage),
+						false);
+				newNode.acquireWriteLatch();
+
+				try {
+					int metaMaxPage = metaFrame.getMaxPage();
+
+					// 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);
+		}
+	}
+
+	@Override
+	public int getFreePage(ITreeIndexMetaDataFrame metaFrame)
+			throws HyracksDataException {
+		ICachedPage metaNode = bufferCache.pin(
+				BufferedFileHandle.getDiskPageId(fileId, headPage), false);
+
+		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);
+
+					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());
+
+						// 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);
+		}
+
+		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 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);
+		}
+	}
+
+	@Override
+	public ITreeIndexMetaDataFrameFactory getMetaDataFrameFactory() {
+		return metaDataFrameFactory;
+	}
+
+	@Override
+	public byte getFreePageLevelIndicator() {
+		return FREE_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 isMetaPage(ITreeIndexMetaDataFrame metaFrame) {
+		return metaFrame.getLevel() == META_PAGE_LEVEL_INDICATOR;
+	}
+
+    @Override
+    public int getFirstMetadataPage() {
+        return headPage;
+    }
+
+	@Override
+	public void open(int fileId) {
+		this.fileId = fileId;
+	}
+
+	@Override
+	public void close() {
+		fileId = -1;
+	}
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/freepage/LinkedListFreePageManagerFactory.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/freepage/LinkedListFreePageManagerFactory.java
new file mode 100644
index 0000000..157b563
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/freepage/LinkedListFreePageManagerFactory.java
@@ -0,0 +1,35 @@
+/*
+ * 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.freepage;
+
+import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrameFactory;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+
+public class LinkedListFreePageManagerFactory {
+
+	private final ITreeIndexMetaDataFrameFactory metaDataFrameFactory;
+	private final IBufferCache bufferCache;
+	
+	public LinkedListFreePageManagerFactory(IBufferCache bufferCache, ITreeIndexMetaDataFrameFactory metaDataFrameFactory) {
+		this.metaDataFrameFactory = metaDataFrameFactory;
+		this.bufferCache = bufferCache;
+	}
+	
+    public IFreePageManager createFreePageManager() {
+        return new LinkedListFreePageManager(bufferCache, 0, metaDataFrameFactory);
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/NoOpOperationCallback.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/NoOpOperationCallback.java
new file mode 100644
index 0000000..828dd81
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/NoOpOperationCallback.java
@@ -0,0 +1,41 @@
+/*
+ * 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.impls;
+
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+import edu.uci.ics.hyracks.storage.am.common.api.IOperationCallback;
+
+/**
+ * Dummy operation callback that simply does nothing. Mainly, intended to be
+ * used in non-transaction access method testing.
+ */
+public class NoOpOperationCallback implements IOperationCallback {
+
+    public static IOperationCallback INSTANCE = new NoOpOperationCallback();
+    
+    private NoOpOperationCallback() {
+    }
+    
+    @Override
+    public void pre(ITupleReference tuple) {
+        // Do nothing.
+    }
+
+    @Override
+    public void post(ITupleReference tuple) {
+        // Do nothing.
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/NoOpOperationCallbackProvider.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/NoOpOperationCallbackProvider.java
new file mode 100644
index 0000000..55dfb74e
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/NoOpOperationCallbackProvider.java
@@ -0,0 +1,19 @@
+package edu.uci.ics.hyracks.storage.am.common.impls;
+
+import edu.uci.ics.hyracks.storage.am.common.api.IOperationCallback;
+import edu.uci.ics.hyracks.storage.am.common.api.IOperationCallbackProvider;
+
+/**
+ * Dummy NoOp callback provider used primarily for testing. Always returns the 
+ * {@link NoOpOperationCallback} instance. 
+ *
+ * Implemented as an enum to preserve singleton model while being serializable
+ */
+public enum NoOpOperationCallbackProvider implements IOperationCallbackProvider {
+    INSTANCE;
+
+    @Override
+    public IOperationCallback getOperationCallback() {
+        return NoOpOperationCallback.INSTANCE;
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/TreeDiskOrderScanCursor.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/TreeDiskOrderScanCursor.java
new file mode 100644
index 0000000..ea4c105
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/impls/TreeDiskOrderScanCursor.java
@@ -0,0 +1,154 @@
+/*
+ * 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.impls;
+
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.storage.am.common.api.ICursorInitialState;
+import edu.uci.ics.hyracks.storage.am.common.api.ISearchPredicate;
+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.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;
+	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();
+	}
+
+	@Override
+	public void close() throws HyracksDataException {
+		page.releaseReadLatch();
+		bufferCache.unpin(page);
+		page = null;
+	}
+
+	@Override
+	public ITreeIndexTupleReference getTuple() {
+		return frameTuple;
+	}
+
+	@Override
+	public ICachedPage getPage() {
+		return page;
+	}
+
+	private boolean positionToNextLeaf(boolean skipCurrent)
+			throws HyracksDataException {
+		while ((frame.getLevel() != 0 || skipCurrent || frame.getTupleCount() == 0) && (currentPageId <= maxPageId)) {
+			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;
+		}
+	}
+
+	@Override
+	public boolean hasNext() throws HyracksDataException {		
+		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;
+	}
+
+	@Override
+	public void next() throws HyracksDataException {
+		tupleIndex++;
+	}
+
+	@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);
+	}
+
+	@Override
+	public void reset() {
+		tupleIndex = 0;
+		currentPageId = -1;
+		maxPageId = -1;
+		page = null;
+	}
+
+	@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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleMode.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleMode.java
new file mode 100644
index 0000000..5002189
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleMode.java
@@ -0,0 +1,20 @@
+/*
+ * 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 enum FindTupleMode {
+	INCLUSIVE, EXCLUSIVE, EXCLUSIVE_ERROR_IF_EXISTS, EXACT
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleNoExactMatchPolicy.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleNoExactMatchPolicy.java
new file mode 100644
index 0000000..8b3f7f5
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/FindTupleNoExactMatchPolicy.java
@@ -0,0 +1,20 @@
+/*
+ * 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 enum FindTupleNoExactMatchPolicy {
+	LOWER_KEY, HIGHER_KEY, NONE
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IndexOp.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IndexOp.java
new file mode 100644
index 0000000..77ad7ff
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IndexOp.java
@@ -0,0 +1,20 @@
+/*
+ * 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 enum IndexOp {
+	INSERT, DELETE, UPDATE, UPSERT, SEARCH, DISKORDERSCAN, PHYSICALDELETE
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IntArrayList.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IntArrayList.java
new file mode 100644
index 0000000..12bc997
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/IntArrayList.java
@@ -0,0 +1,98 @@
+/*
+ * 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 IntArrayList {
+    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 int size() {
+        return size;
+    }
+
+    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;
+        }
+
+        data[size++] = i;
+    }
+
+    public void addFirst(int i) {
+        int[] newData = new int[data.length + 1];
+        System.arraycopy(data, 0, newData, 0, first);
+        System.arraycopy(data, first, newData, first + 1, size - first);
+        data = newData;
+        data[first] = i;
+        size++;
+    }
+
+    public void removeLast() {
+        if (size > 0)
+            size--;
+    }
+
+    // WARNING: caller is responsible for checking size > 0
+    public int getLast() {
+        return data[size - 1];
+    }
+
+    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;
+
+    }
+
+    public int 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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/LongArrayList.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/LongArrayList.java
new file mode 100644
index 0000000..cb4c8fe
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/LongArrayList.java
@@ -0,0 +1,99 @@
+/*
+ * 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 addFirst(long i) {
+	    long[] newData = new long[data.length + 1];
+        System.arraycopy(data, 0, newData, 0, first);
+        System.arraycopy(data, first, newData, first + 1, size - first);
+        data = newData;
+        data[first] = i;
+        size++;
+    }
+
+
+	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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/MultiComparator.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/MultiComparator.java
new file mode 100644
index 0000000..c653c9a
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/MultiComparator.java
@@ -0,0 +1,90 @@
+/*
+ * 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;
+
+import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparator;
+import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+
+public class MultiComparator {
+
+	private final IBinaryComparator[] cmps;
+
+	public MultiComparator(IBinaryComparator[] cmps) {
+		this.cmps = cmps;
+	}
+
+	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 int compare(ITupleReference tupleA,
+			ITupleReference tupleB, int startFieldIndex) {
+		for (int i = 0; i < cmps.length; i++) {
+			int ix = startFieldIndex + i;
+			int cmp = cmps[i].compare(tupleA.getFieldData(ix),
+					tupleA.getFieldStart(ix), tupleA.getFieldLength(ix),
+					tupleB.getFieldData(ix), tupleB.getFieldStart(ix),
+					tupleB.getFieldLength(ix));
+			if (cmp < 0)
+				return -1;
+			else if (cmp > 0)
+				return 1;
+		}
+		return 0;
+	}
+
+	public IBinaryComparator[] getComparators() {
+		return cmps;
+	}
+
+    public int getKeyFieldCount() {
+		return cmps.length;
+	}
+    
+    public static MultiComparator create(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);
+    }
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/SlotOffTupleOff.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/SlotOffTupleOff.java
new file mode 100644
index 0000000..7e9042c
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/ophelpers/SlotOffTupleOff.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.ophelpers;
+
+public class SlotOffTupleOff implements Comparable<SlotOffTupleOff> {
+	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;
+	}
+
+	@Override
+	public int compareTo(SlotOffTupleOff o) {
+		return tupleOff - o.tupleOff;
+	}
+	
+	@Override 
+	public String toString() {
+		return tupleIndex + " " + slotOff + " " + tupleOff;
+	}
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleReference.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleReference.java
new file mode 100644
index 0000000..a470d04
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleReference.java
@@ -0,0 +1,99 @@
+/*
+ * 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.tuples;
+
+import java.nio.ByteBuffer;
+
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleReference;
+
+public class SimpleTupleReference implements ITreeIndexTupleReference {
+
+    protected ByteBuffer buf;
+    protected int fieldStartIndex;
+    protected int fieldCount;
+    protected int tupleStartOff;
+    protected int nullFlagsBytes;
+    protected int fieldSlotsBytes;
+
+    @Override
+    public void resetByTupleOffset(ByteBuffer buf, int tupleStartOff) {
+        this.buf = buf;
+        this.tupleStartOff = tupleStartOff;
+    }
+
+    @Override
+    public void resetByTupleIndex(ITreeIndexFrame frame, int tupleIndex) {
+        resetByTupleOffset(frame.getBuffer(), frame.getTupleOffset(tupleIndex));
+    }
+
+    @Override
+    public void setFieldCount(int fieldCount) {
+        this.fieldCount = fieldCount;
+        nullFlagsBytes = getNullFlagsBytes();
+        fieldSlotsBytes = getFieldSlotsBytes();
+        fieldStartIndex = 0;
+    }
+
+    @Override
+    public void setFieldCount(int fieldStartIndex, int fieldCount) {
+        this.fieldCount = fieldCount;
+        this.fieldStartIndex = fieldStartIndex;
+    }
+
+    @Override
+    public int getFieldCount() {
+        return fieldCount;
+    }
+
+    @Override
+    public byte[] getFieldData(int fIdx) {
+        return buf.array();
+    }
+
+    @Override
+    public int getFieldLength(int fIdx) {
+        if (fIdx == 0) {
+            return buf.getShort(tupleStartOff + nullFlagsBytes);
+        } else {
+            return buf.getShort(tupleStartOff + nullFlagsBytes + fIdx * 2)
+                    - buf.getShort(tupleStartOff + nullFlagsBytes + ((fIdx - 1) * 2));
+        }
+    }
+
+    @Override
+    public int getFieldStart(int fIdx) {
+        if (fIdx == 0) {
+            return tupleStartOff + nullFlagsBytes + fieldSlotsBytes;
+        } else {
+            return tupleStartOff + nullFlagsBytes + fieldSlotsBytes
+                    + buf.getShort(tupleStartOff + nullFlagsBytes + ((fIdx - 1) * 2));
+        }
+    }
+
+    protected int getNullFlagsBytes() {
+        return (int) Math.ceil(fieldCount / 8.0);
+    }
+
+    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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriter.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriter.java
new file mode 100644
index 0000000..f5ec5f3
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriter.java
@@ -0,0 +1,119 @@
+/*
+ * 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.tuples;
+
+import java.nio.ByteBuffer;
+
+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 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);
+	}
+	
+    @Override
+    public int bytesRequired(ITupleReference tuple) {
+        int bytes = getNullFlagsBytes(tuple) + getFieldSlotsBytes(tuple);
+        for (int i = 0; i < tuple.getFieldCount(); i++) {
+            bytes += tuple.getFieldLength(i);
+        }
+        return bytes;
+    }
+
+    @Override
+    public int bytesRequired(ITupleReference tuple, int startField, int numFields) {
+        int bytes = getNullFlagsBytes(tuple, startField, numFields) + getFieldSlotsBytes(tuple, startField, numFields);
+        for (int i = startField; i < startField + numFields; i++) {
+            bytes += tuple.getFieldLength(i);
+        }
+        return bytes;
+    }
+
+    @Override
+    public ITreeIndexTupleReference createTupleReference() {
+        return new SimpleTupleReference();
+    }
+
+    @Override
+    public int writeTuple(ITupleReference tuple, ByteBuffer targetBuf, int targetOff) {
+        return writeTuple(tuple, targetBuf.array(), targetOff);
+    }
+    
+    @Override
+	public int writeTuple(ITupleReference tuple, byte[] targetBuf, int targetOff) {
+    	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
+    public int writeTupleFields(ITupleReference tuple, int startField, int numFields, byte[] targetBuf,
+            int targetOff) {
+        int runner = targetOff;
+        int nullFlagsBytes = getNullFlagsBytes(tuple, startField, numFields);
+        for (int i = 0; i < nullFlagsBytes; i++) {
+            targetBuf[runner++] = (byte) 0;
+        }
+        runner += getFieldSlotsBytes(tuple, startField, numFields);
+
+        int fieldEndOff = 0;
+        int fieldCounter = 0;
+        for (int i = startField; i < startField + numFields; 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 + fieldCounter * 2);
+            fieldCounter++;
+        }
+
+        return runner - targetOff;
+    }
+
+    protected int getNullFlagsBytes(ITupleReference tuple) {
+        return (int) Math.ceil((double) tuple.getFieldCount() / 8.0);
+    }
+
+    protected int getFieldSlotsBytes(ITupleReference tuple) {
+        return tuple.getFieldCount() * 2;
+    }
+
+    protected int getNullFlagsBytes(ITupleReference tuple, int startField, int numFields) {
+        return (int) Math.ceil((double) numFields / 8.0);
+    }
+
+    protected int getFieldSlotsBytes(ITupleReference tuple, int startField, int numFields) {
+        return numFields * 2;
+    }	
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriterFactory.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriterFactory.java
new file mode 100644
index 0000000..10d4c3a
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/SimpleTupleWriterFactory.java
@@ -0,0 +1,30 @@
+/*
+ * 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.tuples;
+
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleWriter;
+import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexTupleWriterFactory;
+
+public class SimpleTupleWriterFactory implements ITreeIndexTupleWriterFactory {
+
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	public ITreeIndexTupleWriter createTupleWriter() {
+		return new SimpleTupleWriter();
+	}
+
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleReference.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleReference.java
new file mode 100644
index 0000000..4776bdd
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleReference.java
@@ -0,0 +1,125 @@
+/*
+ * 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.tuples;
+
+import java.nio.ByteBuffer;
+
+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;
+
+public class TypeAwareTupleReference implements ITreeIndexTupleReference {
+    protected ByteBuffer buf;
+    protected int fieldStartIndex;
+    protected int fieldCount;
+    protected int tupleStartOff;
+    protected int nullFlagsBytes;
+    protected int dataStartOff;
+
+    protected ITypeTraits[] typeTraits;
+    protected VarLenIntEncoderDecoder encDec = new VarLenIntEncoderDecoder();
+    protected int[] decodedFieldSlots;
+
+    public TypeAwareTupleReference(ITypeTraits[] typeTraits) {
+        this.typeTraits = typeTraits;
+        this.fieldStartIndex = 0;
+        setFieldCount(typeTraits.length);
+    }
+
+    @Override
+    public void resetByTupleOffset(ByteBuffer buf, int tupleStartOff) {
+        this.buf = buf;
+        this.tupleStartOff = tupleStartOff;
+
+        // decode field slots
+        int field = 0;
+        int cumul = 0;
+        int end = fieldStartIndex + fieldCount;
+        encDec.reset(buf.array(), tupleStartOff + nullFlagsBytes);
+        for (int i = fieldStartIndex; i < end; i++) {
+            if (!typeTraits[i].isFixedLength()) {
+                cumul += encDec.decode();
+                decodedFieldSlots[field++] = cumul;
+            } else {
+                cumul += typeTraits[i].getFixedLength();
+                decodedFieldSlots[field++] = cumul;
+            }
+        }
+        dataStartOff = encDec.getPos();
+    }
+
+    @Override
+    public void resetByTupleIndex(ITreeIndexFrame frame, int tupleIndex) {
+        resetByTupleOffset(frame.getBuffer(), frame.getTupleOffset(tupleIndex));
+    }
+
+    @Override
+    public void setFieldCount(int fieldCount) {
+        this.fieldCount = fieldCount;
+        if (decodedFieldSlots == null) {
+            decodedFieldSlots = new int[fieldCount];
+        } else {
+            if (fieldCount > decodedFieldSlots.length) {
+                decodedFieldSlots = new int[fieldCount];
+            }
+        }
+        nullFlagsBytes = getNullFlagsBytes();
+        this.fieldStartIndex = 0;
+    }
+
+    @Override
+    public void setFieldCount(int fieldStartIndex, int fieldCount) {
+        setFieldCount(fieldCount);
+        this.fieldStartIndex = fieldStartIndex;
+    }
+
+    @Override
+    public int getFieldCount() {
+        return fieldCount;
+    }
+
+    @Override
+    public byte[] getFieldData(int fIdx) {
+        return buf.array();
+    }
+
+    @Override
+    public int getFieldLength(int fIdx) {
+        if (fIdx == 0) {
+            return decodedFieldSlots[0];
+        } else {
+            return decodedFieldSlots[fIdx] - decodedFieldSlots[fIdx - 1];
+        }
+    }
+
+    @Override
+    public int getFieldStart(int fIdx) {
+        if (fIdx == 0) {
+            return dataStartOff;
+        } else {
+            return dataStartOff + decodedFieldSlots[fIdx - 1];
+        }
+    }
+
+    protected int getNullFlagsBytes() {
+        return (int) Math.ceil(fieldCount / 8.0);
+    }
+
+    @Override
+    public int getTupleSize() {
+        return dataStartOff - tupleStartOff + decodedFieldSlots[fieldCount - 1];
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriter.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriter.java
new file mode 100644
index 0000000..9730346
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriter.java
@@ -0,0 +1,152 @@
+/*
+ * 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.tuples;
+
+import java.nio.ByteBuffer;
+
+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 ITypeTraits[] typeTraits;
+    protected VarLenIntEncoderDecoder encDec = new VarLenIntEncoderDecoder();
+
+    public TypeAwareTupleWriter(ITypeTraits[] typeTraits) {
+        this.typeTraits = typeTraits;
+    }
+
+    @Override
+    public int bytesRequired(ITupleReference tuple) {
+        int bytes = getNullFlagsBytes(tuple) + getFieldSlotsBytes(tuple);
+        for (int i = 0; i < tuple.getFieldCount(); i++) {
+            bytes += tuple.getFieldLength(i);
+        }
+        return bytes;
+    }
+
+    @Override
+    public int bytesRequired(ITupleReference tuple, int startField, int numFields) {
+        int bytes = getNullFlagsBytes(numFields) + getFieldSlotsBytes(tuple, startField, numFields);
+        for (int i = startField; i < startField + numFields; i++) {
+            bytes += tuple.getFieldLength(i);
+        }
+        return bytes;
+    }
+
+    @Override
+    public ITreeIndexTupleReference createTupleReference() {
+        return new TypeAwareTupleReference(typeTraits);
+    }
+
+    @Override
+    public int writeTuple(ITupleReference tuple, ByteBuffer targetBuf, int targetOff) {
+        return writeTuple(tuple, targetBuf.array(), targetOff);
+    }
+
+    @Override
+    public int writeTuple(ITupleReference tuple, byte[] targetBuf, int targetOff) {
+        int runner = targetOff;
+        int nullFlagsBytes = getNullFlagsBytes(tuple);
+        // write null indicator bits
+        for (int i = 0; i < nullFlagsBytes; i++) {
+            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].isFixedLength()) {
+                encDec.encode(tuple.getFieldLength(i));
+            }
+        }
+        runner = encDec.getPos();
+
+        // write data fields
+        for (int i = 0; i < tuple.getFieldCount(); 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, byte[] targetBuf,
+            int targetOff) {
+        int runner = targetOff;
+        int nullFlagsBytes = getNullFlagsBytes(numFields);
+        // write null indicator bits
+        for (int i = 0; i < nullFlagsBytes; i++) {
+            targetBuf[runner++] = (byte) 0;
+        }
+
+        // write field slots for variable length fields
+        encDec.reset(targetBuf, runner);
+        for (int i = startField; i < startField + numFields; i++) {
+            if (!typeTraits[i].isFixedLength()) {
+                encDec.encode(tuple.getFieldLength(i));
+            }
+        }
+        runner = encDec.getPos();
+
+        for (int i = startField; i < startField + numFields; i++) {
+            System.arraycopy(tuple.getFieldData(i), tuple.getFieldStart(i), targetBuf, runner,
+                    tuple.getFieldLength(i));
+            runner += tuple.getFieldLength(i);
+        }
+
+        return runner - targetOff;
+    }
+
+    protected int getNullFlagsBytes(ITupleReference tuple) {
+        return (int) Math.ceil((double) tuple.getFieldCount() / 8.0);
+    }
+
+    protected int getFieldSlotsBytes(ITupleReference tuple) {
+        int fieldSlotBytes = 0;
+        for (int i = 0; i < tuple.getFieldCount(); i++) {
+            if (!typeTraits[i].isFixedLength()) {
+                fieldSlotBytes += encDec.getBytesRequired(tuple.getFieldLength(i));
+            }
+        }
+        return fieldSlotBytes;
+    }
+
+    protected int getNullFlagsBytes(int numFields) {
+        return (int) Math.ceil((double) numFields / 8.0);
+    }
+
+    protected int getFieldSlotsBytes(ITupleReference tuple, int startField, int numFields) {
+        int fieldSlotBytes = 0;
+        for (int i = startField; i < startField + numFields; i++) {
+            if (!typeTraits[i].isFixedLength()) {
+                fieldSlotBytes += encDec.getBytesRequired(tuple.getFieldLength(i));
+            }
+        }
+        return fieldSlotBytes;
+    }
+
+    public ITypeTraits[] getTypeTraits() {
+        return typeTraits;
+    }
+
+    public void setTypeTraits(ITypeTraits[] typeTraits) {
+        this.typeTraits = typeTraits;
+    }
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriterFactory.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriterFactory.java
new file mode 100644
index 0000000..9e6ba6f
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/TypeAwareTupleWriterFactory.java
@@ -0,0 +1,37 @@
+/*
+ * 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.tuples;
+
+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 {
+
+	private static final long serialVersionUID = 1L;
+	private ITypeTraits[] typeTraits;
+
+	public TypeAwareTupleWriterFactory(ITypeTraits[] typeTraits) {
+		this.typeTraits = typeTraits;
+	}
+
+	@Override
+	public ITreeIndexTupleWriter createTupleWriter() {
+		return new TypeAwareTupleWriter(typeTraits);
+	}
+
+}
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/VarLenIntEncoderDecoder.java b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/VarLenIntEncoderDecoder.java
new file mode 100644
index 0000000..979bbd3
--- /dev/null
+++ b/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/tuples/VarLenIntEncoderDecoder.java
@@ -0,0 +1,88 @@
+/*
+ * 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.tuples;
+
+// 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;
+
+	private byte[] encTmp = new byte[5];
+
+	private int pos;
+	private byte[] bytes;
+
+	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);
+
+		// 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;
+	}
+
+	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;
+	}
+
+	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; }
+	 */
+}
\ No newline at end of file
diff --git a/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexBufferCacheWarmup.java b/fullstack/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/fullstack/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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexStats.java b/fullstack/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/fullstack/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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexStatsGatherer.java b/fullstack/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/fullstack/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/fullstack/hyracks/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/util/TreeIndexUtils.java b/fullstack/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/fullstack/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();
+    }
+}