You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by am...@apache.org on 2016/12/16 07:49:48 UTC

[6/9] asterixdb git commit: Remove Append Only Flag

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.java
index f59c5fd..f78c843 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IIndexOperatorDescriptor.java
@@ -25,33 +25,36 @@ import org.apache.hyracks.api.dataflow.value.RecordDescriptor;
 import org.apache.hyracks.dataflow.std.file.IFileSplitProvider;
 import org.apache.hyracks.storage.am.common.api.IIndexLifecycleManagerProvider;
 import org.apache.hyracks.storage.am.common.api.IModificationOperationCallbackFactory;
+import org.apache.hyracks.storage.am.common.api.IPageManagerFactory;
 import org.apache.hyracks.storage.am.common.api.ISearchOperationCallbackFactory;
 import org.apache.hyracks.storage.am.common.api.ITupleFilterFactory;
 import org.apache.hyracks.storage.common.IStorageManagerInterface;
 import org.apache.hyracks.storage.common.file.ILocalResourceFactoryProvider;
 
 public interface IIndexOperatorDescriptor extends IActivity {
-    public IFileSplitProvider getFileSplitProvider();
+    IFileSplitProvider getFileSplitProvider();
 
-    public IStorageManagerInterface getStorageManager();
+    IStorageManagerInterface getStorageManager();
 
-    public IIndexLifecycleManagerProvider getLifecycleManagerProvider();
+    IIndexLifecycleManagerProvider getLifecycleManagerProvider();
 
-    public RecordDescriptor getRecordDescriptor();
+    RecordDescriptor getRecordDescriptor();
 
-    public IIndexDataflowHelperFactory getIndexDataflowHelperFactory();
+    IIndexDataflowHelperFactory getIndexDataflowHelperFactory();
 
-    public boolean getRetainInput();
+    boolean getRetainInput();
 
-    public boolean getRetainMissing();
+    boolean getRetainMissing();
 
-    public IMissingWriterFactory getMissingWriterFactory();
+    IMissingWriterFactory getMissingWriterFactory();
 
-    public ISearchOperationCallbackFactory getSearchOpCallbackFactory();
+    ISearchOperationCallbackFactory getSearchOpCallbackFactory();
 
-    public IModificationOperationCallbackFactory getModificationOpCallbackFactory();
+    IModificationOperationCallbackFactory getModificationOpCallbackFactory();
 
-    public ITupleFilterFactory getTupleFilterFactory();
+    ITupleFilterFactory getTupleFilterFactory();
 
-    public ILocalResourceFactoryProvider getLocalResourceFactoryProvider();
+    ILocalResourceFactoryProvider getLocalResourceFactoryProvider();
+
+    IPageManagerFactory getPageManagerFactory();
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
index 76e4dec..5099df1 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexDataflowHelper.java
@@ -28,6 +28,7 @@ import org.apache.hyracks.api.io.FileSplit;
 import org.apache.hyracks.api.io.IIOManager;
 import org.apache.hyracks.storage.am.common.api.IIndex;
 import org.apache.hyracks.storage.am.common.api.IIndexDataflowHelper;
+import org.apache.hyracks.storage.am.common.api.IPageManagerFactory;
 import org.apache.hyracks.storage.am.common.api.IResourceLifecycleManager;
 import org.apache.hyracks.storage.am.common.frames.LIFOMetaDataFrame;
 import org.apache.hyracks.storage.common.file.ILocalResourceFactory;
@@ -43,6 +44,7 @@ public abstract class IndexDataflowHelper implements IIndexDataflowHelper {
     protected final IResourceLifecycleManager<IIndex> lcManager;
     protected final ILocalResourceRepository localResourceRepository;
     protected final IResourceIdFactory resourceIdFactory;
+    protected final IPageManagerFactory pageManagerFactory;
     protected final boolean durable;
     protected final FileReference resourceRef;
     protected final String resourceName;
@@ -60,6 +62,7 @@ public abstract class IndexDataflowHelper implements IIndexDataflowHelper {
         FileSplit fileSplit = opDesc.getFileSplitProvider().getFileSplits()[partition];
         this.resourceRef = fileSplit.getFileReference(ioManager);
         this.resourceName = resourceRef.getRelativePath();
+        this.pageManagerFactory = opDesc.getPageManagerFactory();
         this.durable = durable;
         this.partition = partition;
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexDropOperatorDescriptor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexDropOperatorDescriptor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexDropOperatorDescriptor.java
index d5a26ea..9d3be6f 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexDropOperatorDescriptor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/IndexDropOperatorDescriptor.java
@@ -29,6 +29,7 @@ import org.apache.hyracks.api.job.IOperatorDescriptorRegistry;
 import org.apache.hyracks.data.std.primitive.IntegerPointable;
 import org.apache.hyracks.dataflow.std.file.IFileSplitProvider;
 import org.apache.hyracks.storage.am.common.api.IIndexLifecycleManagerProvider;
+import org.apache.hyracks.storage.am.common.api.IPageManagerFactory;
 import org.apache.hyracks.storage.am.common.impls.NoOpOperationCallbackFactory;
 import org.apache.hyracks.storage.common.IStorageManagerInterface;
 import org.apache.hyracks.storage.common.file.NoOpLocalResourceFactoryProvider;
@@ -39,15 +40,16 @@ public class IndexDropOperatorDescriptor extends AbstractTreeIndexOperatorDescri
 
     public IndexDropOperatorDescriptor(IOperatorDescriptorRegistry spec, IStorageManagerInterface storageManager,
             IIndexLifecycleManagerProvider lifecycleManagerProvider, IFileSplitProvider fileSplitProvider,
-            IIndexDataflowHelperFactory dataflowHelperFactory) {
+            IIndexDataflowHelperFactory dataflowHelperFactory, IPageManagerFactory pageManagerFactory) {
         // TODO: providing the type traits below is a hack to allow:
         // 1) Type traits not to be specified when creating the drop operator
         // 2) The LSMRTreeDataflowHelper to get acceptable type traits
         // This should eventually not be *hacked*, but I don't know the proper fix yet. -zheilbron
         super(spec, 0, 0, null, storageManager, lifecycleManagerProvider, fileSplitProvider, new ITypeTraits[] {
-                IntegerPointable.TYPE_TRAITS, IntegerPointable.TYPE_TRAITS }, new IBinaryComparatorFactory[] { null }, null,
-                dataflowHelperFactory, null, false, false,
-                null, NoOpLocalResourceFactoryProvider.INSTANCE, NoOpOperationCallbackFactory.INSTANCE, NoOpOperationCallbackFactory.INSTANCE);
+                IntegerPointable.TYPE_TRAITS, IntegerPointable.TYPE_TRAITS },
+                new IBinaryComparatorFactory[] { null }, null, dataflowHelperFactory, null, false, false,
+                null, NoOpLocalResourceFactoryProvider.INSTANCE, NoOpOperationCallbackFactory.INSTANCE,
+                NoOpOperationCallbackFactory.INSTANCE, pageManagerFactory);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java
index 30c7197..cd26fb0 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexBulkLoadOperatorDescriptor.java
@@ -29,6 +29,7 @@ import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.job.IOperatorDescriptorRegistry;
 import org.apache.hyracks.dataflow.std.file.IFileSplitProvider;
 import org.apache.hyracks.storage.am.common.api.IIndexLifecycleManagerProvider;
+import org.apache.hyracks.storage.am.common.api.IPageManagerFactory;
 import org.apache.hyracks.storage.am.common.impls.NoOpOperationCallbackFactory;
 import org.apache.hyracks.storage.common.IStorageManagerInterface;
 import org.apache.hyracks.storage.common.file.NoOpLocalResourceFactoryProvider;
@@ -48,11 +49,11 @@ public class TreeIndexBulkLoadOperatorDescriptor extends AbstractTreeIndexOperat
             IFileSplitProvider fileSplitProvider, ITypeTraits[] typeTraits,
             IBinaryComparatorFactory[] comparatorFactories, int[] bloomFilterKeyFields, int[] fieldPermutation,
             float fillFactor, boolean verifyInput, long numElementsHint, boolean checkIfEmptyIndex,
-            IIndexDataflowHelperFactory dataflowHelperFactory) {
+            IIndexDataflowHelperFactory dataflowHelperFactory, IPageManagerFactory pageManagerFactory) {
         super(spec, 1, 1, recDesc, storageManager, lifecycleManagerProvider, fileSplitProvider, typeTraits,
                 comparatorFactories, bloomFilterKeyFields, dataflowHelperFactory, null, false, false, null,
                 NoOpLocalResourceFactoryProvider.INSTANCE, NoOpOperationCallbackFactory.INSTANCE,
-                NoOpOperationCallbackFactory.INSTANCE);
+                NoOpOperationCallbackFactory.INSTANCE, pageManagerFactory);
         this.fieldPermutation = fieldPermutation;
         this.fillFactor = fillFactor;
         this.verifyInput = verifyInput;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorDescriptor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorDescriptor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorDescriptor.java
index e491d1d..c225d37 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorDescriptor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexCreateOperatorDescriptor.java
@@ -29,6 +29,7 @@ import org.apache.hyracks.api.job.IOperatorDescriptorRegistry;
 import org.apache.hyracks.dataflow.std.file.IFileSplitProvider;
 import org.apache.hyracks.storage.am.common.api.IIndexLifecycleManagerProvider;
 import org.apache.hyracks.storage.am.common.api.IModificationOperationCallbackFactory;
+import org.apache.hyracks.storage.am.common.api.IPageManagerFactory;
 import org.apache.hyracks.storage.am.common.impls.NoOpOperationCallbackFactory;
 import org.apache.hyracks.storage.common.IStorageManagerInterface;
 import org.apache.hyracks.storage.common.file.ILocalResourceFactoryProvider;
@@ -42,10 +43,12 @@ public class TreeIndexCreateOperatorDescriptor extends AbstractTreeIndexOperator
             ITypeTraits[] typeTraits, IBinaryComparatorFactory[] comparatorFactories, int[] bloomFilterKeyFields,
             IIndexDataflowHelperFactory dataflowHelperFactory,
             ILocalResourceFactoryProvider localResourceFactoryProvider,
-            IModificationOperationCallbackFactory modificationOpCallbackFactory) {
+            IModificationOperationCallbackFactory modificationOpCallbackFactory,
+            IPageManagerFactory pageManagerFactory) {
         super(spec, 0, 0, null, storageManager, lifecycleManagerProvider, fileSplitProvider, typeTraits,
                 comparatorFactories, bloomFilterKeyFields, dataflowHelperFactory, null, false, false, null,
-                localResourceFactoryProvider, NoOpOperationCallbackFactory.INSTANCE, modificationOpCallbackFactory);
+                localResourceFactoryProvider, NoOpOperationCallbackFactory.INSTANCE, modificationOpCallbackFactory,
+                pageManagerFactory);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java
index 8589290..58b63a8 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexDiskOrderScanOperatorDescriptor.java
@@ -28,6 +28,7 @@ import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.job.IOperatorDescriptorRegistry;
 import org.apache.hyracks.dataflow.std.file.IFileSplitProvider;
 import org.apache.hyracks.storage.am.common.api.IIndexLifecycleManagerProvider;
