completed bulk loading with compression and modified cursors to provide a fielditerator to hide compression details

git-svn-id: https://hyracks.googlecode.com/svn/trunk/hyracks@108 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-examples/hyracks-integration-tests/src/test/java/edu/uci/ics/hyracks/tests/btree/BTreeOperatorsTest.java b/hyracks-examples/hyracks-integration-tests/src/test/java/edu/uci/ics/hyracks/tests/btree/BTreeOperatorsTest.java
index 646795f..43b97d1 100644
--- a/hyracks-examples/hyracks-integration-tests/src/test/java/edu/uci/ics/hyracks/tests/btree/BTreeOperatorsTest.java
+++ b/hyracks-examples/hyracks-integration-tests/src/test/java/edu/uci/ics/hyracks/tests/btree/BTreeOperatorsTest.java
@@ -1,7 +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.tests.btree;
 
 import java.io.DataOutputStream;
 import java.io.File;
+import java.io.RandomAccessFile;
 
 import org.junit.Test;
 
@@ -28,6 +44,7 @@
 import edu.uci.ics.hyracks.dataflow.std.file.FileScanOperatorDescriptor;
 import edu.uci.ics.hyracks.dataflow.std.file.FileSplit;
 import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
+import edu.uci.ics.hyracks.dataflow.std.misc.NullSinkOperatorDescriptor;
 import edu.uci.ics.hyracks.dataflow.std.misc.PrinterOperatorDescriptor;
 import edu.uci.ics.hyracks.dataflow.std.sort.InMemorySortOperatorDescriptor;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeCursor;
@@ -35,20 +52,28 @@
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeLeafFrameFactory;
 import edu.uci.ics.hyracks.storage.am.btree.api.IFieldAccessor;
 import edu.uci.ics.hyracks.storage.am.btree.api.IFieldAccessorFactory;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.dataflow.BTreeBulkLoadOperatorDescriptor;
+import edu.uci.ics.hyracks.storage.am.btree.dataflow.BTreeInsertUpdateDeleteOperatorDescriptor;
+import edu.uci.ics.hyracks.storage.am.btree.dataflow.BTreeRegistry;
 import edu.uci.ics.hyracks.storage.am.btree.dataflow.BTreeRegistryProvider;
 import edu.uci.ics.hyracks.storage.am.btree.dataflow.BTreeSearchOperatorDescriptor;
 import edu.uci.ics.hyracks.storage.am.btree.dataflow.BufferCacheProvider;
 import edu.uci.ics.hyracks.storage.am.btree.dataflow.IBTreeRegistryProvider;
 import edu.uci.ics.hyracks.storage.am.btree.dataflow.IBufferCacheProvider;
+import edu.uci.ics.hyracks.storage.am.btree.frames.MetaDataFrame;
 import edu.uci.ics.hyracks.storage.am.btree.frames.NSMInteriorFrameFactory;
 import edu.uci.ics.hyracks.storage.am.btree.frames.NSMLeafFrameFactory;
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTree;
+import edu.uci.ics.hyracks.storage.am.btree.impls.BTreeOp;
 import edu.uci.ics.hyracks.storage.am.btree.impls.MultiComparator;
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangePredicate;
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangeSearchCursor;
 import edu.uci.ics.hyracks.storage.am.btree.types.Int32AccessorFactory;
 import edu.uci.ics.hyracks.storage.am.btree.types.UTF8StringAccessorFactory;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+import edu.uci.ics.hyracks.storage.common.file.FileInfo;
+import edu.uci.ics.hyracks.storage.common.file.FileManager;
 import edu.uci.ics.hyracks.tests.integration.AbstractIntegrationTest;
 
 public class BTreeOperatorsTest extends AbstractIntegrationTest {
@@ -77,7 +102,7 @@
                 new AbsoluteLocationConstraint(NC1_ID) });
         ordScanner.setPartitionConstraint(ordersPartitionConstraint);
 
-        InMemorySortOperatorDescriptor sorter = new InMemorySortOperatorDescriptor(spec, new int[] { 1 },
+        InMemorySortOperatorDescriptor sorter = new InMemorySortOperatorDescriptor(spec, new int[] { 0 },
                 new IBinaryComparatorFactory[] { UTF8StringBinaryComparatorFactory.INSTANCE }, ordersDesc);
         PartitionConstraint sortersPartitionConstraint = new ExplicitPartitionConstraint(new LocationConstraint[] {
                 new AbsoluteLocationConstraint(NC1_ID) });
@@ -89,7 +114,6 @@
 		IBufferCacheProvider bufferCacheProvider = new BufferCacheProvider();		
 		IBTreeRegistryProvider btreeRegistryProvider = new BTreeRegistryProvider();
         
-        // build first bulk load operator		
 		IFieldAccessorFactory[] fieldAccessorFactories = new IFieldAccessorFactory[3];
 		fieldAccessorFactories[0] = new UTF8StringAccessorFactory(); // key
 		fieldAccessorFactories[1] = new UTF8StringAccessorFactory(); // payload
@@ -99,7 +123,7 @@
 		IBinaryComparatorFactory[] comparatorFactories = new IBinaryComparatorFactory[keyLen];
 		comparatorFactories[0] = UTF8StringBinaryComparatorFactory.INSTANCE;		
 				
-        int[] keyFields = { 1 };
+        int[] keyFields = { 0 };
         int[] payloadFields = { 4, 5 };
         int btreeFileId = 0;
         
@@ -125,7 +149,7 @@
     		comparators[i] = comparatorFactories[i].createBinaryComparator();
     	}
     	
-        MultiComparator cmpA = new MultiComparator(comparators, fields);
+        MultiComparator cmp = new MultiComparator(comparators, fields);
 
         // try an ordered scan on the bulk-loaded btree
         BTree btreeA = btreeRegistryProvider.getBTreeRegistry().get(btreeFileId);
@@ -135,10 +159,9 @@
         try {
         	while (scanCursor.hasNext()) {
         		scanCursor.next();
-        		byte[] array = scanCursor.getPage().getBuffer().array();
-        		int recOffset = scanCursor.getOffset();                
-        		String rec = cmpA.printRecord(array, recOffset);
-        		System.out.println(rec);
+        		IFieldIterator fieldIter = scanCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
+                System.out.println(rec);
         	}
         } catch (Exception e) {
         	e.printStackTrace();
@@ -146,7 +169,7 @@
         	scanCursor.close();
         }                        
 	}
-	
+		
 	@Test
 	public void btreeSearchTest() throws Exception {
 		JobSpecification spec = new JobSpecification();
@@ -199,4 +222,220 @@
         spec.addRoot(printer);
         runTest(spec);
     }
