Added BTreeStats operator. Fixed some minor bugs in the process.

git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_indexes@467 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 a9b9502..b9426d3 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
@@ -52,6 +52,7 @@
 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.BTreeSearchOperatorDescriptor;
+import edu.uci.ics.hyracks.storage.am.btree.dataflow.BTreeStatsOperatorDescriptor;
 import edu.uci.ics.hyracks.storage.am.btree.dataflow.IBTreeRegistryProvider;
 import edu.uci.ics.hyracks.storage.am.btree.frames.NSMInteriorFrameFactory;
 import edu.uci.ics.hyracks.storage.am.btree.frames.NSMLeafFrameFactory;
@@ -90,8 +91,7 @@
 	private static String primaryBtreeName = "primary"
 			+ simpleDateFormat.format(new Date());
 	private static String primaryFileName = System
-			.getProperty("java.io.tmpdir")
-			+ sep + primaryBtreeName;
+			.getProperty("java.io.tmpdir") + sep + primaryBtreeName;
 
 	private IFileSplitProvider primaryBtreeSplitProvider = new ConstantFileSplitProvider(
 			new FileSplit[] { new FileSplit(NC1_ID, new FileReference(new File(
@@ -121,8 +121,7 @@
 	private static String secondaryBtreeName = "secondary"
 			+ simpleDateFormat.format(new Date());
 	private static String secondaryFileName = System
-			.getProperty("java.io.tmpdir")
-			+ sep + secondaryBtreeName;
+			.getProperty("java.io.tmpdir") + sep + secondaryBtreeName;
 
 	private IFileSplitProvider secondaryBtreeSplitProvider = new ConstantFileSplitProvider(
 			new FileSplit[] { new FileSplit(NC1_ID, new FileReference(new File(
@@ -216,6 +215,22 @@
 	}
 
 	@Test
+	public void showPrimaryIndexStats() throws Exception {
+		JobSpecification spec = new JobSpecification();
+		
+		BTreeStatsOperatorDescriptor primaryStatsOp = new BTreeStatsOperatorDescriptor(
+				spec, storageManager, btreeRegistryProvider,
+				primaryBtreeSplitProvider, primaryInteriorFrameFactory,
+				primaryLeafFrameFactory, primaryTypeTraits,
+				primaryComparatorFactories);
+		PartitionConstraintHelper.addAbsoluteLocationConstraint(spec,
+				primaryStatsOp, NC1_ID);
+		
+		spec.addRoot(primaryStatsOp);
+		runTest(spec);
+	}	
+		
+	@Test
 	public void scanPrimaryIndexTest() throws Exception {
 		JobSpecification spec = new JobSpecification();
 
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeOpHelper.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeOpHelper.java
index 770bbba..501436a 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeOpHelper.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeOpHelper.java
@@ -25,7 +25,6 @@
 import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrameFactory;
-import edu.uci.ics.hyracks.storage.am.common.frames.LIFOMetaDataFrame;
 import edu.uci.ics.hyracks.storage.am.common.frames.LIFOMetaDataFrameFactory;
 import edu.uci.ics.hyracks.storage.am.common.freepage.LinkedListFreePageManager;
 import edu.uci.ics.hyracks.storage.am.common.ophelpers.MultiComparator;
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeStatsOperatorDescriptor.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeStatsOperatorDescriptor.java
new file mode 100644
index 0000000..a0b0545
--- /dev/null
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeStatsOperatorDescriptor.java
@@ -0,0 +1,32 @@
+package edu.uci.ics.hyracks.storage.am.btree.dataflow;
+
+import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.dataflow.IOperatorNodePushable;
+import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
+import edu.uci.ics.hyracks.api.dataflow.value.IRecordDescriptorProvider;
+import edu.uci.ics.hyracks.api.dataflow.value.ITypeTrait;
+import edu.uci.ics.hyracks.api.job.IOperatorEnvironment;
+import edu.uci.ics.hyracks.api.job.JobSpecification;
+import edu.uci.ics.hyracks.dataflow.std.file.IFileSplitProvider;
+import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeInteriorFrameFactory;
+import edu.uci.ics.hyracks.storage.am.btree.api.IBTreeLeafFrameFactory;
+import edu.uci.ics.hyracks.storage.common.IStorageManagerInterface;
+
+public class BTreeStatsOperatorDescriptor extends AbstractBTreeOperatorDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    
+    public BTreeStatsOperatorDescriptor(JobSpecification spec, IStorageManagerInterface storageManager,
+            IBTreeRegistryProvider btreeRegistryProvider, IFileSplitProvider fileSplitProvider,
+            IBTreeInteriorFrameFactory interiorFactory, IBTreeLeafFrameFactory leafFactory, ITypeTrait[] typeTraits,
+            IBinaryComparatorFactory[] comparatorFactories) {
+        super(spec, 0, 0, null, storageManager, btreeRegistryProvider, fileSplitProvider, interiorFactory, leafFactory,
+                typeTraits, comparatorFactories);
+    }
+    
+    @Override
+    public IOperatorNodePushable createPushRuntime(IHyracksStageletContext ctx, IOperatorEnvironment env,
+            IRecordDescriptorProvider recordDescProvider, int partition, int nPartitions) {
+        return new BTreeStatsOperatorNodePushable(this, ctx, partition);
+    }
+}
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeStatsOperatorNodePushable.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeStatsOperatorNodePushable.java
new file mode 100644
index 0000000..111b2da
--- /dev/null
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/dataflow/BTreeStatsOperatorNodePushable.java
@@ -0,0 +1,77 @@
+/*
+ * 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.comm.IFrameWriter;
+import edu.uci.ics.hyracks.api.context.IHyracksStageletContext;
+import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.dataflow.std.base.AbstractOperatorNodePushable;
+import edu.uci.ics.hyracks.storage.am.btree.impls.BTree;
+import edu.uci.ics.hyracks.storage.am.common.utility.TreeIndexStats;
+import edu.uci.ics.hyracks.storage.am.common.utility.TreeIndexStatsGatherer;
+import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
+
+public class BTreeStatsOperatorNodePushable extends
+AbstractOperatorNodePushable {
+	private final BTreeOpHelper btreeOpHelper;
+	private final IHyracksStageletContext ctx;
+	private TreeIndexStatsGatherer statsGatherer;
+
+	public BTreeStatsOperatorNodePushable(
+			AbstractBTreeOperatorDescriptor opDesc,
+			IHyracksStageletContext ctx, int partition) {
+		btreeOpHelper = new BTreeOpHelper(opDesc, ctx, partition,
+				BTreeOpHelper.BTreeMode.CREATE_BTREE);
+		this.ctx = ctx;
+	}
+
+	@Override
+	public void deinitialize() throws HyracksDataException {
+	}
+
+	@Override
+	public int getInputArity() {
+		return 0;
+	}
+
+	@Override
+	public IFrameWriter getInputFrameWriter(int index) {
+		return null;
+	}
+
+	@Override
+	public void initialize() throws HyracksDataException {
+		try {
+			btreeOpHelper.init();
+			btreeOpHelper.getBTree().open(btreeOpHelper.getBTreeFileId());
+
+			BTree btree = btreeOpHelper.getBTree();			
+			IBufferCache bufferCache = btreeOpHelper.getOperatorDescriptor().getStorageManager().getBufferCache(ctx);
+
+			statsGatherer = new TreeIndexStatsGatherer(bufferCache, btree.getFreePageManager(), btreeOpHelper.getBTreeFileId(), btree.getRootPageId());
+			TreeIndexStats stats = statsGatherer.gatherStats(btree.getLeafFrameFactory().getFrame(), btree.getInteriorFrameFactory().getFrame(), btree.getFreePageManager().getMetaDataFrameFactory().getFrame());
+			System.err.println(stats.toString());
+		} catch (Exception e) {
+			btreeOpHelper.deinit();
+			throw new HyracksDataException(e);
+		}
+	}
+
+	@Override
+	public void setOutputFrameWriter(int index, IFrameWriter writer,
+			RecordDescriptor recordDesc) {		
+	}
+}
\ No newline at end of file
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 b65bd02..7fb424d 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
@@ -1281,15 +1281,25 @@
 		ICachedPage rootNode = bufferCache.pin(BufferedFileHandle
 				.getDiskPageId(fileId, rootPage), bulkNewPage);
 		rootNode.acquireWriteLatch();
+		NodeFrontier lastNodeFrontier = ctx.nodeFrontiers.get(ctx.nodeFrontiers
+				.size() - 1);
+		IBTreeInteriorFrame interiorFrame = ctx.interiorFrame;
 		try {
-			ICachedPage toBeRoot = ctx.nodeFrontiers.get(ctx.nodeFrontiers
-					.size() - 1).page;
+			ICachedPage toBeRoot = lastNodeFrontier.page;
 			System.arraycopy(toBeRoot.getBuffer().array(), 0, rootNode
 					.getBuffer().array(), 0, toBeRoot.getBuffer().capacity());
 		} finally {
 			rootNode.releaseWriteLatch();
 			bufferCache.unpin(rootNode);
 
+			// register old root as free page
+			System.out.println("ADDING FREE PAGE: " + lastNodeFrontier.pageId);
+			freePageManager.addFreePage(ctx.metaFrame, lastNodeFrontier.pageId);
+			
+			// make old root a free page
+			interiorFrame.setPage(lastNodeFrontier.page);
+			interiorFrame.initBuffer(freePageManager.getFreePageLevelIndicator());
+						
 			// cleanup
 			for (int i = 0; i < ctx.nodeFrontiers.size(); i++) {
 				ctx.nodeFrontiers.get(i).page.releaseWriteLatch();
diff --git a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexStats.java b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexStats.java
index 861f43c..ad7166e 100644
--- a/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexStats.java
+++ b/hyracks-storage-am-common/src/main/java/edu/uci/ics/hyracks/storage/am/common/utility/TreeIndexStats.java
@@ -2,12 +2,15 @@
 
 import java.text.DecimalFormat;
 
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.api.dataflow.value.RecordDescriptor;
+import edu.uci.ics.hyracks.dataflow.common.data.marshalling.IntegerSerializerDeserializer;
 import edu.uci.ics.hyracks.storage.am.common.api.IFreePageManager;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexFrame;
 import edu.uci.ics.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
 
 public class TreeIndexStats {
-
+	
 	private TreeIndexNodeTypeStats rootStats = new TreeIndexNodeTypeStats();
 	private TreeIndexNodeTypeStats interiorStats = new TreeIndexNodeTypeStats();
 	private TreeIndexNodeTypeStats leafStats = new TreeIndexNodeTypeStats();	
@@ -129,4 +132,6 @@
 			return sumFillFactors / numPages;
 		}
 	}	
+	
+	
 }