+import org.apache.hyracks.storage.am.common.api.IPageManagerFactory;
 import org.apache.hyracks.storage.am.common.api.ISearchOperationCallbackFactory;
 import org.apache.hyracks.storage.am.common.impls.NoOpOperationCallbackFactory;
 import org.apache.hyracks.storage.common.IStorageManagerInterface;
@@ -40,10 +41,12 @@ public class TreeIndexDiskOrderScanOperatorDescriptor extends AbstractTreeIndexO
     public TreeIndexDiskOrderScanOperatorDescriptor(IOperatorDescriptorRegistry spec, RecordDescriptor recDesc,
             IStorageManagerInterface storageManager, IIndexLifecycleManagerProvider lifecycleManagerProvider,
             IFileSplitProvider fileSplitProvider, ITypeTraits[] typeTraits,
-            IIndexDataflowHelperFactory dataflowHelperFactory, ISearchOperationCallbackFactory searchOpCallbackProvider) {
+            IIndexDataflowHelperFactory dataflowHelperFactory,
+            ISearchOperationCallbackFactory searchOpCallbackProvider, IPageManagerFactory pageManagerFactory) {
         super(spec, 0, 1, recDesc, storageManager, lifecycleManagerProvider, fileSplitProvider, typeTraits, null, null,
-                dataflowHelperFactory, null, false, false,
-                null, NoOpLocalResourceFactoryProvider.INSTANCE, searchOpCallbackProvider, NoOpOperationCallbackFactory.INSTANCE);
+                dataflowHelperFactory, null, false, false, null,
+                NoOpLocalResourceFactoryProvider.INSTANCE, searchOpCallbackProvider,
+                NoOpOperationCallbackFactory.INSTANCE, pageManagerFactory);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java
index 6b55b5e..9e1b172 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexInsertUpdateDeleteOperatorDescriptor.java
@@ -30,6 +30,7 @@ import org.apache.hyracks.api.job.IOperatorDescriptorRegistry;
 import org.apache.hyracks.dataflow.std.file.IFileSplitProvider;
 import org.apache.hyracks.storage.am.common.api.IIndexLifecycleManagerProvider;
 import org.apache.hyracks.storage.am.common.api.IModificationOperationCallbackFactory;
+import org.apache.hyracks.storage.am.common.api.IPageManagerFactory;
 import org.apache.hyracks.storage.am.common.api.ITupleFilterFactory;
 import org.apache.hyracks.storage.am.common.impls.NoOpOperationCallbackFactory;
 import org.apache.hyracks.storage.am.common.ophelpers.IndexOperation;
@@ -48,11 +49,13 @@ public class TreeIndexInsertUpdateDeleteOperatorDescriptor extends AbstractTreeI
             IFileSplitProvider fileSplitProvider, ITypeTraits[] typeTraits,
             IBinaryComparatorFactory[] comparatorFactories, int[] bloomFilterKeyFields, int[] fieldPermutation,
             IndexOperation op, IIndexDataflowHelperFactory dataflowHelperFactory,
-            ITupleFilterFactory tupleFilterFactory, IModificationOperationCallbackFactory modificationOpCallbackProvider) {
+            ITupleFilterFactory tupleFilterFactory,
+            IModificationOperationCallbackFactory modificationOpCallbackProvider,
+            IPageManagerFactory pageManagerFactory) {
         super(spec, 1, 1, recDesc, storageManager, lifecycleManagerProvider, fileSplitProvider, typeTraits,
                 comparatorFactories, bloomFilterKeyFields, dataflowHelperFactory, tupleFilterFactory, false,
-                false, null,
-                NoOpLocalResourceFactoryProvider.INSTANCE, NoOpOperationCallbackFactory.INSTANCE, modificationOpCallbackProvider);
+                false, null, NoOpLocalResourceFactoryProvider.INSTANCE, NoOpOperationCallbackFactory.INSTANCE,
+                modificationOpCallbackProvider, pageManagerFactory);
         this.fieldPermutation = fieldPermutation;
         this.op = op;
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java
index 06371d2..ecedc21 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorDescriptor.java
@@ -30,6 +30,7 @@ import org.apache.hyracks.api.job.IOperatorDescriptorRegistry;
 import org.apache.hyracks.dataflow.common.data.marshalling.UTF8StringSerializerDeserializer;
 import org.apache.hyracks.dataflow.std.file.IFileSplitProvider;
 import org.apache.hyracks.storage.am.common.api.IIndexLifecycleManagerProvider;
+import org.apache.hyracks.storage.am.common.api.IPageManagerFactory;
 import org.apache.hyracks.storage.am.common.api.ISearchOperationCallbackFactory;
 import org.apache.hyracks.storage.am.common.impls.NoOpOperationCallbackFactory;
 import org.apache.hyracks.storage.common.IStorageManagerInterface;