+		
+	@Test
+	public void insertTest() throws Exception {
+		JobSpecification spec = new JobSpecification();
+		
+        FileSplit[] ordersSplits = new FileSplit[] {
+                new FileSplit(NC1_ID, new File("data/tpch0.001/orders-part1.tbl")) };
+        IFileSplitProvider ordersSplitProvider = new ConstantFileSplitProvider(ordersSplits);
+        RecordDescriptor ordersDesc = new RecordDescriptor(new ISerializerDeserializer[] {
+                UTF8StringSerializerDeserializer.INSTANCE, UTF8StringSerializerDeserializer.INSTANCE,
+                UTF8StringSerializerDeserializer.INSTANCE, UTF8StringSerializerDeserializer.INSTANCE,
+                UTF8StringSerializerDeserializer.INSTANCE, UTF8StringSerializerDeserializer.INSTANCE,
+                UTF8StringSerializerDeserializer.INSTANCE, UTF8StringSerializerDeserializer.INSTANCE,
+                UTF8StringSerializerDeserializer.INSTANCE });
+        
+        FileScanOperatorDescriptor ordScanner = new FileScanOperatorDescriptor(spec, ordersSplitProvider,
+                new DelimitedDataTupleParserFactory(new IValueParserFactory[] { UTF8StringParserFactory.INSTANCE,
+                        UTF8StringParserFactory.INSTANCE, UTF8StringParserFactory.INSTANCE,
+                        UTF8StringParserFactory.INSTANCE, UTF8StringParserFactory.INSTANCE,
+                        UTF8StringParserFactory.INSTANCE, UTF8StringParserFactory.INSTANCE,
+                        UTF8StringParserFactory.INSTANCE, UTF8StringParserFactory.INSTANCE }, '|'), ordersDesc);
+        PartitionConstraint ordersPartitionConstraint = new ExplicitPartitionConstraint(new LocationConstraint[] {
+                new AbsoluteLocationConstraint(NC1_ID) });
+        ordScanner.setPartitionConstraint(ordersPartitionConstraint);
+        
+        IBTreeInteriorFrameFactory interiorFrameFactory = new NSMInteriorFrameFactory();
+		IBTreeLeafFrameFactory leafFrameFactory = new NSMLeafFrameFactory();
+		
+		IBufferCacheProvider bufferCacheProvider = new BufferCacheProvider();		
+		IBTreeRegistryProvider btreeRegistryProvider = new BTreeRegistryProvider();
+		
+		// we will create a primary index and 2 secondary indexes
+		// first create fieldaccessors and comparators for primary index
+		IFieldAccessorFactory[] primaryFieldAccessorFactories = new IFieldAccessorFactory[6];
+		primaryFieldAccessorFactories[0] = new UTF8StringAccessorFactory(); // key
+		primaryFieldAccessorFactories[1] = new UTF8StringAccessorFactory(); // payload
+		primaryFieldAccessorFactories[2] = new UTF8StringAccessorFactory(); // payload
+		primaryFieldAccessorFactories[3] = new UTF8StringAccessorFactory(); // payload
+		primaryFieldAccessorFactories[4] = new UTF8StringAccessorFactory(); // payload
+		primaryFieldAccessorFactories[5] = new UTF8StringAccessorFactory(); // payload		
+		
+		int primaryKeyLen = 1;
+		IBinaryComparatorFactory[] primaryComparatorFactories = new IBinaryComparatorFactory[primaryKeyLen];
+		primaryComparatorFactories[0] = UTF8StringBinaryComparatorFactory.INSTANCE;		
+		
+		// construct a multicomparator for the primary index                
+        IFieldAccessor[] primaryFields = new IFieldAccessor[primaryFieldAccessorFactories.length];
+    	for(int i = 0; i < primaryFieldAccessorFactories.length; i++) {
+    		primaryFields[i] = primaryFieldAccessorFactories[i].getFieldAccessor();
+    	}
+    	
+    	IBinaryComparator[] primaryComparators = new IBinaryComparator[primaryComparatorFactories.length];
+    	for(int i = 0; i < primaryComparatorFactories.length; i++) {
+    		primaryComparators[i] = primaryComparatorFactories[i].createBinaryComparator();
+    	}
+    	
+        MultiComparator primaryCmp = new MultiComparator(primaryComparators, primaryFields);
+        
+        
+        // now create fieldaccessors and comparators for secondary indexes
+		IFieldAccessorFactory[] secondaryFieldAccessorFactories = new IFieldAccessorFactory[2];
+		secondaryFieldAccessorFactories[0] = new UTF8StringAccessorFactory(); // key
+		secondaryFieldAccessorFactories[1] = new UTF8StringAccessorFactory(); // key (key in primary index)
+		
+		int secondaryKeyLen = 2;
+		IBinaryComparatorFactory[] secondaryComparatorFactories = new IBinaryComparatorFactory[secondaryKeyLen];
+		secondaryComparatorFactories[0] = UTF8StringBinaryComparatorFactory.INSTANCE;
+		secondaryComparatorFactories[1] = UTF8StringBinaryComparatorFactory.INSTANCE;		
+		
+		// construct a multicomparator for the secondary indexes                
+        IFieldAccessor[] secondaryFields = new IFieldAccessor[secondaryFieldAccessorFactories.length];
+    	for(int i = 0; i < secondaryFieldAccessorFactories.length; i++) {
+    		secondaryFields[i] = secondaryFieldAccessorFactories[i].getFieldAccessor();
+    	}
+    	
+    	IBinaryComparator[] secondaryComparators = new IBinaryComparator[secondaryComparatorFactories.length];
+    	for(int i = 0; i < secondaryComparatorFactories.length; i++) {
+    		secondaryComparators[i] = secondaryComparatorFactories[i].createBinaryComparator();
+    	}
+    	
+        MultiComparator secondaryCmp = new MultiComparator(secondaryComparators, secondaryFields);
+        
+        // we create and register 3 btrees for in an insert pipeline being fed from a filescan op        
+        IBufferCache bufferCache = bufferCacheProvider.getBufferCache();
+        BTreeRegistry btreeRegistry = btreeRegistryProvider.getBTreeRegistry();        
+        FileManager fileManager = bufferCacheProvider.getFileManager();
+        
+        // primary index
+        int fileIdA = 3;
+        File fA = new File("/tmp/btreetestA.ix");
+        RandomAccessFile rafA = new RandomAccessFile(fA, "rw");                
+        FileInfo fiA = new FileInfo(fileIdA, rafA);
+        fileManager.registerFile(fiA);
+        BTree btreeA = new BTree(bufferCache, interiorFrameFactory, leafFrameFactory, primaryCmp);		
+		btreeA.create(fileIdA, leafFrameFactory.getFrame(), new MetaDataFrame());
+        btreeA.open(fileIdA);
+        btreeRegistry.register(fileIdA, btreeA);
+        
+        // first secondary index
+        int fileIdB = 4;
+        File fB = new File("/tmp/btreetestB.ix");
+        RandomAccessFile rafB = new RandomAccessFile(fB, "rw");   
+        FileInfo fiB = new FileInfo(fileIdB, rafB);
+        fileManager.registerFile(fiB);
+        BTree btreeB = new BTree(bufferCache, interiorFrameFactory, leafFrameFactory, secondaryCmp);		
+		btreeB.create(fileIdB, leafFrameFactory.getFrame(), new MetaDataFrame());
+        btreeB.open(fileIdB);
+        btreeRegistry.register(fileIdB, btreeB);
+        
+        // second secondary index
+        int fileIdC = 5;
+        File fC = new File("/tmp/btreetestC.ix");
+        RandomAccessFile rafC = new RandomAccessFile(fC, "rw");                
+        FileInfo fiC = new FileInfo(fileIdC, rafC);
+        fileManager.registerFile(fiC);
+        BTree btreeC = new BTree(bufferCache, interiorFrameFactory, leafFrameFactory, secondaryCmp);	
+		btreeC.create(fileIdC, leafFrameFactory.getFrame(), new MetaDataFrame());
+        btreeC.open(fileIdC);
+        btreeRegistry.register(fileIdC, btreeC);
+        
+                
+        // create insert operators
+        
+        // primary index
+        int[] keyFieldsA = { 0 };
+        int[] payloadFieldsA = { 1,2,3,4,5 };                
+        BTreeInsertUpdateDeleteOperatorDescriptor insertOpA = new BTreeInsertUpdateDeleteOperatorDescriptor(spec, ordersSplitProvider, ordersDesc, bufferCacheProvider, btreeRegistryProvider, fileIdA, "/tmp/btreetestA.ix", interiorFrameFactory, leafFrameFactory, primaryFieldAccessorFactories, primaryComparatorFactories, keyFieldsA, payloadFieldsA, BTreeOp.BTO_INSERT);
+        PartitionConstraint insertPartitionConstraintA = new ExplicitPartitionConstraint(new LocationConstraint[] { new AbsoluteLocationConstraint(NC1_ID) });
+        insertOpA.setPartitionConstraint(insertPartitionConstraintA);
+        
+        // first secondary index
+        int[] keyFieldsB = { 3, 0 };
+        int[] payloadFieldsB = { };                
+        BTreeInsertUpdateDeleteOperatorDescriptor insertOpB = new BTreeInsertUpdateDeleteOperatorDescriptor(spec, ordersSplitProvider, ordersDesc, bufferCacheProvider, btreeRegistryProvider, fileIdB, "/tmp/btreetestB.ix", interiorFrameFactory, leafFrameFactory, secondaryFieldAccessorFactories, secondaryComparatorFactories, keyFieldsB, payloadFieldsB, BTreeOp.BTO_INSERT);
+        PartitionConstraint insertPartitionConstraintB = new ExplicitPartitionConstraint(new LocationConstraint[] { new AbsoluteLocationConstraint(NC1_ID) });
+        insertOpB.setPartitionConstraint(insertPartitionConstraintB);
+		
+        // second secondary index
+        int[] keyFieldsC = { 4, 0 };
+        int[] payloadFieldsC = { };                
+        BTreeInsertUpdateDeleteOperatorDescriptor insertOpC = new BTreeInsertUpdateDeleteOperatorDescriptor(spec, ordersSplitProvider, ordersDesc, bufferCacheProvider, btreeRegistryProvider, fileIdC, "/tmp/btreetestC.ix", interiorFrameFactory, leafFrameFactory, secondaryFieldAccessorFactories, secondaryComparatorFactories, keyFieldsC, payloadFieldsC, BTreeOp.BTO_INSERT);
+        PartitionConstraint insertPartitionConstraintC = new ExplicitPartitionConstraint(new LocationConstraint[] { new AbsoluteLocationConstraint(NC1_ID) });
+        insertOpC.setPartitionConstraint(insertPartitionConstraintC);
+                
+        NullSinkOperatorDescriptor nullSink = new NullSinkOperatorDescriptor(spec);
+        PartitionConstraint nullSinkPartitionConstraint = new ExplicitPartitionConstraint(new LocationConstraint[] { new AbsoluteLocationConstraint(NC1_ID) });
+        nullSink.setPartitionConstraint(nullSinkPartitionConstraint);
+        
+        spec.connect(new OneToOneConnectorDescriptor(spec), ordScanner, 0, insertOpA, 0);
+        
+        spec.connect(new OneToOneConnectorDescriptor(spec), insertOpA, 0, insertOpB, 0);
+        
+        spec.connect(new OneToOneConnectorDescriptor(spec), insertOpB, 0, insertOpC, 0);        
+        
+        spec.connect(new OneToOneConnectorDescriptor(spec), insertOpC, 0, nullSink, 0);               
+        
+        spec.addRoot(nullSink);
+        runTest(spec);               
+        
+        // scan primary index         
+        System.out.println("PRINTING PRIMARY INDEX");
+        IBTreeCursor scanCursorA = new RangeSearchCursor(leafFrameFactory.getFrame());
+        RangePredicate nullPredA = new RangePredicate(true, null, null, null);
+        btreeA.search(scanCursorA, nullPredA, leafFrameFactory.getFrame(), interiorFrameFactory.getFrame());
+        try {
+        	while (scanCursorA.hasNext()) {
+        		scanCursorA.next();
+        		IFieldIterator fieldIter = scanCursorA.getFieldIterator();                                
+                String rec = primaryCmp.printRecord(fieldIter);
+                System.out.println(rec);
+        	}
+        } catch (Exception e) {
+        	e.printStackTrace();
+        } finally {
+        	scanCursorA.close();
+        }            
+        System.out.println();
+        
+        // scan first secondary index
+        System.out.println("PRINTING FIRST SECONDARY INDEX");
+        IBTreeCursor scanCursorB = new RangeSearchCursor(leafFrameFactory.getFrame());
+        RangePredicate nullPredB = new RangePredicate(true, null, null, null);
+        btreeB.search(scanCursorB, nullPredB, leafFrameFactory.getFrame(), interiorFrameFactory.getFrame());
+        try {
+        	while (scanCursorB.hasNext()) {
+        		scanCursorB.next();
+        		IFieldIterator fieldIter = scanCursorB.getFieldIterator();                                
+                String rec = secondaryCmp.printRecord(fieldIter);
+                System.out.println(rec);
+        	}
+        } catch (Exception e) {
+        	e.printStackTrace();
+        } finally {
+        	scanCursorB.close();
+        }           
+        System.out.println();
+        
+        // scan second secondary index
+        System.out.println("PRINTING SECOND SECONDARY INDEX");
+        IBTreeCursor scanCursorC = new RangeSearchCursor(leafFrameFactory.getFrame());
+        RangePredicate nullPredC = new RangePredicate(true, null, null, null);
+        btreeC.search(scanCursorC, nullPredC, leafFrameFactory.getFrame(), interiorFrameFactory.getFrame());
+        try {
+        	while (scanCursorC.hasNext()) {
+        		scanCursorC.next();
+        		IFieldIterator fieldIter = scanCursorC.getFieldIterator();                                
+                String rec = secondaryCmp.printRecord(fieldIter);
+                System.out.println(rec);
+        	}
+        } catch (Exception e) {
+        	e.printStackTrace();
+        } finally {
+        	scanCursorC.close();
+        }        
+        System.out.println();
+	}
 }
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IBTreeCursor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IBTreeCursor.java
index 78767d1..74e6478 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IBTreeCursor.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IBTreeCursor.java
@@ -21,11 +21,11 @@
 public interface IBTreeCursor {
 	public void reset();
 	public boolean hasNext() throws Exception;
-	public int getOffset();
 	public void next() throws Exception;	
 	public void open(ICachedPage page, ISearchPredicate searchPred) throws Exception;
 	public ICachedPage getPage();
 	public void close() throws Exception;
 	public void setBufferCache(IBufferCache bufferCache);
 	public void setFileId(int fileId);
+	public IFieldIterator getFieldIterator();
 }
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IBTreeFrame.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IBTreeFrame.java
index da5a39a..aabd005 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IBTreeFrame.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IBTreeFrame.java
@@ -68,12 +68,15 @@
 	public boolean getSmFlag(); // structure modification flag
 	public void setSmFlag(boolean smFlag);	
 	