@@ -44,11 +45,13 @@ public class TreeIndexStatsOperatorDescriptor extends AbstractTreeIndexOperatorD
     public TreeIndexStatsOperatorDescriptor(IOperatorDescriptorRegistry spec, IStorageManagerInterface storageManager,
             IIndexLifecycleManagerProvider lifecycleManagerProvider, IFileSplitProvider fileSplitProvider,
             ITypeTraits[] typeTraits, IBinaryComparatorFactory[] comparatorFactories, int[] bloomFilterKeyFields,
-            IIndexDataflowHelperFactory dataflowHelperFactory, ISearchOperationCallbackFactory searchOpCallbackProvider) {
+            IIndexDataflowHelperFactory dataflowHelperFactory,
+            ISearchOperationCallbackFactory searchOpCallbackProvider,
+            IPageManagerFactory pageManagerFactory) {
         super(spec, 0, 1, recDesc, storageManager, lifecycleManagerProvider, fileSplitProvider, typeTraits,
-                comparatorFactories, bloomFilterKeyFields, dataflowHelperFactory, null, false,
-                false, null,
-                NoOpLocalResourceFactoryProvider.INSTANCE, searchOpCallbackProvider, NoOpOperationCallbackFactory.INSTANCE);
+                comparatorFactories, bloomFilterKeyFields, dataflowHelperFactory, null, false, false, null,
+                NoOpLocalResourceFactoryProvider.INSTANCE, searchOpCallbackProvider,
+                NoOpOperationCallbackFactory.INSTANCE, pageManagerFactory);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java
index a501efb..91d433c 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/dataflow/TreeIndexStatsOperatorNodePushable.java
@@ -74,11 +74,10 @@ public class TreeIndexStatsOperatorNodePushable extends AbstractUnaryOutputSourc
             IIOManager ioManager = ctx.getIOManager();
             FileReference fileRef = ioManager.resolve(resource.getPath());
             int indexFileId = fileMapProvider.lookupFileId(fileRef);
-            statsGatherer = new TreeIndexStatsGatherer(bufferCache, treeIndex.getMetaManager(), indexFileId,
+            statsGatherer = new TreeIndexStatsGatherer(bufferCache, treeIndex.getPageManager(), indexFileId,
                     treeIndex.getRootPageId());
             TreeIndexStats stats = statsGatherer.gatherStats(treeIndex.getLeafFrameFactory().createFrame(), treeIndex
-                    .getInteriorFrameFactory().createFrame(), treeIndex.getMetaManager().getMetaDataFrameFactory()
-                    .createFrame());
+                    .getInteriorFrameFactory().createFrame(), treeIndex.getPageManager().createMetadataFrame());
             // Write the stats output as a single string field.
             FrameTupleAppender appender = new FrameTupleAppender(new VSizeFrame(ctx));
             ArrayTupleBuilder tb = new ArrayTupleBuilder(1);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java
index 5489dcc..7d33519 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/LIFOMetaDataFrame.java
@@ -31,6 +31,9 @@ import org.apache.hyracks.storage.common.buffercache.ICachedPage;
 
 public class LIFOMetaDataFrame implements ITreeIndexMetaDataFrame {
 
+    private static final byte META_PAGE_LEVEL_INDICATOR = -1;
+    private static final byte FREE_PAGE_LEVEL_INDICATOR = -2;
+
     // Arbitrarily chosen magic integer.
     protected static final int OBSOLETE_MAGIC_VALID_INT = 0x5bd1e995;
     protected static final int MAGIC_VALID_INT = 0x1B16DA7A;
@@ -119,21 +122,21 @@ public class LIFOMetaDataFrame implements ITreeIndexMetaDataFrame {
     }
 
     @Override
-    public void initBuffer(byte level) {
+    public void initBuffer() {
         buf.putInt(TUPLE_COUNT_OFFSET, 0);
         buf.putInt(FREE_SPACE_OFFSET, HEADER_END_OFFSET);
         buf.putInt(MAX_PAGE_OFFSET, 0);
-        buf.put(LEVEL_OFFSET, level);
+        buf.put(LEVEL_OFFSET, META_PAGE_LEVEL_INDICATOR);
         buf.putInt(NEXT_PAGE_OFFSET, -1);
         buf.putInt(ADDITIONAL_FILTERING_PAGE_OFFSET, -1);
         buf.putLong(LAST_MARKER_LSN_OFFSET, -1L);
-        buf.putInt(ROOT_PAGE_NUMBER, 0);
+        buf.putInt(ROOT_PAGE_NUMBER, 1);
         buf.putInt(STORAGE_VERSION_OFFSET, VERSION);
         setValid(false);
     }
 
     @Override
-    public int getNextPage() {
+    public int getNextMetadataPage() {
         return buf.getInt(NEXT_PAGE_OFFSET);
     }
 
@@ -204,4 +207,14 @@ public class LIFOMetaDataFrame implements ITreeIndexMetaDataFrame {
     public int getRootPageNumber() {
         return buf.getInt(ROOT_PAGE_NUMBER);
     }
+
+    @Override
+    public boolean isMetadataPage() {
+        return getLevel() == META_PAGE_LEVEL_INDICATOR;
+    }
+
+    @Override
+    public boolean isFreePage() {
+        return getLevel() == FREE_PAGE_LEVEL_INDICATOR;
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java
index d2cec23..b0406c2 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/LIFOMetaDataFrameFactory.java
@@ -16,7 +16,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 package org.apache.hyracks.storage.am.common.frames;
 
 import org.apache.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java
index 72c6fe2..47530a8 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/frames/TreeIndexNSMFrame.java
@@ -149,7 +149,7 @@ public abstract class TreeIndexNSMFrame implements ITreeIndexFrame {
         int tupleCount = buf.getInt(tupleCountOff);
         int freeSpace = buf.getInt(freeSpaceOff);
         // Sort the slots by the tuple offset they point to.
-        ArrayList<SlotOffTupleOff> sortedTupleOffs = new ArrayList<SlotOffTupleOff>();
+        ArrayList<SlotOffTupleOff> sortedTupleOffs = new ArrayList<>();
         sortedTupleOffs.ensureCapacity(tupleCount);
         for (int i = 0; i < tupleCount; i++) {
             int slotOff = slotManager.getSlotOff(i);
@@ -287,6 +287,7 @@ public abstract class TreeIndexNSMFrame implements ITreeIndexFrame {
         return buf.getInt(tupleCountOff);
     }
 
+    @Override
     public ISlotManager getSlotManager() {
         return slotManager;
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/AppendOnlyLinkedMetadataPageManager.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/AppendOnlyLinkedMetadataPageManager.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/AppendOnlyLinkedMetadataPageManager.java
new file mode 100644
index 0000000..4126c19
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/AppendOnlyLinkedMetadataPageManager.java
@@ -0,0 +1,417 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 at
+ *
+ *   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 org.apache.hyracks.storage.am.common.freepage;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.storage.am.common.api.IMetadataPageManager;
+import org.apache.hyracks.storage.am.common.api.ITreeIndexFrame;
+import org.apache.hyracks.storage.am.common.api.ITreeIndexFrameFactory;
+import org.apache.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
+import org.apache.hyracks.storage.am.common.api.ITreeIndexMetaDataFrameFactory;
+import org.apache.hyracks.storage.am.common.frames.LIFOMetaDataFrame;
+import org.apache.hyracks.storage.am.common.impls.AbstractTreeIndex;
+import org.apache.hyracks.storage.common.buffercache.BufferCache;
+import org.apache.hyracks.storage.common.buffercache.IBufferCache;
+import org.apache.hyracks.storage.common.buffercache.ICachedPage;
+import org.apache.hyracks.storage.common.buffercache.IFIFOPageQueue;
+import org.apache.hyracks.storage.common.file.BufferedFileHandle;
+
+public class AppendOnlyLinkedMetadataPageManager implements IMetadataPageManager {
+    private final IBufferCache bufferCache;
+    private int metadataPage = IBufferCache.INVALID_PAGEID;
+    private int fileId = -1;
+    private final ITreeIndexMetaDataFrameFactory frameFactory;
+    ICachedPage confiscatedPage;
+    ICachedPage filterPage;
+    boolean ready = false;
+
+    public AppendOnlyLinkedMetadataPageManager(IBufferCache bufferCache, ITreeIndexMetaDataFrameFactory frameFactory) {
+        this.bufferCache = bufferCache;
+        this.frameFactory = frameFactory;
+    }
+
+    @Override
+    public void releasePage(ITreeIndexMetaDataFrame metaFrame, int freePageNum) throws HyracksDataException {
+        ICachedPage metaPage = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        metaPage.acquireWriteLatch();
+        try {
+            metaFrame.setPage(metaPage);
+            if (metaFrame.hasSpace()) {
+                metaFrame.addFreePage(freePageNum);
+            } else {
+                int newPageNum = metaFrame.getFreePage();
+                if (newPageNum < 0) {
+                    throw new HyracksDataException(
+                            "Inconsistent Meta Page State. It has no space, but it also has no entries.");
+                }
+                ICachedPage newNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, newPageNum), false);
+                newNode.acquireWriteLatch();
+                try {
+                    int metaMaxPage = metaFrame.getMaxPage();
+                    System.arraycopy(metaPage.getBuffer().array(), 0, newNode.getBuffer().array(), 0,
+                            metaPage.getBuffer().capacity());
+                    metaFrame.initBuffer();
+                    metaFrame.setNextPage(newPageNum);
+                    metaFrame.setMaxPage(metaMaxPage);
+                    metaFrame.addFreePage(freePageNum);
+                } finally {
+                    newNode.releaseWriteLatch(true);
+                    bufferCache.unpin(newNode);
+                }
+            }
+        } finally {
+            metaPage.releaseWriteLatch(true);
+            bufferCache.unpin(metaPage);
+        }
+    }
+
+    @Override
+    public void releaseBlock(ITreeIndexMetaDataFrame metaFrame, int startingPage, int count)
+            throws HyracksDataException {
+        for (int i = 0; i < count; i++) {
+            releasePage(metaFrame, startingPage + i);
+        }
+    }
+
+    @Override
+    public int takePage(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
+        confiscatedPage.acquireWriteLatch();
+        int freePage = IBufferCache.INVALID_PAGEID;
+        try {
+            metaFrame.setPage(confiscatedPage);
+            freePage = metaFrame.getFreePage();
+            if (freePage < 0) { // no free page entry on this page
+                int nextPage = metaFrame.getNextMetadataPage();
+                if (nextPage > 0) { // sibling may have free pages
+                    ICachedPage nextNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, nextPage), false);
+                    nextNode.acquireWriteLatch();
+                    // we copy over the free space entries of nextpage into the
+                    // first meta page (metaDataPage)
+                    // we need to link the first page properly to the next page
+                    // of nextpage
+                    try {
+                        // remember entries that remain unchanged
+                        int maxPage = metaFrame.getMaxPage();
+                        // copy entire page (including sibling pointer, free
+                        // page entries, and all other info)
+                        // after this copy nextPage is considered a free page
+                        System.arraycopy(nextNode.getBuffer().array(), 0, confiscatedPage.getBuffer().array(), 0,
+                                nextNode.getBuffer().capacity());
+                        // reset unchanged entry
+                        metaFrame.setMaxPage(maxPage);
+                        freePage = metaFrame.getFreePage();
+                        // sibling also has no free pages, this "should" not
+                        // happen, but we deal with it anyway just to be safe
+                        if (freePage < 0) {
+                            freePage = nextPage;
+                        } else {
+                            metaFrame.addFreePage(nextPage);
+                        }
+                    } finally {
+                        nextNode.releaseWriteLatch(true);
+                        bufferCache.unpin(nextNode);
+                    }
+                } else {
+                    freePage = metaFrame.getMaxPage();
+                    freePage++;
+                    metaFrame.setMaxPage(freePage);
+                }
+            }
+        } finally {
+            confiscatedPage.releaseWriteLatch(false);
+        }
+        return freePage;
+    }
+
+    @Override
+    public int takeBlock(ITreeIndexMetaDataFrame metaFrame, int count) throws HyracksDataException {
+        int maxPage = metaFrame.getMaxPage();
+        metaFrame.setMaxPage(maxPage + count);
+        return maxPage + 1;
+    }
+
+    @Override
+    public int getMaxPageId(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
+        ICachedPage metaNode;
+        if (confiscatedPage == null) {
+            int mdPage = getMetadataPageId();
+            if (mdPage < 0) {
+                return IBufferCache.INVALID_PAGEID;
+            }
+            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, mdPage), false);
+        } else {
+            metaNode = confiscatedPage;
+        }
+        metaNode.acquireReadLatch();
+        int maxPage = -1;
+        try {
+            metaFrame.setPage(metaNode);
+            maxPage = metaFrame.getMaxPage();
+        } finally {
+            metaNode.releaseReadLatch();
+            if (confiscatedPage == null) {
+                bufferCache.unpin(metaNode);
+            }
+        }
+        return maxPage;
+    }
+
+    @Override
+    public void setFilterPageId(int filterPageId) throws HyracksDataException {
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+        confiscatedPage.acquireWriteLatch();
+        try {
+            metaFrame.setPage(confiscatedPage);
+            metaFrame.setLSMComponentFilterPageId(filterPageId);
+        } finally {
+            confiscatedPage.releaseWriteLatch(false);
+        }
+    }
+
+    @Override
+    public int getFilterPageId() throws HyracksDataException {
+        ICachedPage metaNode = (confiscatedPage == null) ? bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId,
+                getMetadataPageId()), false) : confiscatedPage;
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+        metaNode.acquireReadLatch();
+        try {
+            metaFrame.setPage(metaNode);
+            return metaFrame.getLSMComponentFilterPageId();
+        } finally {
+            metaNode.releaseReadLatch();
+            if (confiscatedPage == null) {
+                bufferCache.unpin(metaNode);
+            }
+        }
+    }
+
+    @Override
+    public void init(ITreeIndexFrameFactory interiorFrameFactory, ITreeIndexFrameFactory leafFrameFactory)
+            throws HyracksDataException {
+        // an initialized append only tree is always completely empty with size = 0, hence, this operation is a No Op
+    }
+
+    @Override
+    public ITreeIndexMetaDataFrame createMetadataFrame() {
+        return frameFactory.createFrame();
+    }
+
+    @Override
+    public void open(int fileId) throws HyracksDataException {
+        this.fileId = fileId;
+        // get the number of pages of the file
+        int pages = bufferCache.getNumPagesOfFile(fileId);
+        //if there are no pages in the file yet, we're just initializing
+        if (pages == 0) {
+            if (confiscatedPage != null) {
+                throw new HyracksDataException("Metadata Page Manager is already initialized");
+            }
+            ITreeIndexMetaDataFrame metaFrame = createMetadataFrame();
+            ICachedPage metaNode = bufferCache.confiscatePage(BufferCache.INVALID_DPID);
+            try {
+                metaFrame.setPage(metaNode);
+                metaFrame.initBuffer();
+                metaFrame.setMaxPage(-1);
+            } finally {
+                confiscatedPage = metaNode;
+            }
+        }
+    }
+
+    @Override
+    public void close() throws HyracksDataException {
+        if (ready) {
+            IFIFOPageQueue queue = bufferCache.createFIFOQueue();
+            writeFilterPage(queue);
+            ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+            confiscatedPage.acquireWriteLatch();
+            try {
+                metaFrame.setPage(confiscatedPage);
+                metaFrame.setValid(true);
+            } finally {
+                confiscatedPage.releaseWriteLatch(false);
+            }
+            int finalMetaPage = getMaxPageId(metaFrame) + 1;
+            bufferCache.setPageDiskId(confiscatedPage, BufferedFileHandle.getDiskPageId(fileId, finalMetaPage));
+            queue.put(confiscatedPage);
+            bufferCache.finishQueue();
+            metadataPage = getMetadataPageId();
+            ready = false;
+        } else if (confiscatedPage != null) {
+            bufferCache.returnPage(confiscatedPage, false);
+        }
+        confiscatedPage = null;
+    }
+
+    private void writeFilterPage(IFIFOPageQueue queue) throws HyracksDataException {
+        if (filterPage != null) {
+            ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+            metaFrame.setPage(confiscatedPage);
+            int finalFilterPage = takePage(metaFrame);
+            setFilterPageId(finalFilterPage);
+            bufferCache.setPageDiskId(filterPage, BufferedFileHandle.getDiskPageId(fileId, finalFilterPage));
+            queue.put(filterPage);
+        }
+    }
+
+    /**
+     * For storage on append-only media (such as HDFS), the meta data page has to be written last.
+     * However, some implementations still write the meta data to the front. To deal with this as well
+     * as to provide downward compatibility, this method tries to find the meta data page first in the
+     * last and then in the first page of the file.
+     *
+     * @return The Id of the page holding the meta data
+     * @throws HyracksDataException
+     */
+    @Override
+    public int getMetadataPageId() throws HyracksDataException {
+        // if found already, just return it
+        if (metadataPage != IBufferCache.INVALID_PAGEID) {
+            return metadataPage;
+        }
+        // get the number of pages of the file
+        int pages = bufferCache.getNumPagesOfFile(fileId);
+        //if there are no pages in the file yet, we're just initializing
+        if (pages == 0) {
+            return 0;
+        }
+        metadataPage = pages - 1;
+        return metadataPage;
+    }
+
+    @Override
+    public long getLSN() throws HyracksDataException {
+        ICachedPage metaNode;
+        if (confiscatedPage == null) {
+            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        } else {
+            metaNode = confiscatedPage;
+        }
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+        metaNode.acquireReadLatch();
+        try {
+            metaFrame.setPage(metaNode);
+            return metaFrame.getLSN();
+        } finally {
+            metaNode.releaseReadLatch();
+            if (confiscatedPage == null) {
+                bufferCache.unpin(metaNode);
+            }
+        }
+    }
+
+    @Override
+    public void setLSN(long lsn) throws HyracksDataException {
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+        confiscatedPage.acquireWriteLatch();
+        try {
+            metaFrame.setPage(confiscatedPage);
+            metaFrame.setLSN(lsn);
+        } finally {
+            confiscatedPage.releaseWriteLatch(false);
+        }
+    }
+
+    @Override
+    public void setFilterPage(ICachedPage filterPage) {
+        filterPage.releaseWriteLatch(false);
+        this.filterPage = filterPage;
+    }
+
+    @Override
+    public ICachedPage getFilterPage() throws HyracksDataException {
+        filterPage = bufferCache.confiscatePage(IBufferCache.INVALID_DPID);
+        filterPage.acquireWriteLatch();
+        return filterPage;
+    }
+
+    @Override
+    public boolean isEmpty(ITreeIndexFrame frame, int rootPage) throws HyracksDataException {
+        return bufferCache.getNumPagesOfFile(fileId) <= AbstractTreeIndex.MINIMAL_TREE_PAGE_COUNT;
+    }
+
+    @Override
+    public long getLSNOffset() throws HyracksDataException {
+        int metadataPageNum = getMetadataPageId();
+        if (metadataPageNum != IBufferCache.INVALID_PAGEID) {
+            return ((long) metadataPageNum * bufferCache.getPageSizeWithHeader()) + LIFOMetaDataFrame.LSN_OFFSET;
+        }
+        return IMetadataPageManager.Constants.INVALID_LSN_OFFSET;
+    }
+
+    @Override
+    public long getLastMarkerLSN() throws HyracksDataException {
+        ICachedPage metaNode;
+        if (confiscatedPage == null) {
+            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        } else {
+            metaNode = confiscatedPage;
+        }
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+        metaNode.acquireReadLatch();
+        try {
+            metaFrame.setPage(metaNode);
+            return metaFrame.getLastMarkerLSN();
+        } finally {
+            metaNode.releaseReadLatch();
+            if (confiscatedPage == null) {
+                bufferCache.unpin(metaNode);
+            }
+        }
+    }
+
+    @Override
+    public void setRootPageId(int rootPage) throws HyracksDataException {
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+        confiscatedPage.acquireWriteLatch();
+        try {
+            metaFrame.setPage(confiscatedPage);
+            metaFrame.setRootPageNumber(rootPage);
+        } finally {
+            confiscatedPage.releaseWriteLatch(false);
+        }
+        ready = true;
+    }
+
+    @Override
+    public int getRootPageId() throws HyracksDataException {
+        ICachedPage metaNode;
+        if (confiscatedPage == null) {
+            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        } else {
+            metaNode = confiscatedPage;
+        }
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+        metaNode.acquireReadLatch();
+        try {
+            metaFrame.setPage(metaNode);
+            return metaFrame.getRootPageNumber();
+        } finally {
+            metaNode.releaseReadLatch();
+            if (confiscatedPage == null) {
+                bufferCache.unpin(metaNode);
+            }
+        }
+    }
+
+    @Override
+    public int getBulkLoadLeaf() throws HyracksDataException {
+        return 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/AppendOnlyLinkedMetadataPageManagerFactory.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/AppendOnlyLinkedMetadataPageManagerFactory.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/AppendOnlyLinkedMetadataPageManagerFactory.java
new file mode 100644
index 0000000..fea128d
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/AppendOnlyLinkedMetadataPageManagerFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 at
+ *
+ *   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 org.apache.hyracks.storage.am.common.freepage;
+
+import org.apache.hyracks.storage.am.common.api.IMetadataPageManager;
+import org.apache.hyracks.storage.am.common.api.IMetadataPageManagerFactory;
+import org.apache.hyracks.storage.am.common.frames.LIFOMetaDataFrameFactory;
+import org.apache.hyracks.storage.common.buffercache.IBufferCache;
+
+public class AppendOnlyLinkedMetadataPageManagerFactory implements IMetadataPageManagerFactory {
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public IMetadataPageManager createPageManager(IBufferCache bufferCache) {
+        return new AppendOnlyLinkedMetadataPageManager(bufferCache, new LIFOMetaDataFrameFactory());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedListMetadataManagerFactory.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedListMetadataManagerFactory.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedListMetadataManagerFactory.java
deleted file mode 100644
index a911413..0000000
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedListMetadataManagerFactory.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 at
- *
- *   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 org.apache.hyracks.storage.am.common.freepage;
-
-import org.apache.hyracks.api.exceptions.HyracksDataException;
-import org.apache.hyracks.storage.am.common.api.IMetaDataPageManager;
-import org.apache.hyracks.storage.am.common.api.IMetadataManagerFactory;
-import org.apache.hyracks.storage.am.common.api.ITreeIndexMetaDataFrameFactory;
-import org.apache.hyracks.storage.common.buffercache.IBufferCache;
-
-public class LinkedListMetadataManagerFactory implements IMetadataManagerFactory {
-
-    private final ITreeIndexMetaDataFrameFactory metaDataFrameFactory;
-    private final IBufferCache bufferCache;
-
-    public LinkedListMetadataManagerFactory(IBufferCache bufferCache,
-                                            ITreeIndexMetaDataFrameFactory metaDataFrameFactory) {
-        this.metaDataFrameFactory = metaDataFrameFactory;
-        this.bufferCache = bufferCache;
-    }
-
-    public IMetaDataPageManager createFreePageManager() throws HyracksDataException {
-        return new LinkedMetaDataPageManager(bufferCache, metaDataFrameFactory);
-    }
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetaDataPageManager.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetaDataPageManager.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetaDataPageManager.java
index 2b0566d..6cedb4d 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetaDataPageManager.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetaDataPageManager.java
@@ -19,94 +19,81 @@
 package org.apache.hyracks.storage.am.common.freepage;
 
 import org.apache.hyracks.api.exceptions.HyracksDataException;
-import org.apache.hyracks.storage.am.common.api.IMetaDataPageManager;
+import org.apache.hyracks.storage.am.common.api.IMetadataPageManager;
+import org.apache.hyracks.storage.am.common.api.ITreeIndexFrame;
+import org.apache.hyracks.storage.am.common.api.ITreeIndexFrameFactory;
 import org.apache.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
 import org.apache.hyracks.storage.am.common.api.ITreeIndexMetaDataFrameFactory;
 import org.apache.hyracks.storage.am.common.frames.LIFOMetaDataFrame;
-import org.apache.hyracks.storage.common.buffercache.BufferCache;
 import org.apache.hyracks.storage.common.buffercache.IBufferCache;
 import org.apache.hyracks.storage.common.buffercache.ICachedPage;
-import org.apache.hyracks.storage.common.buffercache.IFIFOPageQueue;
 import org.apache.hyracks.storage.common.file.BufferedFileHandle;
 
-public class LinkedMetaDataPageManager implements IMetaDataPageManager {
-
-    private static final byte META_PAGE_LEVEL_INDICATOR = -1;
-    private static final byte FREE_PAGE_LEVEL_INDICATOR = -2;
-    public static final int NO_FILTER_IN_PLACE = -1;
-    public static final int NO_FILTER_APPEND_ONLY = -2;
+public class LinkedMetaDataPageManager implements IMetadataPageManager {
     private final IBufferCache bufferCache;
-    private int headPage = IBufferCache.INVALID_PAGEID;
     private int fileId = -1;
-    private final ITreeIndexMetaDataFrameFactory metaDataFrameFactory;
-    private boolean appendOnly = false;
-    ICachedPage confiscatedMetaNode;
-    ICachedPage filterPage;
+    private final ITreeIndexMetaDataFrameFactory frameFactory;
+    private boolean ready = false;
 
-    public LinkedMetaDataPageManager(IBufferCache bufferCache, ITreeIndexMetaDataFrameFactory metaDataFrameFactory) {
+    public LinkedMetaDataPageManager(IBufferCache bufferCache, ITreeIndexMetaDataFrameFactory frameFactory) {
         this.bufferCache = bufferCache;
-        this.metaDataFrameFactory = metaDataFrameFactory;
+        this.frameFactory = frameFactory;
     }
 
     @Override
-    public void addFreePage(ITreeIndexMetaDataFrame metaFrame, int freePage) throws HyracksDataException {
-        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), false);
-        metaNode.acquireWriteLatch();
-
+    public void releasePage(ITreeIndexMetaDataFrame metaFrame, int freePageNum) throws HyracksDataException {
+        // Get the metadata node
+        ICachedPage metaPage = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        metaPage.acquireWriteLatch();
         try {
-            metaFrame.setPage(metaNode);
+            metaFrame.setPage(metaPage);
 
             if (metaFrame.hasSpace()) {
-                metaFrame.addFreePage(freePage);
+                metaFrame.addFreePage(freePageNum);
             } else {
                 // allocate a new page in the chain of meta pages
-                int newPage = metaFrame.getFreePage();
-                if (newPage < 0) {
+                int newPageNum = metaFrame.getFreePage();
+                if (newPageNum < 0) {
                     throw new HyracksDataException(
                             "Inconsistent Meta Page State. It has no space, but it also has no entries.");
                 }
 
-                ICachedPage newNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, newPage), false);
+                ICachedPage newNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, newPageNum), false);
                 newNode.acquireWriteLatch();
 
                 try {
                     int metaMaxPage = metaFrame.getMaxPage();
 
                     // copy metaDataPage to newNode
-                    System.arraycopy(metaNode.getBuffer().array(), 0, newNode.getBuffer().array(), 0,
-                            metaNode.getBuffer().capacity());
+                    System.arraycopy(metaPage.getBuffer().array(), 0, newNode.getBuffer().array(), 0,
+                            metaPage.getBuffer().capacity());
 
-                    metaFrame.initBuffer(META_PAGE_LEVEL_INDICATOR);
-                    metaFrame.setNextPage(newPage);
+                    metaFrame.initBuffer();
+                    metaFrame.setNextPage(newPageNum);
                     metaFrame.setMaxPage(metaMaxPage);
-                    metaFrame.addFreePage(freePage);
+                    metaFrame.addFreePage(freePageNum);
                 } finally {
                     newNode.releaseWriteLatch(true);
                     bufferCache.unpin(newNode);
                 }
             }
         } finally {
-            metaNode.releaseWriteLatch(true);
-            bufferCache.unpin(metaNode);
+            metaPage.releaseWriteLatch(true);
+            bufferCache.unpin(metaPage);
         }
     }
 
     @Override
-    public void addFreePageBlock(ITreeIndexMetaDataFrame metaFrame, int startingPage, int count)
+    public void releaseBlock(ITreeIndexMetaDataFrame metaFrame, int startingPage, int count)
             throws HyracksDataException {
         for (int i = 0; i < count; i++) {
-            addFreePage(metaFrame, startingPage + i);
+            releasePage(metaFrame, startingPage + i);
         }
     }
 
     @Override
-    public int getFreePage(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
-        ICachedPage metaNode;
-        if (!appendOnly) {
-            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), false);
-        } else {
-            metaNode = confiscatedMetaNode;
-        }
+    public int takePage(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
+        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
 
         metaNode.acquireWriteLatch();
 
@@ -115,7 +102,7 @@ public class LinkedMetaDataPageManager implements IMetaDataPageManager {
             metaFrame.setPage(metaNode);
             freePage = metaFrame.getFreePage();
             if (freePage < 0) { // no free page entry on this page
-                int nextPage = metaFrame.getNextPage();
+                int nextPage = metaFrame.getNextMetadataPage();
                 if (nextPage > 0) { // sibling may have free pages
                     ICachedPage nextNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, nextPage), false);
 
@@ -156,36 +143,29 @@ public class LinkedMetaDataPageManager implements IMetaDataPageManager {
                 }
             }
         } finally {
-            if (!appendOnly) {
-                metaNode.releaseWriteLatch(true);
-                bufferCache.unpin(metaNode);
-            } else {
-                metaNode.releaseWriteLatch(false);
-            }
+            metaNode.releaseWriteLatch(true);
+            bufferCache.unpin(metaNode);
         }
 
         return freePage;
     }
 
     @Override
-    public int getFreePageBlock(ITreeIndexMetaDataFrame metaFrame, int count) throws HyracksDataException {
+    public int takeBlock(ITreeIndexMetaDataFrame metaFrame, int count) throws HyracksDataException {
         int maxPage = metaFrame.getMaxPage();
         metaFrame.setMaxPage(maxPage + count);
         return maxPage + 1;
     }
 
     @Override
-    public int getMaxPage(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
+    public int getMaxPageId(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
         ICachedPage metaNode;
-        if (!appendOnly || confiscatedMetaNode == null) {
-            int mdPage = getFirstMetadataPage();
-            if (mdPage < 0) {
-                return IBufferCache.INVALID_PAGEID;
-            }
-            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, mdPage), false);
-        } else {
-            metaNode = confiscatedMetaNode;
+        int mdPage = getMetadataPageId();
+        if (mdPage < 0) {
+            return IBufferCache.INVALID_PAGEID;
         }
+        metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, mdPage), false);
+
         metaNode.acquireReadLatch();
         int maxPage = -1;
         try {
@@ -193,9 +173,7 @@ public class LinkedMetaDataPageManager implements IMetaDataPageManager {
             maxPage = metaFrame.getMaxPage();
         } finally {
             metaNode.releaseReadLatch();
-            if (!appendOnly || confiscatedMetaNode == null) {
-                bufferCache.unpin(metaNode);
-            }
+            bufferCache.unpin(metaNode);
         }
         return maxPage;
     }
@@ -203,116 +181,74 @@ public class LinkedMetaDataPageManager implements IMetaDataPageManager {
     @Override
     public void setFilterPageId(int filterPageId) throws HyracksDataException {
         ICachedPage metaNode;
-        if (!appendOnly) {
-            int mdPage = getFirstMetadataPage();
-            if (mdPage < 0) {
-                return;
-            }
-            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, mdPage), false);
-        } else {
-            metaNode = confiscatedMetaNode;
+        int mdPage = getMetadataPageId();
+        if (mdPage < 0) {
+            return;
         }
-        ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
+        metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, mdPage), false);
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
         metaNode.acquireWriteLatch();
         try {
             metaFrame.setPage(metaNode);
             metaFrame.setLSMComponentFilterPageId(filterPageId);
         } finally {
-            if (!appendOnly) {
-                metaNode.releaseWriteLatch(true);
-                bufferCache.unpin(metaNode);
-            } else {
-                metaNode.releaseWriteLatch(false);
-            }
+            metaNode.releaseWriteLatch(true);
+            bufferCache.unpin(metaNode);
         }
     }
 
     @Override
     public int getFilterPageId() throws HyracksDataException {
-        ICachedPage metaNode;
-        int filterPageId = NO_FILTER_IN_PLACE;
-        if (!appendOnly || confiscatedMetaNode == null) {
-            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), false);
-        } else {
-            metaNode = confiscatedMetaNode;
-        }
-        ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
+        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
         metaNode.acquireReadLatch();
         try {
             metaFrame.setPage(metaNode);
-            filterPageId = metaFrame.getLSMComponentFilterPageId();
-            if (appendOnly && filterPageId == -1) {
-                //hint to filter manager that we are in append-only mode
-                filterPageId = NO_FILTER_APPEND_ONLY;
-            }
+            return metaFrame.getLSMComponentFilterPageId();
         } finally {
             metaNode.releaseReadLatch();
-            if (!appendOnly || confiscatedMetaNode == null) {
-                bufferCache.unpin(metaNode);
-            }
+            bufferCache.unpin(metaNode);
         }