-	//public int getNumPrefixRecords();
-	//public void setNumPrefixRecords(int numPrefixRecords);
-	
 	public void insertSorted(byte[] data, MultiComparator cmp) throws Exception;
 	
+	public int getSlotSize();
+	
+	public IFieldIterator createFieldIterator();
+	
 	// for debugging
 	public int getFreeSpaceOff();
 	public void setFreeSpaceOff(int freeSpace);
+	
+	
 }
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IFieldIterator.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IFieldIterator.java
new file mode 100644
index 0000000..65702b2
--- /dev/null
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IFieldIterator.java
@@ -0,0 +1,40 @@
+/*
+ * 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.btree.api;
+
+import java.nio.ByteBuffer;
+
+public interface IFieldIterator {
+	public void setFrame(IBTreeFrame frame);
+
+    public void setFields(IFieldAccessor[] fields);
+    
+    public void openRecSlotNum(int recSlotNum);
+    
+    public void openRecSlotOff(int recSlotOff);
+    
+    public void reset();
+    
+    public void nextField();
+    
+    public int getFieldOff();
+    
+    public int getFieldSize();
+    
+    public int copyFields(int startField, int endField, byte[] dest, int destOff);   
+    
+    public ByteBuffer getBuffer();
+}
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IPrefixSlotManager.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IPrefixSlotManager.java
index 3599933..7792fa0 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IPrefixSlotManager.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/api/IPrefixSlotManager.java
@@ -15,8 +15,6 @@
 
 package edu.uci.ics.hyracks.storage.am.btree.api;
 
-import java.nio.ByteBuffer;
-
 import edu.uci.ics.hyracks.storage.am.btree.frames.FieldPrefixNSMLeafFrame;
 import edu.uci.ics.hyracks.storage.am.btree.impls.MultiComparator;
 
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/compressors/FieldPrefixCompressor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/compressors/FieldPrefixCompressor.java
index 27a8952..a0f0258 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/compressors/FieldPrefixCompressor.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/compressors/FieldPrefixCompressor.java
@@ -25,7 +25,7 @@
 import edu.uci.ics.hyracks.storage.am.btree.api.IFrameCompressor;
 import edu.uci.ics.hyracks.storage.am.btree.api.IPrefixSlotManager;
 import edu.uci.ics.hyracks.storage.am.btree.frames.FieldPrefixNSMLeafFrame;
-import edu.uci.ics.hyracks.storage.am.btree.impls.FieldIterator;
+import edu.uci.ics.hyracks.storage.am.btree.impls.FieldPrefixFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.impls.FieldPrefixSlotManager;
 import edu.uci.ics.hyracks.storage.am.btree.impls.MultiComparator;
 
@@ -48,13 +48,13 @@
     	if(numRecords <= 0) {
             frame.setNumPrefixRecords(0);
             frame.setFreeSpaceOff(frame.getOrigFreeSpaceOff());
-            frame.setTotalFreeSpace(frame.getOrigTotalFreeSpace());
+            frame.setTotalFreeSpace(frame.getOrigTotalFreeSpace());            
             return false;
         }
-    	
+    	    	
     	int numUncompressedRecords = frame.getNumUncompressedRecords();
     	float ratio = (float)numUncompressedRecords / (float)numRecords;    	
-    	if(ratio < ratioThreshold) return false;
+    	if(ratio < ratioThreshold) return false;    	
     	
         IBinaryComparator[] cmps = cmp.getComparators();
         IFieldAccessor[] fields = cmp.getFields();
@@ -65,7 +65,7 @@
                 
         // perform analysis pass
         ArrayList<KeyPartition> keyPartitions = getKeyPartitions(frame, cmp, occurrenceThreshold);
-        if(keyPartitions.size() == 0) return false;
+        if(keyPartitions.size() == 0) return false;        
         
         // for each keyPartition, determine the best prefix length for compression, and count how many prefix records we would need in total
         int totalSlotsNeeded = 0;
@@ -143,7 +143,7 @@
         int recSlotNum = 0;
         int prefixSlotNum = 0;
         numUncompressedRecords = 0;
-        FieldIterator recToWrite = new FieldIterator(fields, frame);
+        FieldPrefixFieldIterator recToWrite = new FieldPrefixFieldIterator(fields, frame);
         while(recSlotNum < numRecords) {           
             if(kpIndex < keyPartitions.size()) {
             	
@@ -157,8 +157,8 @@
             		
             		//System.out.println("PROCESSING KEYPARTITION: " + kpIndex + " RANGE: " + keyPartitions.get(kpIndex).firstRecSlotNum + " " + keyPartitions.get(kpIndex).lastRecSlotNum + " FIELDSTOCOMPRESS: " + numFieldsToCompress);
             		
-            		FieldIterator prevRec = new FieldIterator(fields, frame);        
-                    FieldIterator rec = new FieldIterator(fields, frame);
+            		FieldPrefixFieldIterator prevRec = new FieldPrefixFieldIterator(fields, frame);        
+                    FieldPrefixFieldIterator rec = new FieldPrefixFieldIterator(fields, frame);
                     
                     for(int i = recSlotNum + 1; i <= keyPartitions.get(kpIndex).lastRecSlotNum; i++) {
                     	prevRec.openRecSlotNum(i - 1);
@@ -312,8 +312,8 @@
         KeyPartition kp = new KeyPartition(maxCmps);        
         keyPartitions.add(kp);
         
-        FieldIterator prevRec = new FieldIterator(fields, frame);        
-        FieldIterator rec = new FieldIterator(fields, frame);
+        FieldPrefixFieldIterator prevRec = new FieldPrefixFieldIterator(fields, frame);        
+        FieldPrefixFieldIterator rec = new FieldPrefixFieldIterator(fields, frame);
         
         kp.firstRecSlotNum = 0;        
         int numRecords = frame.getNumRecords();
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/AbstractBTreeOperatorDescriptor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/AbstractBTreeOperatorDescriptor.java
index 0a1efa5..d1ade0c 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/AbstractBTreeOperatorDescriptor.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/AbstractBTreeOperatorDescriptor.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/AbstractBTreeOperatorNodePushable.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/AbstractBTreeOperatorNodePushable.java
index af7c3c6..1949651 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/AbstractBTreeOperatorNodePushable.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/AbstractBTreeOperatorNodePushable.java
@@ -1,8 +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.btree.dataflow;
 
 import java.io.DataOutputStream;
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.RandomAccessFile;
 import java.util.Random;
 
@@ -32,18 +46,25 @@
 	protected AbstractBTreeOperatorDescriptor opDesc;	
 	protected IHyracksContext ctx;
 	
-	public AbstractBTreeOperatorNodePushable(AbstractBTreeOperatorDescriptor opDesc, final IHyracksContext ctx) {
+	protected boolean createBTree;
+	
+	public AbstractBTreeOperatorNodePushable(AbstractBTreeOperatorDescriptor opDesc, final IHyracksContext ctx, boolean createBTree) {
 		this.opDesc = opDesc;
 		this.ctx = ctx;
+		this.createBTree = createBTree;
 	}
 	
-	public void init() throws FileNotFoundException {				
+	public void init() throws Exception {				
 		IBufferCache bufferCache = opDesc.getBufferCacheProvider().getBufferCache();
 		FileManager fileManager = opDesc.getBufferCacheProvider().getFileManager();
 		
         File f = new File(opDesc.getBtreeFileName());
         RandomAccessFile raf = new RandomAccessFile(f, "rw");
         
+        if(!f.exists() && !createBTree) {
+        	throw new Exception("Trying to open btree from file " + opDesc.getBtreeFileName() + " but file doesn't exist.");
+        }
+        
         try {
         	FileInfo fi = new FileInfo(opDesc.getBtreeFileId(), raf);
         	fileManager.registerFile(fi);
@@ -51,6 +72,9 @@
         catch (Exception e) {
         }
         
+        interiorFrame = opDesc.getInteriorFactory().getFrame();
+        leafFrame = opDesc.getLeafFactory().getFrame();    	
+        
 		BTreeRegistry btreeRegistry = opDesc.getBtreeRegistryProvider().getBTreeRegistry();
 		btree = btreeRegistry.get(opDesc.getBtreeFileId());
         if(btree == null) {
@@ -77,23 +101,24 @@
                     MultiComparator cmp = new MultiComparator(comparators, fields);
                 	
                 	btree = new BTree(bufferCache, opDesc.getInteriorFactory(), opDesc.getLeafFactory(), cmp);
-                    btree.open(opDesc.getBtreeFileId());
+                	if(createBTree) {
+                		MetaDataFrame metaFrame = new MetaDataFrame();                		
+                		btree.create(opDesc.getBtreeFileId(), leafFrame, metaFrame);
+                	}
+                	btree.open(opDesc.getBtreeFileId());
                     btreeRegistry.register(opDesc.getBtreeFileId(), btree);
                 }                
             }
             finally {                        
                 btreeRegistry.unlock();
             }
-        }            
-                
-        interiorFrame = opDesc.getInteriorFactory().getFrame();
-        leafFrame = opDesc.getLeafFactory().getFrame();    	
+        }                      
 	}	
 	
 	// debug
 	protected void fill() throws Exception {
-		MetaDataFrame metaFrame = new MetaDataFrame();
 		
+		MetaDataFrame metaFrame = new MetaDataFrame();                		
 		btree.create(opDesc.getBtreeFileId(), leafFrame, metaFrame);
 		
 		Random rnd = new Random();
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeBulkLoadOperatorDescriptor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeBulkLoadOperatorDescriptor.java
index 221adab..0df2581 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeBulkLoadOperatorDescriptor.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeBulkLoadOperatorDescriptor.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import edu.uci.ics.hyracks.api.context.IHyracksContext;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeBulkLoadOperatorNodePushable.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeBulkLoadOperatorNodePushable.java
index d6b0036..8376260 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeBulkLoadOperatorNodePushable.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeBulkLoadOperatorNodePushable.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import java.nio.ByteBuffer;
@@ -24,7 +39,7 @@
     private IRecordDescriptorProvider recordDescProvider;
     
 	public BTreeBulkLoadOperatorNodePushable(AbstractBTreeOperatorDescriptor opDesc, IHyracksContext ctx, int[] keyFields, int[] payloadFields, float fillFactor, IRecordDescriptorProvider recordDescProvider) {
-		super(opDesc, ctx);
+		super(opDesc, ctx, true);
 		this.keyFields = keyFields;
 		this.payloadFields = payloadFields;
 		this.fillFactor = fillFactor;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeDiskOrderScanOperatorDescriptor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeDiskOrderScanOperatorDescriptor.java
index 4509d8c..8b1da5a 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeDiskOrderScanOperatorDescriptor.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeDiskOrderScanOperatorDescriptor.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import edu.uci.ics.hyracks.api.context.IHyracksContext;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeDiskOrderScanOperatorNodePushable.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeDiskOrderScanOperatorNodePushable.java
index 74c878a..373a27d 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeDiskOrderScanOperatorNodePushable.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeDiskOrderScanOperatorNodePushable.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import java.io.DataOutput;
@@ -11,6 +26,7 @@
 import edu.uci.ics.hyracks.dataflow.common.comm.util.FrameUtils;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeLeafFrame;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeMetaDataFrame;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.frames.MetaDataFrame;
 import edu.uci.ics.hyracks.storage.am.btree.impls.DiskOrderScanCursor;
 import edu.uci.ics.hyracks.storage.am.btree.impls.MultiComparator;
@@ -18,7 +34,7 @@
 public class BTreeDiskOrderScanOperatorNodePushable extends AbstractBTreeOperatorNodePushable {
 	
 	public BTreeDiskOrderScanOperatorNodePushable(AbstractBTreeOperatorDescriptor opDesc, IHyracksContext ctx) {
-		super(opDesc, ctx);
+		super(opDesc, ctx, false);
 	}
 	
 	@Override
@@ -50,15 +66,13 @@
 				tb.reset();                		
 				cursor.next();
 
-				int recRunner = cursor.getOffset();
-				byte[] array = cursor.getPage().getBuffer().array();
-				for(int i = 0; i < cmp.getFields().length; i++) {
-					int fieldLen = cmp.getFields()[i].getLength(array, recRunner);
-					dos.write(array, recRunner, fieldLen);                			
-					recRunner += fieldLen;
+				IFieldIterator fieldIter = cursor.getFieldIterator();
+				for(int i = 0; i < cmp.getFields().length; i++) {					
+					int fieldLen = fieldIter.getFieldSize();
+					dos.write(fieldIter.getBuffer().array(), fieldIter.getFieldOff(), fieldLen);
 					tb.addFieldEndOffset();
 				}
-
+				
 				if (!appender.append(tb.getFieldEndOffsets(), tb.getByteArray(), 0, tb.getSize())) {
 					FrameUtils.flushFrame(frame, writer);
 					appender.reset(frame, true);
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertOperatorNodePushable.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertOperatorNodePushable.java
deleted file mode 100644
index eddbbfa..0000000
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertOperatorNodePushable.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package edu.uci.ics.hyracks.storage.am.btree.dataflow;
-
-import java.nio.ByteBuffer;
-
-import edu.uci.ics.hyracks.api.context.IHyracksContext;
-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.storage.am.btree.api.IBTreeMetaDataFrame;
-import edu.uci.ics.hyracks.storage.am.btree.frames.MetaDataFrame;
-
-public class BTreeInsertOperatorNodePushable extends AbstractBTreeOperatorNodePushable {
-	
-	private final int[] keyFields;
-	private final int[] payloadFields;
-	    
-    private FrameTupleAccessor accessor;
-    
-    private IRecordDescriptorProvider recordDescProvider;
-    
-    private IBTreeMetaDataFrame metaFrame;
-    
-	public BTreeInsertOperatorNodePushable(AbstractBTreeOperatorDescriptor opDesc, IHyracksContext ctx, int[] keyFields, int[] payloadFields, IRecordDescriptorProvider recordDescProvider) {
-		super(opDesc, ctx);
-		this.keyFields = keyFields;
-		this.payloadFields = payloadFields;
-		this.recordDescProvider = recordDescProvider;
-	}
-	
-	@Override
-	public void close() throws HyracksDataException {
-		writer.close();		
-	}
-	
-	@Override
-	public void nextFrame(ByteBuffer buffer) throws HyracksDataException {		
-		accessor.reset(buffer);
-		
-		int tupleCount = accessor.getTupleCount();
-		for(int i = 0; i < tupleCount; i++) {
-			byte[] btreeRecord = buildBTreeRecordFromHyraxRecord(accessor, i, keyFields, payloadFields);
-			try {
-				btree.insert(btreeRecord, leafFrame, interiorFrame, metaFrame);
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		}
-		
-		// pass a copy of the frame to next op
-		FrameUtils.flushFrame(buffer.duplicate(), writer);
-	}
-	
-	@Override
-	public void open() throws HyracksDataException {		
-		RecordDescriptor recDesc = recordDescProvider.getInputRecordDescriptor(opDesc.getOperatorId(), 0);		
-		accessor = new FrameTupleAccessor(ctx, recDesc);		
-		try {
-			init();
-			btree.open(opDesc.getBtreeFileId());
-			metaFrame = new MetaDataFrame();
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-    @Override
-    public void flush() throws HyracksDataException {
-    }	
-}
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertOperatorDescriptor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertUpdateDeleteOperatorDescriptor.java
similarity index 62%
rename from hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertOperatorDescriptor.java
rename to hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertUpdateDeleteOperatorDescriptor.java
index 80066be..e88b633 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertOperatorDescriptor.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertUpdateDeleteOperatorDescriptor.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import edu.uci.ics.hyracks.api.context.IHyracksContext;
@@ -11,27 +26,31 @@
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeInteriorFrameFactory;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeLeafFrameFactory;
 import edu.uci.ics.hyracks.storage.am.btree.api.IFieldAccessorFactory;
+import edu.uci.ics.hyracks.storage.am.btree.impls.BTreeOp;
 
-public class BTreeInsertOperatorDescriptor extends AbstractBTreeOperatorDescriptor {
+public class BTreeInsertUpdateDeleteOperatorDescriptor extends AbstractBTreeOperatorDescriptor {
 	
 	private static final long serialVersionUID = 1L;
 	
 	private final int[] keyFields;
 	private final int[] payloadFields;
 	
-	public BTreeInsertOperatorDescriptor(JobSpecification spec,
+	private BTreeOp op;
+	
+	public BTreeInsertUpdateDeleteOperatorDescriptor(JobSpecification spec,
 			IFileSplitProvider fileSplitProvider, RecordDescriptor recDesc,
 			IBufferCacheProvider bufferCacheProvider,
 			IBTreeRegistryProvider btreeRegistryProvider, int btreeFileId,
 			String btreeFileName, IBTreeInteriorFrameFactory interiorFactory,
 			IBTreeLeafFrameFactory leafFactory, IFieldAccessorFactory[] fieldAccessorFactories, 
 			IBinaryComparatorFactory[] comparatorFactories,			
-			int[] keyFields, int[] payloadFields) {
+			int[] keyFields, int[] payloadFields, BTreeOp op) {
 		super(spec, 1, 1, fileSplitProvider, recDesc, bufferCacheProvider,
 				btreeRegistryProvider, btreeFileId, btreeFileName, interiorFactory,
 				leafFactory, fieldAccessorFactories, comparatorFactories);
 		this.keyFields = keyFields;
 		this.payloadFields = payloadFields;
+		this.op = op;
 	}
 	
 	@Override
@@ -39,7 +58,7 @@
 			IOperatorEnvironment env,
 			IRecordDescriptorProvider recordDescProvider, int partition,
 			int nPartitions) {
-		return new BTreeInsertOperatorNodePushable(this, ctx, keyFields, payloadFields, recordDescProvider);
+		return new BTreeInsertUpdateDeleteOperatorNodePushable(this, ctx, keyFields, payloadFields, recordDescProvider, op);
 	}
 	
 }
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertUpdateDeleteOperatorNodePushable.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertUpdateDeleteOperatorNodePushable.java
new file mode 100644
index 0000000..f578538
--- /dev/null
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeInsertUpdateDeleteOperatorNodePushable.java
@@ -0,0 +1,106 @@
+/*
+ * 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.btree.dataflow;
+
+import java.nio.ByteBuffer;
+
+import edu.uci.ics.hyracks.api.context.IHyracksContext;
+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.storage.am.btree.api.IBTreeMetaDataFrame;
+import edu.uci.ics.hyracks.storage.am.btree.frames.MetaDataFrame;
+import edu.uci.ics.hyracks.storage.am.btree.impls.BTreeOp;
+
+public class BTreeInsertUpdateDeleteOperatorNodePushable extends AbstractBTreeOperatorNodePushable {
+	
+	private final int[] keyFields;
+	private final int[] payloadFields;
+	    
+    private FrameTupleAccessor accessor;
+    
+    private IRecordDescriptorProvider recordDescProvider;
+    
+    private IBTreeMetaDataFrame metaFrame;
+    
+    private BTreeOp op;
+    
+	public BTreeInsertUpdateDeleteOperatorNodePushable(AbstractBTreeOperatorDescriptor opDesc, IHyracksContext ctx, int[] keyFields, int[] payloadFields, IRecordDescriptorProvider recordDescProvider, BTreeOp op) {
+		super(opDesc, ctx, false);
+		this.keyFields = keyFields;
+		this.payloadFields = payloadFields;
+		this.recordDescProvider = recordDescProvider;
+		this.op = op;
+	}
+	
+	@Override
+	public void close() throws HyracksDataException {
+		writer.close();		
+	}
+	
+	@Override
+	public void nextFrame(ByteBuffer buffer) throws HyracksDataException {		
+		accessor.reset(buffer);
+		
+		int tupleCount = accessor.getTupleCount();
+		for(int i = 0; i < tupleCount; i++) {
+			byte[] btreeRecord = buildBTreeRecordFromHyraxRecord(accessor, i, keyFields, payloadFields);
+			try {
+				
+				switch(op) {
+				
+				case BTO_INSERT: {
+					btree.insert(btreeRecord, leafFrame, interiorFrame, metaFrame);				
+				} break;
+				
+				case BTO_DELETE: {
+					btree.delete(btreeRecord, leafFrame, interiorFrame, metaFrame);				
+				} break;
+				
+				default: {
+					throw new HyracksDataException("Unsupported operation " + op + " in BTree InsertUpdateDelete operator");
+				}
+				
+				}
+				
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+		
+		// pass a copy of the frame to next op
+		FrameUtils.flushFrame(buffer.duplicate(), writer);
+	}
+	
+	@Override
+	public void open() throws HyracksDataException {		
+		RecordDescriptor recDesc = recordDescProvider.getInputRecordDescriptor(opDesc.getOperatorId(), 0);		
+		accessor = new FrameTupleAccessor(ctx, recDesc);		
+		try {
+			init();
+			btree.open(opDesc.getBtreeFileId());
+			metaFrame = new MetaDataFrame();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+    @Override
+    public void flush() throws HyracksDataException {
+    }	
+}
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeRegistry.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeRegistry.java
index 4ef4789..7f551d0 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeRegistry.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeRegistry.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import java.util.HashMap;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeRegistryProvider.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeRegistryProvider.java
index c07bd8b..677d4d4 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeRegistryProvider.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeRegistryProvider.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 public class BTreeRegistryProvider implements IBTreeRegistryProvider {
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorDescriptor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorDescriptor.java
index b30c6e2..ce5795b 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorDescriptor.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorDescriptor.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import edu.uci.ics.hyracks.api.context.IHyracksContext;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorNodePushable.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorNodePushable.java
index e360be2..67a4ff2 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorNodePushable.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeSearchOperatorNodePushable.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import java.io.DataOutput;
@@ -12,6 +27,7 @@
 import edu.uci.ics.hyracks.dataflow.common.comm.util.FrameUtils;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeCursor;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeLeafFrame;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.impls.MultiComparator;
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangePredicate;
 import edu.uci.ics.hyracks.storage.am.btree.impls.RangeSearchCursor;
@@ -24,7 +40,7 @@
 	private int searchKeyFields;
 	
 	public BTreeSearchOperatorNodePushable(AbstractBTreeOperatorDescriptor opDesc, IHyracksContext ctx, boolean isForward, byte[] lowKey, byte[] highKey, int searchKeyFields) {
-		super(opDesc, ctx);
+		super(opDesc, ctx, false);
 		this.isForward = isForward;
 		this.lowKey = lowKey;
 		this.highKey = highKey;
@@ -68,13 +84,11 @@
 			while(cursor.hasNext()) {
 				tb.reset();                		
 				cursor.next();
-
-				int recRunner = cursor.getOffset();
-				byte[] array = cursor.getPage().getBuffer().array();
-				for(int i = 0; i < cmp.getFields().length; i++) {
-					int fieldLen = cmp.getFields()[i].getLength(array, recRunner);
-					dos.write(array, recRunner, fieldLen);                			
-					recRunner += fieldLen;
+				
+				IFieldIterator fieldIter = cursor.getFieldIterator();
+				for(int i = 0; i < cmp.getFields().length; i++) {					
+					int fieldLen = fieldIter.getFieldSize();
+					dos.write(fieldIter.getBuffer().array(), fieldIter.getFieldOff(), fieldLen);
 					tb.addFieldEndOffset();
 				}
 
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BufferCacheProvider.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BufferCacheProvider.java
index 66f062e..bc64d81 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BufferCacheProvider.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BufferCacheProvider.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import java.nio.ByteBuffer;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBTreeOperatorDescriptor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBTreeOperatorDescriptor.java
index b25aec2..707d20e 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBTreeOperatorDescriptor.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBTreeOperatorDescriptor.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeInteriorFrameFactory;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBTreeRegistryProvider.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBTreeRegistryProvider.java
index ec9a007..128af09 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBTreeRegistryProvider.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBTreeRegistryProvider.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import java.io.Serializable;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBufferCacheProvider.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBufferCacheProvider.java
index 6f0edc6..c1a0eb4 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBufferCacheProvider.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/IBufferCacheProvider.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.dataflow;
 
 import java.io.Serializable;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/FieldPrefixNSMLeafFrame.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/FieldPrefixNSMLeafFrame.java
index 7627055..96884e4 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/FieldPrefixNSMLeafFrame.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/FieldPrefixNSMLeafFrame.java
@@ -23,12 +23,13 @@
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeFrame;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeLeafFrame;
 import edu.uci.ics.hyracks.storage.am.btree.api.IFieldAccessor;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.api.IFrameCompressor;
 import edu.uci.ics.hyracks.storage.am.btree.api.IPrefixSlotManager;
 import edu.uci.ics.hyracks.storage.am.btree.api.ISlotManager;
 import edu.uci.ics.hyracks.storage.am.btree.compressors.FieldPrefixCompressor;
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTreeException;
-import edu.uci.ics.hyracks.storage.am.btree.impls.FieldIterator;
+import edu.uci.ics.hyracks.storage.am.btree.impls.FieldPrefixFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.impls.FieldPrefixSlotManager;
 import edu.uci.ics.hyracks.storage.am.btree.impls.MultiComparator;
 import edu.uci.ics.hyracks.storage.am.btree.impls.SlotOffRecOff;
@@ -164,7 +165,7 @@
             if(exactDelete) {                    
                 IBinaryComparator[] cmps = cmp.getComparators();
                 IFieldAccessor[] fields = cmp.getFields();
-                FieldIterator fieldIter = new FieldIterator(fields, this);                    
+                FieldPrefixFieldIterator fieldIter = new FieldPrefixFieldIterator(fields, this);                    
                 fieldIter.openRecSlotOff(recSlotOff);
                 
                 int dataRunner = 0;
@@ -190,10 +191,11 @@
             // maintain space information, get size of record suffix (suffix could be entire record)
             int recSize = 0;                        
             int suffixFieldStart = 0;
-            FieldIterator fieldIter = new FieldIterator(cmp.getFields(), this);                 
+            FieldPrefixFieldIterator fieldIter = new FieldPrefixFieldIterator(cmp.getFields(), this);                 
             fieldIter.openRecSlotOff(recSlotOff);
             if(prefixSlotNum == FieldPrefixSlotManager.RECORD_UNCOMPRESSED) {
                 suffixFieldStart = 0;
+                buf.putInt(numUncompressedRecordsOff, buf.getInt(numUncompressedRecordsOff) - 1);
             }
             else {                
                 int prefixSlot = buf.getInt(slotManager.getPrefixSlotOff(prefixSlotNum));
@@ -355,13 +357,13 @@
     }
     
     public ISlotManager getSlotManager() {
-        return null; // TODO: dummy
+        return null;
     }
     
     @Override
     public String printKeys(MultiComparator cmp) {      
         StringBuilder strBuilder = new StringBuilder();
-        FieldIterator rec = new FieldIterator(cmp.getFields(), this);      
+        FieldPrefixFieldIterator rec = new FieldPrefixFieldIterator(cmp.getFields(), this);      
         int numRecords = buf.getInt(numRecordsOff);
         for(int i = 0; i < numRecords; i++) {                               	
         	rec.openRecSlotNum(i);        	
@@ -378,7 +380,9 @@
     
     @Override
     public int getRecordOffset(int slotNum) {        
-    	return slotManager.getRecSlotOff(slotNum);
+    	int recSlotOff = slotManager.getRecSlotOff(slotNum);
+    	int recSlot = buf.getInt(recSlotOff);
+    	return slotManager.decodeSecondSlotField(recSlot);    	
     }
     
     @Override
@@ -433,9 +437,40 @@
 	}
 
     @Override
-    public void insertSorted(byte[] data, MultiComparator cmp) throws Exception {
-        // TODO Auto-generated method stub
-        
+    public void insertSorted(byte[] data, MultiComparator cmp) throws Exception {    	
+    	int freeSpace = buf.getInt(freeSpaceOff);				
+		int fieldsToTruncate = 0;
+		if(buf.getInt(numPrefixRecordsOff) > 0) {
+			// check if record matches last prefix record
+			int prefixSlotOff = slotManager.getPrefixSlotOff(buf.getInt(numPrefixRecordsOff)-1);
+			int prefixSlot = buf.getInt(prefixSlotOff);
+			int numPrefixFields = slotManager.decodeFirstSlotField(prefixSlot);
+			int prefixRecOff = slotManager.decodeSecondSlotField(prefixSlot);
+			
+			if(cmp.fieldRangeCompare(data, 0, buf.array(), prefixRecOff, 0, numPrefixFields) == 0) {
+				fieldsToTruncate = numPrefixFields;													
+			}			
+		}
+				
+		// copy truncated record
+		int recStart = 0;		
+		for(int i = 0; i < fieldsToTruncate; i++) {
+			recStart += cmp.getFields()[i].getLength(data, recStart);
+		}
+		int recLen = data.length - recStart;
+		System.arraycopy(data, recStart, buf.array(), freeSpace, recLen);
+		
+		// insert slot
+		int prefixSlotNum = FieldPrefixSlotManager.RECORD_UNCOMPRESSED;
+		if(fieldsToTruncate > 0) prefixSlotNum = buf.getInt(numPrefixRecordsOff)-1;					
+		else buf.putInt(numUncompressedRecordsOff, buf.getInt(numUncompressedRecordsOff) + 1);					
+		int insSlot = slotManager.encodeSlotFields(prefixSlotNum, FieldPrefixSlotManager.GREATEST_SLOT);				
+		slotManager.insertSlot(insSlot, freeSpace);
+		
+		// update page metadata
+		buf.putInt(numRecordsOff, buf.getInt(numRecordsOff) + 1);
+		buf.putInt(freeSpaceOff, buf.getInt(freeSpaceOff) + recLen);
+		buf.putInt(totalFreeSpaceOff, buf.getInt(totalFreeSpaceOff) - recLen - slotManager.getSlotSize());			
     }
     
     @Override
@@ -579,7 +614,7 @@
 		int splitKeyRecSlotOff = slotManager.getRecSlotEndOff();		
 		
 		int keySize = 0;
-		FieldIterator fieldIter = new FieldIterator(cmp.getFields(), this);
+		FieldPrefixFieldIterator fieldIter = new FieldPrefixFieldIterator(cmp.getFields(), this);
 		fieldIter.openRecSlotOff(splitKeyRecSlotOff);		
 		for(int i = 0; i < cmp.getKeyLength(); i++) {
 			keySize += fieldIter.getFieldSize();
@@ -632,4 +667,14 @@
 	public void setNumUncompressedRecords(int numUncompressedRecords) {
 		buf.putInt(numUncompressedRecordsOff, numUncompressedRecords);
 	}
+	
+	@Override
+	public int getSlotSize() {
+		return slotManager.getSlotSize();
+	}
+	
+	@Override
+    public IFieldIterator createFieldIterator() {
+    	return new FieldPrefixFieldIterator();
+    }
 }
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMFrame.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMFrame.java
index 20a3e19..cca5268 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMFrame.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMFrame.java
@@ -20,9 +20,11 @@
 import java.util.Collections;
 
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeFrame;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.api.ISlotManager;
 import edu.uci.ics.hyracks.storage.am.btree.impls.BTreeException;
 import edu.uci.ics.hyracks.storage.am.btree.impls.MultiComparator;
+import edu.uci.ics.hyracks.storage.am.btree.impls.NSMFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.impls.OrderedSlotManager;
 import edu.uci.ics.hyracks.storage.am.btree.impls.SlotOffRecOff;
 import edu.uci.ics.hyracks.storage.am.btree.impls.SpaceStatus;
@@ -263,4 +265,14 @@
     public boolean compress(MultiComparator cmp) {
         return false;
     }
+    
+    @Override
+    public int getSlotSize() {
+    	return slotManager.getSlotSize();
+    }
+    
+    @Override
+    public IFieldIterator createFieldIterator() {
+    	return new NSMFieldIterator();
+    }
 }
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMInteriorFrame.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMInteriorFrame.java
index 773400a..a3af5b2 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMInteriorFrame.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMInteriorFrame.java
@@ -103,7 +103,7 @@
 		buf.putInt(numRecordsOff, buf.getInt(numRecordsOff) + 1);
 		buf.putInt(freeSpaceOff, buf.getInt(freeSpaceOff) + recSize);
 		buf.putInt(totalFreeSpaceOff, buf.getInt(totalFreeSpaceOff) - recSize - slotManager.getSlotSize());
-		System.arraycopy(data, recSize, buf.array(), rightLeafOff, childPtrSize);			
+		System.arraycopy(data, recSize, buf.array(), rightLeafOff, childPtrSize);
 	}
 		
 	@Override
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMInteriorFrameFactory.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMInteriorFrameFactory.java
index f772761..81a6e34 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMInteriorFrameFactory.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMInteriorFrameFactory.java
@@ -19,6 +19,9 @@
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeInteriorFrameFactory;
 
 public class NSMInteriorFrameFactory implements IBTreeInteriorFrameFactory {
+	
+	private static final long serialVersionUID = 1L;
+
 	@Override
 	public IBTreeInteriorFrame getFrame() {		
 		return new NSMInteriorFrame();
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMLeafFrame.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMLeafFrame.java
index 3d51f05c..c41106d 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMLeafFrame.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMLeafFrame.java
@@ -90,7 +90,7 @@
 		buf.putInt(freeSpaceOff, buf.getInt(freeSpaceOff) + data.length);
 		buf.putInt(totalFreeSpaceOff, buf.getInt(totalFreeSpaceOff) - data.length - slotManager.getSlotSize());
 	}
-
+	
 	@Override
 	public int split(IBTreeFrame rightFrame, byte[] data, MultiComparator cmp, SplitKey splitKey) throws Exception {
 		
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMLeafFrameFactory.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMLeafFrameFactory.java
index 7ef1c8f..169327b 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMLeafFrameFactory.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/frames/NSMLeafFrameFactory.java
@@ -19,6 +19,9 @@
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeLeafFrameFactory;
 
 public class NSMLeafFrameFactory implements IBTreeLeafFrameFactory {
+			
+	private static final long serialVersionUID = 1L;
+
 	@Override
 	public IBTreeLeafFrame getFrame() {		
 		return new NSMLeafFrame();
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
index 74e67af..42d375c 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
@@ -20,6 +20,7 @@
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeCursor;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeFrame;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeInteriorFrame;
@@ -33,7 +34,7 @@
 import edu.uci.ics.hyracks.storage.common.file.FileInfo;
 
 public class BTree {
-		
+	
     private final static int RESTART_OP = Integer.MIN_VALUE;
     private final static int MAX_RESTARTS = 10;
     
@@ -42,13 +43,14 @@
     private final int rootPage = 1; // the root page never changes
     
     private boolean created = false;
-    
+            
     private final IBufferCache bufferCache;
     private int fileId;
     private final IBTreeInteriorFrameFactory interiorFrameFactory;
     private final IBTreeLeafFrameFactory leafFrameFactory;    
     private final MultiComparator cmp;
-    private final ReadWriteLock treeLatch;
+    private final ReadWriteLock treeLatch;    
+    private final RangePredicate diskOrderScanPredicate;
     
     public int rootSplits = 0;
     public int[] splitsByLevel = new int[500];
@@ -93,6 +95,7 @@
         this.leafFrameFactory = leafFrameFactory;       
         this.cmp = cmp;
         this.treeLatch = new ReentrantReadWriteLock(true);
+        this.diskOrderScanPredicate = new RangePredicate(true, null, null, cmp);
     }
     
     public void create(int fileId, IBTreeLeafFrame leafFrame, IBTreeMetaDataFrame metaFrame) throws Exception {
@@ -102,7 +105,7 @@
     	treeLatch.writeLock().lock();	
     	try {
     	
-    		// check if another thread bet us to it
+    		// check if another thread beat us to it
     		if(created) return;    		    		
     		
     		// initialize meta data page
@@ -285,6 +288,26 @@
         }
     }
     
+    public int getMaxPage(IBTreeMetaDataFrame metaFrame) throws HyracksDataException {
+    	ICachedPage metaNode = bufferCache.pin(FileInfo.getDiskPageId(fileId, metaDataPage), false);
+		pins++;
+		
+		metaNode.acquireWriteLatch();
+		writeLatchesAcquired++;
+		int maxPage = -1;
+		try {
+			metaFrame.setPage(metaNode);			
+			maxPage = metaFrame.getMaxPage();
+		} finally {
+			metaNode.releaseWriteLatch();
+			writeLatchesReleased++;
+			bufferCache.unpin(metaNode);
+			unpins++;
+		}
+		
+		return maxPage;
+    }
+    
     public void printTree(IBTreeLeafFrame leafFrame, IBTreeInteriorFrame interiorFrame) throws Exception {
         printTree(rootPage, null, false, leafFrame, interiorFrame);
     }
@@ -393,7 +416,7 @@
         cursor.setFileId(fileId);
         cursor.setCurrentPageId(currentPageId);
         cursor.setMaxPageId(maxPageId);
-        cursor.open(page, null);
+        cursor.open(page, diskOrderScanPredicate);
     }
     
     public void search(IBTreeCursor cursor, RangePredicate pred, IBTreeLeafFrame leafFrame,
@@ -1179,13 +1202,13 @@
 
             interiorFrame.setPage(leafFrontier.page);
             interiorFrame.initBuffer((byte) 0);
-            interiorMaxBytes = (int) ((float) interiorFrame.getTotalFreeSpace() * fillFactor);
-
+            interiorMaxBytes = (int) ((float) interiorFrame.getBuffer().capacity() * fillFactor);
+            
             leafFrame.setPage(leafFrontier.page);
             leafFrame.initBuffer((byte) 0);
-            leafMaxBytes = (int) ((float) leafFrame.getTotalFreeSpace() * fillFactor);
-
-            slotSize = leafFrame.getSlotManager().getSlotSize();
+            leafMaxBytes = (int) ((float) leafFrame.getBuffer().capacity() * fillFactor);
+            
+            slotSize = leafFrame.getSlotSize();
 
             this.leafFrame = leafFrame;
             this.interiorFrame = interiorFrame;
@@ -1196,7 +1219,6 @@
 
         private void addLevel() throws Exception {
             NodeFrontier frontier = new NodeFrontier();
-            frontier.bytesInserted = 0;
             frontier.pageId = getFreePage(metaFrame);
             frontier.page = bufferCache.pin(FileInfo.getDiskPageId(fileId, frontier.pageId), bulkNewPage);
             frontier.page.acquireWriteLatch();
@@ -1218,10 +1240,9 @@
         ctx.interiorFrame.setPage(frontier.page);
         byte[] insBytes = ctx.splitKey.getData();
         int keySize = cmp.getKeySize(insBytes, 0);
-        int spaceNeeded = keySize + ctx.slotSize + 4; // TODO: this is a dirty
-        // constant for the size
-        // of a child pointer
-        if (frontier.bytesInserted + spaceNeeded > ctx.interiorMaxBytes) {
+        int spaceNeeded = keySize + ctx.slotSize + 4; // TODO: this is a dirty constant for the size of a child pointer
+        int spaceUsed = ctx.interiorFrame.getBuffer().capacity() - ctx.interiorFrame.getTotalFreeSpace();
+        if (spaceUsed + spaceNeeded > ctx.interiorMaxBytes) {
             ctx.interiorFrame.deleteGreatest(cmp);
             int splitKeySize = cmp.getKeySize(frontier.lastRecord, 0);
             ctx.splitKey.initData(splitKeySize);
@@ -1239,11 +1260,9 @@
             frontier.page.acquireWriteLatch();
             ctx.interiorFrame.setPage(frontier.page);
             ctx.interiorFrame.initBuffer((byte) level);
-            frontier.bytesInserted = 0;
         }
         ctx.interiorFrame.insertSorted(insBytes, cmp);
         frontier.lastRecord = insBytes;
-        frontier.bytesInserted += spaceNeeded;
     }
     
     // assumes btree has been created and opened
@@ -1257,7 +1276,15 @@
         IBTreeLeafFrame leafFrame = ctx.leafFrame;
         
         int spaceNeeded = record.length + ctx.slotSize;
-        if (leafFrontier.bytesInserted + spaceNeeded > ctx.leafMaxBytes) {
+        int spaceUsed = leafFrame.getBuffer().capacity() - leafFrame.getTotalFreeSpace();
+        
+        // try to free space by compression
+        if (spaceUsed + spaceNeeded > ctx.leafMaxBytes) {
+        	leafFrame.compress(cmp);
+        	spaceUsed = leafFrame.getBuffer().capacity() - leafFrame.getTotalFreeSpace();
+        }
+        
+        if (spaceUsed + spaceNeeded > ctx.leafMaxBytes) {
             int splitKeySize = cmp.getKeySize(leafFrontier.lastRecord, 0);
             ctx.splitKey.initData(splitKeySize);            
             System.arraycopy(leafFrontier.lastRecord, 0, ctx.splitKey.getData(), 0, splitKeySize);
@@ -1276,13 +1303,11 @@
             leafFrame.setPage(leafFrontier.page);
             leafFrame.initBuffer((byte) 0);
             leafFrame.setPrevLeaf(prevPageId);
-            leafFrontier.bytesInserted = 0;
         }
         
         leafFrame.setPage(leafFrontier.page);
         leafFrame.insertSorted(record, cmp);
         leafFrontier.lastRecord = record;
-        leafFrontier.bytesInserted += spaceNeeded;
     }
     
     public void endBulkLoad(BulkLoadContext ctx) throws Exception {                
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTreeOp.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTreeOp.java
index b1909a9..4c0ef81 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTreeOp.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTreeOp.java
@@ -18,5 +18,6 @@
 public enum BTreeOp {
 	BTO_INSERT,
 	BTO_DELETE,
-	BTO_SEARCH	
+	BTO_UPDATE,
+	BTO_SEARCH
 }
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/DiskOrderScanCursor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/DiskOrderScanCursor.java
index 441ea02..443cf2a 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/DiskOrderScanCursor.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/DiskOrderScanCursor.java
@@ -17,6 +17,7 @@
 
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeCursor;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeLeafFrame;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.api.ISearchPredicate;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
@@ -27,7 +28,6 @@
     // TODO: might want to return records in physical order, not logical order to speed up access
     
     private int recordNum = 0;
-    private int recordOffset = -1;
     private int fileId = -1;    
     int currentPageId = -1;
     int maxPageId = -1; // TODO: figure out how to scan to the end of file, this is dirty and may not with concurrent updates
@@ -35,8 +35,12 @@
     private IBTreeLeafFrame frame = null;
     private IBufferCache bufferCache = null;
     
+    private IFieldIterator fieldIter;
+    
     public DiskOrderScanCursor(IBTreeLeafFrame frame) {
         this.frame = frame;
+        this.fieldIter = frame.createFieldIterator();
+		this.fieldIter.setFrame(frame);
     }
     
     @Override
@@ -45,12 +49,13 @@
         bufferCache.unpin(page);
         page = null;
     }
-
+    
     @Override
-    public int getOffset() {
-        return recordOffset;
-    }
-
+    public IFieldIterator getFieldIterator() {
+		fieldIter.reset();
+		return fieldIter;
+	}
+    
     @Override
     public ICachedPage getPage() {
         return page;
@@ -80,7 +85,7 @@
         if(recordNum >= frame.getNumRecords()) {
             boolean nextLeafExists = positionToNextLeaf(true);
             if(nextLeafExists) {
-                recordOffset = frame.getRecordOffset(recordNum);
+            	fieldIter.openRecSlotNum(recordNum);
                 return true;
             }
             else {
@@ -88,7 +93,7 @@
             }
         }        
         
-        recordOffset = frame.getRecordOffset(recordNum);
+        fieldIter.openRecSlotNum(recordNum);        
         return true;
     }
 
@@ -108,6 +113,9 @@
         this.page = page;
         recordNum = 0;
         frame.setPage(page);
+        RangePredicate pred = (RangePredicate)searchPred;
+		MultiComparator cmp = pred.getComparator();
+		this.fieldIter.setFields(cmp.getFields());
         boolean leafExists = positionToNextLeaf(false);
         if(!leafExists) {
             throw new Exception("Failed to open disk-order scan cursor for B-tree. Traget B-tree has no leaves.");
@@ -117,7 +125,6 @@
     @Override
     public void reset() {
         recordNum = 0;
-        recordOffset = 0;
         currentPageId = -1;
         maxPageId = -1;
         page = null;     
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/FieldIterator.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/FieldPrefixFieldIterator.java
similarity index 87%
rename from hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/FieldIterator.java
rename to hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/FieldPrefixFieldIterator.java
index 8132199..f0fdf1d 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/FieldIterator.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/FieldPrefixFieldIterator.java
@@ -15,11 +15,15 @@
 
 package edu.uci.ics.hyracks.storage.am.btree.impls;
 
+import java.nio.ByteBuffer;
+
+import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeFrame;
 import edu.uci.ics.hyracks.storage.am.btree.api.IFieldAccessor;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.frames.FieldPrefixNSMLeafFrame;
 
-//TODO: make members private, only for debugging now
-public class FieldIterator {
+// TODO: make members private, only for debugging now
+public class FieldPrefixFieldIterator implements IFieldIterator {
     public int recSlotOff = -1;
     public int recOff = -1;
     public int prefixSlotNum = FieldPrefixSlotManager.RECORD_UNCOMPRESSED;
@@ -30,13 +34,16 @@
     public int currentField = -1;
     public int recOffRunner = -1;
     
-    public FieldIterator(IFieldAccessor[] fields, FieldPrefixNSMLeafFrame frame) {
+    public FieldPrefixFieldIterator() {    	
+    }
+    
+    public FieldPrefixFieldIterator(IFieldAccessor[] fields, FieldPrefixNSMLeafFrame frame) {
         this.fields = fields;
         this.frame = frame;
     }
     
-    public void setFrame(FieldPrefixNSMLeafFrame frame) {
-        this.frame = frame;        
+    public void setFrame(IBTreeFrame frame) {
+        this.frame = (FieldPrefixNSMLeafFrame)frame;        
     }
     
     public void setFields(IFieldAccessor[] fields) {
@@ -121,4 +128,8 @@
         return bytesWritten;
     }
     
+    @Override
+    public ByteBuffer getBuffer() {
+    	return frame.getBuffer();
+    }
 }
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/FieldPrefixSlotManager.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/FieldPrefixSlotManager.java
index de4c913..e6d28bd 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/FieldPrefixSlotManager.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/FieldPrefixSlotManager.java
@@ -30,7 +30,7 @@
 	
 	private ByteBuffer buf;
 	private FieldPrefixNSMLeafFrame frame;
-	FieldIterator fieldIter = new FieldIterator(null, null);
+	FieldPrefixFieldIterator fieldIter = new FieldPrefixFieldIterator(null, null);
 	
 	public int decodeFirstSlotField(int slot) {
 		return (slot & 0xFF000000) >>> 24;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/MultiComparator.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/MultiComparator.java
index 659cfbf..6dbd9c5 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/MultiComparator.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/MultiComparator.java
@@ -17,6 +17,7 @@
 
 import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparator;
 import edu.uci.ics.hyracks.storage.am.btree.api.IFieldAccessor;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
 
 public class MultiComparator {
     	
@@ -69,6 +70,24 @@
     	return 0;
 	}
 	
+	public int compare(byte[] data, int recOff, IFieldIterator fieldIter) {
+		 fieldIter.reset();
+         
+         int recRunner = 0;
+         int cmp = 0;
+         for(int i = 0; i < cmps.length; i++) {
+        	 int recFieldLen = fields[i].getLength(data, recRunner);
+        	 cmp = cmps[i].compare(data, recRunner, recFieldLen, fieldIter.getBuffer().array(), fieldIter.getFieldOff(), fieldIter.getFieldSize());          
+             if(cmp < 0) return -1;
+             else if(cmp > 0) return 1;             
+             fieldIter.nextField();
+             recRunner += recFieldLen;
+         }
+         
+         fieldIter.reset();
+         return 0;
+	}
+	
 	public int fieldRangeCompare(byte[] dataA, int recOffA, byte[] dataB, int recOffB, int startFieldIndex, int numFields) {
 		int lenA;
 		int lenB;
@@ -100,6 +119,16 @@
 		return runner - recOff;
 	}		
 	
+	public String printRecord(IFieldIterator fieldIter) {
+		StringBuilder strBuilder = new StringBuilder();	    
+		fieldIter.reset();
+		for(int i = 0; i < fields.length; i++) {
+			strBuilder.append(fields[i].print(fieldIter.getBuffer().array(), fieldIter.getFieldOff()) + " ");						
+			fieldIter.nextField();
+		}
+		return strBuilder.toString();
+	}
+		
 	public String printRecord(byte[] data, int recOff) {
 		StringBuilder strBuilder = new StringBuilder();
 	    int runner = recOff;
@@ -109,7 +138,7 @@
 		}
 		return strBuilder.toString();
 	}
-	
+		
 	public String printKey(byte[] data, int recOff) {
 		StringBuilder strBuilder = new StringBuilder();		
 		int runner = recOff;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/NSMFieldIterator.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/NSMFieldIterator.java
new file mode 100644
index 0000000..760fa8a
--- /dev/null
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/NSMFieldIterator.java
@@ -0,0 +1,91 @@
+/*
+ * 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.btree.impls;
+
+import java.nio.ByteBuffer;
+
+import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeFrame;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldAccessor;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
+import edu.uci.ics.hyracks.storage.am.btree.frames.NSMFrame;
+
+public class NSMFieldIterator implements IFieldIterator {
+    public int recOff = -1;
+    public IFieldAccessor[] fields;
+    public NSMFrame frame;
+    
+    public int currentField = -1;
+    public int recOffRunner = -1;
+		
+	public NSMFieldIterator() {    	
+    }
+    
+    public NSMFieldIterator(IFieldAccessor[] fields, NSMFrame frame) {
+        this.fields = fields;
+        this.frame = frame;
+    }
+    
+    public void setFrame(NSMFrame frame) {
+        this.frame = frame;        
+    }
+    
+    public void setFields(IFieldAccessor[] fields) {
+        this.fields = fields;
+    }
+    
+    public void openRecSlotNum(int recSlotNum) {                 
+    	int recSlotOff = frame.getSlotManager().getSlotOff(recSlotNum);
+    	openRecSlotOff(recSlotOff);
+    }
+    
+    public void openRecSlotOff(int recSlotOff) {
+    	recOff = frame.getSlotManager().getRecOff(recSlotOff);
+        reset();
+    }
+    
+    // re-position to first field
+    public void reset() {
+        currentField = 0;
+        recOffRunner = recOff;               
+    }
+    
+    public void nextField() {                   
+    	recOffRunner += fields[currentField].getLength(frame.getBuffer().array(), recOffRunner);    
+    }
+    
+    public int getFieldOff() {
+        return recOffRunner;
+    }        
+    
+    public int getFieldSize() {
+        return fields[currentField].getLength(frame.getBuffer().array(), recOffRunner);                
+    }
+    
+    public int copyFields(int startField, int endField, byte[] dest, int destOff) {
+    
+    	return 0;
+    }
+
+	@Override
+	public void setFrame(IBTreeFrame frame) {
+		this.frame = (NSMFrame)frame;
+	}	
+	
+	@Override
+    public ByteBuffer getBuffer() {
+    	return frame.getBuffer();
+    }
+}
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/NodeFrontier.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/NodeFrontier.java
index df5f064..6dcafb4 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/NodeFrontier.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/NodeFrontier.java
@@ -18,7 +18,6 @@
 import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
 
 public class NodeFrontier {
-	public int bytesInserted;
 	public ICachedPage page;
 	public int pageId;
 	public byte[] lastRecord;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/RangePredicate.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/RangePredicate.java
index 68d7ad2..d71019f 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/RangePredicate.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/RangePredicate.java
@@ -25,7 +25,7 @@
 	protected byte[] lowKeys = null;
 	protected byte[] highKeys = null;
 	protected MultiComparator cmp;
-	
+			
 	public RangePredicate() {
 	}
 	
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/RangeSearchCursor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/RangeSearchCursor.java
index 99784bc..b6234fb 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/RangeSearchCursor.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/RangeSearchCursor.java
@@ -17,6 +17,7 @@
 
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeCursor;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeLeafFrame;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.api.ISearchPredicate;
 import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
 import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
@@ -32,8 +33,12 @@
 	private IBTreeLeafFrame frame = null;
 	private IBufferCache bufferCache = null;
 	
+	private IFieldIterator fieldIter;
+	
 	public RangeSearchCursor(IBTreeLeafFrame frame) {
-		this.frame = frame;		
+		this.frame = frame;
+		this.fieldIter = frame.createFieldIterator();
+		this.fieldIter.setFrame(frame);
 	}
 	
 	@Override
@@ -42,12 +47,12 @@
 		bufferCache.unpin(page);
 		page = null;
 	}
-
-	@Override
-	public int getOffset() {
-		return recordOffset;
+	
+	public IFieldIterator getFieldIterator() {
+		fieldIter.reset();
+		return fieldIter;
 	}
-
+	
 	@Override
 	public ICachedPage getPage() {
 		return page;
@@ -86,10 +91,12 @@
 		MultiComparator cmp = pred.getComparator();
 		if(searchPred.isForward()) {
 			byte[] highKeys = pred.getHighKeys();			
-			recordOffset = frame.getRecordOffset(recordNum);
+			fieldIter.openRecSlotNum(recordNum);
+			//recordOffset = frame.getRecordOffset(recordNum);
 			
-			if(highKeys == null) return true;						
-			if(cmp.compare(highKeys, 0, page.getBuffer().array(), recordOffset) < 0) {
+			if(highKeys == null) return true;									
+			//if(cmp.compare(highKeys, 0, page.getBuffer().array(), recordOffset) < 0) {
+			if(cmp.compare(highKeys, 0, fieldIter) < 0) {
 				return false;
 			}
 			else {
@@ -111,7 +118,7 @@
 	}
 
 	@Override
-	public void next() throws Exception {		
+	public void next() throws Exception {				
 		recordNum++;
 	}
 	
@@ -122,35 +129,40 @@
 			this.page.releaseReadLatch();
 			bufferCache.unpin(this.page);
 		}
-		
+						
 		this.searchPred = searchPred;
 		this.page = page;
-		frame.setPage(page);
+		frame.setPage(page);					
 		
 		// position recordNum to the first appropriate key
 		// TODO: can be done more efficiently with binary search but this needs some thinking/refactoring
 		RangePredicate pred = (RangePredicate)searchPred;
 		MultiComparator cmp = pred.getComparator();
+		this.fieldIter.setFields(cmp.getFields());
 		if(searchPred.isForward()) {
 			byte[] lowKeys = pred.getLowKeys();
 						
-			recordOffset = frame.getRecordOffset(recordNum);
+			//recordOffset = frame.getRecordOffset(recordNum);			
+			fieldIter.openRecSlotNum(recordNum);
 			if(lowKeys == null) return; // null means -infinity
-			
-			while(cmp.compare(lowKeys, 0, page.getBuffer().array(), recordOffset) > 0 && recordNum < frame.getNumRecords()) {				
+						
+			while(cmp.compare(lowKeys, 0, fieldIter) > 0 && recordNum < frame.getNumRecords()) {
+			//while(cmp.compare(lowKeys, 0, page.getBuffer().array(), recordOffset) > 0 && recordNum < frame.getNumRecords()) {
 			    recordNum++;
-			    recordOffset = frame.getRecordOffset(recordNum);
-			}
+			    fieldIter.openRecSlotNum(recordNum);
+			}						
 		}
 		else {
 			byte[] highKeys = pred.getHighKeys();
 						
-			recordOffset = frame.getRecordOffset(frame.getNumRecords() - recordNum - 1);			
+			//recordOffset = frame.getRecordOffset(frame.getNumRecords() - recordNum - 1);
+			fieldIter.openRecSlotNum(recordNum);
 			if(highKeys != null) return; // null means +infinity
 			    
 			while(cmp.compare(highKeys, 0, page.getBuffer().array(), recordOffset) < 0 && recordNum < frame.getNumRecords()) {				
 			    recordNum++;
-			    recordOffset = frame.getRecordOffset(frame.getNumRecords() - recordNum - 1);				
+			    fieldIter.openRecSlotNum(recordNum);
+			    //recordOffset = frame.getRecordOffset(frame.getNumRecords() - recordNum - 1);			
 			}						
 		}
 	}
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/types/Int32AccessorFactory.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/types/Int32AccessorFactory.java
index b8607c0..4eceeb2 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/types/Int32AccessorFactory.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/types/Int32AccessorFactory.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.types;
 
 import edu.uci.ics.hyracks.storage.am.btree.api.IFieldAccessor;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/types/UTF8StringAccessorFactory.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/types/UTF8StringAccessorFactory.java
index e2d8053..1359190 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/types/UTF8StringAccessorFactory.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/types/UTF8StringAccessorFactory.java
@@ -1,3 +1,18 @@
+/*
+ * 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.btree.types;
 
 import edu.uci.ics.hyracks.storage.am.btree.api.IFieldAccessor;
diff --git a/hyracks-storage-am-btree/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeTest.java b/hyracks-storage-am-btree/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeTest.java
index 1fb08e4..3caba23 100644
--- a/hyracks-storage-am-btree/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeTest.java
+++ b/hyracks-storage-am-btree/src/test/java/edu/uci/ics/hyracks/storage/am/btree/BTreeTest.java
@@ -37,6 +37,7 @@
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeMetaDataFrame;
 import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeMetaDataFrameFactory;
 import edu.uci.ics.hyracks.storage.am.btree.api.IFieldAccessor;
+import edu.uci.ics.hyracks.storage.am.btree.api.IFieldIterator;
 import edu.uci.ics.hyracks.storage.am.btree.frames.MetaDataFrameFactory;
 import edu.uci.ics.hyracks.storage.am.btree.frames.NSMInteriorFrameFactory;
 import edu.uci.ics.hyracks.storage.am.btree.frames.NSMLeafFrameFactory;
@@ -56,6 +57,7 @@
 import edu.uci.ics.hyracks.storage.common.file.FileManager;
 
 public class BTreeTest {    
+	
     private static final int PAGE_SIZE = 128;
     // private static final int PAGE_SIZE = 8192;
     private static final int NUM_PAGES = 10;
@@ -169,9 +171,8 @@
         try {
             while (scanCursor.hasNext()) {
                 scanCursor.next();
-                byte[] array = scanCursor.getPage().getBuffer().array();
-                int recOffset = scanCursor.getOffset();                
-                String rec = cmp.printRecord(array, recOffset);
+                IFieldIterator fieldIter = scanCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
                 print(rec + "\n");
             }
         } catch (Exception e) {
@@ -187,9 +188,8 @@
         try {
             while (diskOrderCursor.hasNext()) {
                 diskOrderCursor.next();
-                byte[] array = diskOrderCursor.getPage().getBuffer().array();
-                int recOffset = diskOrderCursor.getOffset();                
-                String rec = cmp.printRecord(array, recOffset);
+                IFieldIterator fieldIter = diskOrderCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
                 print(rec + "\n");
             }
         } catch (Exception e) {
@@ -224,10 +224,9 @@
         try {
             while (rangeCursor.hasNext()) {
                 rangeCursor.next();
-                byte[] array = rangeCursor.getPage().getBuffer().array();
-                int recOffset = rangeCursor.getOffset();                
-                String rec = cmp.printRecord(array, recOffset);
-                print(rec + "\n");         
+                IFieldIterator fieldIter = rangeCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
+                print(rec + "\n"); 
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -329,10 +328,9 @@
         try {
             while (scanCursor.hasNext()) {
                 scanCursor.next();
-                byte[] array = scanCursor.getPage().getBuffer().array();
-                int recOffset = scanCursor.getOffset();                
-                String rec = cmp.printRecord(array, recOffset);
-                print(rec + "\n");                
+                IFieldIterator fieldIter = scanCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
+                print(rec + "\n");         
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -365,10 +363,9 @@
         try {
             while (rangeCursor.hasNext()) {
                 rangeCursor.next();
-                byte[] array = rangeCursor.getPage().getBuffer().array();
-                int recOffset = rangeCursor.getOffset();                
-                String rec = cmp.printRecord(array, recOffset);
-                print(rec + "\n");                
+                IFieldIterator fieldIter = rangeCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
+                print(rec + "\n");         
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -461,10 +458,9 @@
         try {
             while (scanCursor.hasNext()) {
                 scanCursor.next();
-                byte[] array = scanCursor.getPage().getBuffer().array();
-                int recOffset = scanCursor.getOffset();                
-                String rec = cmp.printRecord(array, recOffset);
-                print(rec + "\n");                
+                IFieldIterator fieldIter = scanCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
+                print(rec + "\n");          
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -498,10 +494,9 @@
         try {
             while (rangeCursor.hasNext()) {
                 rangeCursor.next();
-                byte[] array = rangeCursor.getPage().getBuffer().array();
-                int recOffset = rangeCursor.getOffset();                
-                String rec = cmp.printRecord(array, recOffset);
-                print(rec + "\n");         
+                IFieldIterator fieldIter = rangeCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
+                print(rec + "\n");    
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -736,15 +731,15 @@
         searchCmps[0] = IntegerBinaryComparatorFactory.INSTANCE.createBinaryComparator();
         MultiComparator searchCmp = new MultiComparator(searchCmps, fields);
         
-        RangePredicate rangePred = new RangePredicate(false, lowKey, highKey, searchCmp);
+        // TODO: check when searching backwards
+        RangePredicate rangePred = new RangePredicate(true, lowKey, highKey, searchCmp);
         btree.search(rangeCursor, rangePred, leafFrame, interiorFrame);
 
         try {
             while (rangeCursor.hasNext()) {
                 rangeCursor.next();
-                byte[] array = rangeCursor.getPage().getBuffer().array();
-                int recOffset = rangeCursor.getOffset();                
-                String rec = cmp.printRecord(array, recOffset);
+                IFieldIterator fieldIter = rangeCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
                 print(rec + "\n");
             }
         } catch (Exception e) {
@@ -881,9 +876,8 @@
         try {
             while (scanCursor.hasNext()) {
                 scanCursor.next();
-                byte[] array = scanCursor.getPage().getBuffer().array();
-                int recOffset = scanCursor.getOffset();                
-                String rec = cmp.printRecord(array, recOffset);
+                IFieldIterator fieldIter = scanCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
                 print(rec + "\n");
             }
         } catch (Exception e) {
@@ -922,9 +916,8 @@
         try {
             while (rangeCursor.hasNext()) {
                 rangeCursor.next();
-                byte[] array = rangeCursor.getPage().getBuffer().array();
-                int recOffset = rangeCursor.getOffset();                
-                String rec = cmp.printRecord(array, recOffset);
+                IFieldIterator fieldIter = rangeCursor.getFieldIterator();                                
+                String rec = cmp.printRecord(fieldIter);
                 print(rec + "\n");
             }
         } catch (Exception e) {