-        return filterPageId;
     }
 
     @Override
-    public void init(ITreeIndexMetaDataFrame metaFrame, int currentMaxPage) throws HyracksDataException {
+    public void init(ITreeIndexFrameFactory interiorFrameFactory, ITreeIndexFrameFactory leafFrameFactory)
+            throws HyracksDataException {
         // initialize meta data page
-        int metaPage = getFirstMetadataPage();
+        ITreeIndexMetaDataFrame metaFrame = createMetadataFrame();
+        int metaPage = getMetadataPageId();
         if (metaPage == IBufferCache.INVALID_PAGEID) {
             throw new HyracksDataException("No valid metadata found in this file.");
         }
-        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), true);
-
+        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), true);
         metaNode.acquireWriteLatch();
         try {
             metaFrame.setPage(metaNode);
-            metaFrame.initBuffer(META_PAGE_LEVEL_INDICATOR);
-            metaFrame.setMaxPage(currentMaxPage);
+            metaFrame.initBuffer();
+            metaFrame.setRootPageNumber(1);
+            metaFrame.setMaxPage(1);
         } finally {
             metaNode.releaseWriteLatch(true);
+            bufferCache.flushDirtyPage(metaNode);
             bufferCache.unpin(metaNode);
         }
-    }
-
-    @Override
-    public void init(ITreeIndexMetaDataFrame metaFrame) throws HyracksDataException {
-        if (confiscatedMetaNode != null) { // don't init twice
-            return;
-        }
-        ICachedPage metaNode = bufferCache.confiscatePage(BufferCache.INVALID_DPID);
+        int rootPage = getRootPageId();
+        ICachedPage rootNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rootPage), true);
+        rootNode.acquireWriteLatch();
         try {
-            metaFrame.setPage(metaNode);
-            metaFrame.initBuffer(META_PAGE_LEVEL_INDICATOR);
-            metaFrame.setMaxPage(-1);
+            ITreeIndexFrame leafFrame = leafFrameFactory.createFrame();
+            leafFrame.setPage(rootNode);
+            leafFrame.initBuffer((byte) 0);
         } finally {
-            confiscatedMetaNode = metaNode;
-            appendOnly = true;
+            rootNode.releaseWriteLatch(true);
+            bufferCache.flushDirtyPage(rootNode);
+            bufferCache.unpin(rootNode);
         }
     }
 
     @Override
-    public ITreeIndexMetaDataFrameFactory getMetaDataFrameFactory() {
-        return metaDataFrameFactory;
-    }
-
-    @Override
-    public byte getFreePageLevelIndicator() {
-        return FREE_PAGE_LEVEL_INDICATOR;
-    }
-
-    @Override
-    public byte getMetaPageLevelIndicator() {
-        return META_PAGE_LEVEL_INDICATOR;
-    }
-
-    @Override
-    public boolean isFreePage(ITreeIndexMetaDataFrame metaFrame) {
-        return metaFrame.getLevel() == FREE_PAGE_LEVEL_INDICATOR;
-    }
-
-    @Override
-    public boolean isMetaPage(ITreeIndexMetaDataFrame metaFrame) {
-        return metaFrame.getLevel() == META_PAGE_LEVEL_INDICATOR;
+    public ITreeIndexMetaDataFrame createMetadataFrame() {
+        return frameFactory.createFrame();
     }
 
     @Override
@@ -321,29 +257,37 @@ public class LinkedMetaDataPageManager implements IMetaDataPageManager {
     }
 
     @Override
-    public void close() throws HyracksDataException {
-        if (appendOnly && fileId >= 0 && confiscatedMetaNode != null) {
-            IFIFOPageQueue queue = bufferCache.createFIFOQueue();
-            writeFilterPage(queue);
-            ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
-            metaFrame.setPage(confiscatedMetaNode);
-            metaFrame.setValid(true);
-            int finalMetaPage = getMaxPage(metaFrame) + 1;
-            bufferCache.setPageDiskId(confiscatedMetaNode, BufferedFileHandle.getDiskPageId(fileId, finalMetaPage));
-            queue.put(confiscatedMetaNode);
-            bufferCache.finishQueue();
-            confiscatedMetaNode = null;
+    public void setRootPageId(int rootPage) throws HyracksDataException {
+        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+        metaNode.acquireWriteLatch();
+        try {
+            metaFrame.setPage(metaNode);
+            metaFrame.setRootPageNumber(rootPage);
+        } finally {
+            metaNode.releaseWriteLatch(true);
+            bufferCache.unpin(metaNode);
+            ready = true;
         }
     }
 
-    private void writeFilterPage(IFIFOPageQueue queue) throws HyracksDataException {
-        if (filterPage != null) {
-            ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
-            metaFrame.setPage(confiscatedMetaNode);
-            int finalFilterPage = getFreePage(metaFrame);
-            setFilterPageId(finalFilterPage);
-            bufferCache.setPageDiskId(filterPage, BufferedFileHandle.getDiskPageId(fileId, finalFilterPage));
-            queue.put(filterPage);
+    @Override
+    public void close() throws HyracksDataException {
+        if (ready) {
+            ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()),
+                    false);
+            ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+            metaNode.acquireWriteLatch();
+            try {
+                metaFrame.setPage(metaNode);
+                metaFrame.setValid(true);
+            } finally {
+                metaNode.releaseWriteLatch(true);
+                bufferCache.flushDirtyPage(metaNode);
+                bufferCache.unpin(metaNode);
+                ready = true;
+            }
+            ready = false;
         }
     }
 
@@ -357,186 +301,125 @@ public class LinkedMetaDataPageManager implements IMetaDataPageManager {
      * @throws HyracksDataException
      */
     @Override
-    public int getFirstMetadataPage() throws HyracksDataException {
-        if (headPage != IBufferCache.INVALID_PAGEID) {
-            return headPage;
-        }
-
-        ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
-
-        int pages = bufferCache.getNumPagesOfFile(fileId);
-        //if there are no pages in the file yet, we're just initializing
-        if (pages == 0) {
-            return 0;
-        }
-        //look at the front (modify in-place index)
-        int page = 0;
-        ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, page), false);
-        try {
-            metaNode.acquireReadLatch();
-            metaFrame.setPage(metaNode);
-
-            if (isMetaPage(metaFrame)) {
-                headPage = page;
-                return headPage;
-            }
-        } finally {
-            metaNode.releaseReadLatch();
-            bufferCache.unpin(metaNode);
-        }
-        //otherwise, look at the back. (append-only index)
-        page = pages - 1 > 0 ? pages - 1 : 0;
-        metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, page), false);
-        try {
-            metaNode.acquireReadLatch();
-            metaFrame.setPage(metaNode);
-
-            if (isMetaPage(metaFrame)) {
-                headPage = page;
-                return headPage;
-            }
-        } finally {
-            metaNode.releaseReadLatch();
-            bufferCache.unpin(metaNode);
-        }
-        //if we find nothing, this isn't a tree (or isn't one yet).
-        if (pages > 0) {
-            return IBufferCache.INVALID_PAGEID;
-        } else {
-            return 0;
-        }
+    public int getMetadataPageId() throws HyracksDataException {
+        return 0;
     }
 
     @Override
     public long getLSN() throws HyracksDataException {
         ICachedPage metaNode;
-        if (!appendOnly || confiscatedMetaNode == null) {
-            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), false);
-        } else {
-            metaNode = confiscatedMetaNode;
-        }
-        ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
+        metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
         metaNode.acquireReadLatch();
         try {
             metaFrame.setPage(metaNode);
             return metaFrame.getLSN();
         } finally {
             metaNode.releaseReadLatch();
-            if (!appendOnly || confiscatedMetaNode == null) {
-                bufferCache.unpin(metaNode);
-            }
+            bufferCache.unpin(metaNode);
         }
     }
 
     @Override
     public void setLSN(long lsn) throws HyracksDataException {
         ICachedPage metaNode;
-        if (!appendOnly) {
-            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), false);
-        } else {
-            metaNode = confiscatedMetaNode;
-        }
-        ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
+        metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
         metaNode.acquireWriteLatch();
         try {
             metaFrame.setPage(metaNode);
             metaFrame.setLSN(lsn);
         } finally {
-            if (!appendOnly) {
-                metaNode.releaseWriteLatch(true);
-                bufferCache.unpin(metaNode);
-            } else {
-                metaNode.releaseWriteLatch(false);
-            }
+            metaNode.releaseWriteLatch(true);
+            bufferCache.unpin(metaNode);
         }
     }
 
     @Override
-    public void setFilterPage(ICachedPage filterPage) {
-        this.filterPage = filterPage;
+    public void setFilterPage(ICachedPage filterPage) throws HyracksDataException {
+        filterPage.releaseWriteLatch(true);
+        bufferCache.unpin(filterPage);
+        bufferCache.flushDirtyPage(filterPage);
     }
 
     @Override
-    public ICachedPage getFilterPage() {
-        return this.filterPage;
-    }
-
-    @Override
-    public boolean appendOnlyMode() {
-        return appendOnly;
+    public ICachedPage getFilterPage() throws HyracksDataException {
+        ITreeIndexMetaDataFrame metadataFrame = frameFactory.createFrame();
+        int metaPageId = getMetadataPageId();
+        ICachedPage metadataPage = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, metaPageId), false);
+        metadataPage.acquireWriteLatch();
+        int filterPageId;
+        try {
+            metadataFrame.setPage(metadataPage);
+            filterPageId = takePage(metadataFrame);
+            metadataFrame.setLSMComponentFilterPageId(filterPageId);
+        } finally {
+            metadataPage.releaseWriteLatch(true);
+            bufferCache.unpin(metadataPage);
+        }
+        ICachedPage filterPage = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, filterPageId), true);
+        filterPage.acquireWriteLatch();
+        return filterPage;
     }
 
     @Override
     public long getLSNOffset() throws HyracksDataException {
-        int metadataPageNum = getFirstMetadataPage();
+        int metadataPageNum = getMetadataPageId();
         if (metadataPageNum != IBufferCache.INVALID_PAGEID) {
             return ((long) metadataPageNum * bufferCache.getPageSizeWithHeader()) + LIFOMetaDataFrame.LSN_OFFSET;
         }
-        return IMetaDataPageManager.INVALID_LSN_OFFSET;
+        return IMetadataPageManager.Constants.INVALID_LSN_OFFSET;
     }
 
     @Override
     public long getLastMarkerLSN() throws HyracksDataException {
         ICachedPage metaNode;
-        if (!appendOnly || (appendOnly && confiscatedMetaNode == null)) {
-            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), false);
-        } else {
-            metaNode = confiscatedMetaNode;
-        }
-        ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
+        metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
         metaNode.acquireReadLatch();
         try {
             metaFrame.setPage(metaNode);
             return metaFrame.getLastMarkerLSN();
         } finally {
             metaNode.releaseReadLatch();
-            if (!appendOnly || (appendOnly && confiscatedMetaNode == null)) {
-                bufferCache.unpin(metaNode);
-            }
+            bufferCache.unpin(metaNode);
         }
     }
 
     @Override
-    public void setRootPage(int rootPage) throws HyracksDataException {
+    public int getRootPageId() throws HyracksDataException {
         ICachedPage metaNode;
-        if (!appendOnly) {
-            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), false);
-        } else {
-            metaNode = confiscatedMetaNode;
-        }
-        ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
-        metaNode.acquireWriteLatch();
+        metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getMetadataPageId()), false);
+        ITreeIndexMetaDataFrame metaFrame = frameFactory.createFrame();
+        metaNode.acquireReadLatch();
         try {
             metaFrame.setPage(metaNode);
-            metaFrame.setRootPageNumber(rootPage);
+            return metaFrame.getRootPageNumber();
         } finally {
-            if (!appendOnly) {
-                metaNode.releaseWriteLatch(true);
-                bufferCache.unpin(metaNode);
-            } else {
-                metaNode.releaseWriteLatch(false);
-            }
+            metaNode.releaseReadLatch();
+            bufferCache.unpin(metaNode);
         }
     }
 
     @Override
-    public int getRootPage() throws HyracksDataException {
-        ICachedPage metaNode;
-        if (!appendOnly || confiscatedMetaNode == null) {
-            metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), false);
-        } else {
-            metaNode = confiscatedMetaNode;
-        }
-        ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
-        metaNode.acquireReadLatch();
+    public int getBulkLoadLeaf() throws HyracksDataException {
+        return 2;
+    }
+
+    @Override
+    public boolean isEmpty(ITreeIndexFrame frame, int rootPage) throws HyracksDataException {
+        ICachedPage rootNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, rootPage), false);
+        rootNode.acquireReadLatch();
         try {
-            metaFrame.setPage(metaNode);
-            return metaFrame.getRootPageNumber();
-        } finally {
-            metaNode.releaseReadLatch();
-            if (!appendOnly || confiscatedMetaNode == null) {
-                bufferCache.unpin(metaNode);
+            frame.setPage(rootNode);
+            if (frame.getLevel() == 0 && frame.getTupleCount() == 0) {
+                return true;
+            } else {
+                return false;
             }
+        } finally {
+            rootNode.releaseReadLatch();
+            bufferCache.unpin(rootNode);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/bc3d1b05/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetadataPageManagerFactory.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetadataPageManagerFactory.java b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetadataPageManagerFactory.java
new file mode 100644
index 0000000..393ded3
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetadataPageManagerFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 at
+ *
+ *   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 org.apache.hyracks.storage.am.common.freepage;
+
+import org.apache.hyracks.storage.am.common.api.IMetadataPageManager;
+import org.apache.hyracks.storage.am.common.api.IMetadataPageManagerFactory;
+import org.apache.hyracks.storage.am.common.frames.LIFOMetaDataFrameFactory;
+import org.apache.hyracks.storage.common.buffercache.IBufferCache;
+
+public class LinkedMetadataPageManagerFactory implements IMetadataPageManagerFactory {
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public IMetadataPageManager createPageManager(IBufferCache bufferCache) {
+        return new LinkedMetaDataPageManager(bufferCache, new LIFOMetaDataFrameFactory());
+    }
+
+}