Add Method to Get LSN Byte Offset in LSM Disk Components

The LSN byte offset is needed to support updating LSNs in remote replicas.

Change-Id: I2eb407e607157fe9c71a9cf22b04accc832be31b
Reviewed-on: https://asterix-gerrit.ics.uci.edu/560
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ian Maxon <imaxon@apache.org>
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/api/IMetaDataPageManager.java b/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/api/IMetaDataPageManager.java
index 432eb59..c1dcce7 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/api/IMetaDataPageManager.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/api/IMetaDataPageManager.java
@@ -22,6 +22,8 @@
 import org.apache.hyracks.storage.common.buffercache.ICachedPage;
 
 public interface IMetaDataPageManager {
+    public static final long INVALID_LSN_OFFSET = -1;
+
     /**
      * This is the class through which one interfaces with index metadata.
      * The index metadata contains information such as the LSN of the index, free page information,
@@ -130,4 +132,10 @@
 
     boolean appendOnlyMode();
 
+    /**
+     * @return The LSN byte offset in the LSM disk component if the index is valid, otherwise {@link #INVALID_LSN_OFFSET}.
+     * @throws HyracksDataException 
+     */
+    long getLSNOffset() throws HyracksDataException;
+
 }
diff --git a/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetaDataPageManager.java b/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetaDataPageManager.java
index a89bb0f..61f5919 100644
--- a/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetaDataPageManager.java
+++ b/hyracks/hyracks-storage-am-common/src/main/java/org/apache/hyracks/storage/am/common/freepage/LinkedMetaDataPageManager.java
@@ -24,6 +24,7 @@
 import org.apache.hyracks.storage.am.common.api.IMetaDataPageManager;
 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;
@@ -37,14 +38,13 @@
     public static final int NO_FILTER_IN_PLACE = -1;
     public static final int NO_FILTER_APPEND_ONLY = -2;
     private final IBufferCache bufferCache;
-    private int headPage = -1;
+    private int headPage = IBufferCache.INVALID_PAGEID;
     private int fileId = -1;
     private final ITreeIndexMetaDataFrameFactory metaDataFrameFactory;
     private boolean appendOnly = false;
     ICachedPage confiscatedMetaNode;
     ICachedPage filterPage;
-    private static Logger LOGGER = Logger
-            .getLogger(LinkedMetaDataPageManager.class.getName());
+    private static Logger LOGGER = Logger.getLogger(LinkedMetaDataPageManager.class.getName());
 
     public LinkedMetaDataPageManager(IBufferCache bufferCache, ITreeIndexMetaDataFrameFactory metaDataFrameFactory) {
         this.bufferCache = bufferCache;
@@ -53,7 +53,6 @@
 
     @Override
     public void addFreePage(ITreeIndexMetaDataFrame metaFrame, int freePage) throws HyracksDataException {
-
         ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), false);
         metaNode.acquireWriteLatch();
 
@@ -76,8 +75,8 @@
                     int metaMaxPage = metaFrame.getMaxPage();
 
                     // copy metaDataPage to newNode
-                    System.arraycopy(metaNode.getBuffer().array(), 0, newNode.getBuffer().array(), 0, metaNode
-                            .getBuffer().capacity());
+                    System.arraycopy(metaNode.getBuffer().array(), 0, newNode.getBuffer().array(), 0,
+                            metaNode.getBuffer().capacity());
 
                     metaFrame.initBuffer(META_PAGE_LEVEL_INDICATOR);
                     metaFrame.setNextPage(newPage);
@@ -128,8 +127,8 @@
                         // copy entire page (including sibling pointer, free
                         // page entries, and all other info)
                         // after this copy nextPage is considered a free page
-                        System.arraycopy(nextNode.getBuffer().array(), 0, metaNode.getBuffer().array(), 0, nextNode
-                                .getBuffer().capacity());
+                        System.arraycopy(nextNode.getBuffer().array(), 0, metaNode.getBuffer().array(), 0,
+                                nextNode.getBuffer().capacity());
 
                         // reset unchanged entry
                         metaFrame.setMaxPage(maxPage);
@@ -169,7 +168,7 @@
         ICachedPage metaNode;
         if (!appendOnly || (appendOnly && confiscatedMetaNode == null)) {
             int mdPage = getFirstMetadataPage();
-            if( mdPage <0 ){
+            if (mdPage < 0) {
                 return IBufferCache.INVALID_PAGEID;
             }
             metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, mdPage), false);
@@ -195,7 +194,7 @@
         ICachedPage metaNode;
         if (!appendOnly) {
             int mdPage = getFirstMetadataPage();
-            if( mdPage <0 ){
+            if (mdPage < 0) {
                 return;
             }
             metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, mdPage), false);
@@ -231,7 +230,7 @@
         try {
             metaFrame.setPage(metaNode);
             filterPageId = metaFrame.getLSMComponentFilterPageId();
-            if(appendOnly && filterPageId == -1){
+            if (appendOnly && filterPageId == -1) {
                 //hint to filter manager that we are in append-only mode
                 filterPageId = NO_FILTER_APPEND_ONLY;
             }
@@ -248,7 +247,7 @@
     public void init(ITreeIndexMetaDataFrame metaFrame, int currentMaxPage) throws HyracksDataException {
         // initialize meta data page
         int metaPage = getFirstMetadataPage();
-        if(metaPage == IBufferCache.INVALID_PAGEID){
+        if (metaPage == IBufferCache.INVALID_PAGEID) {
             throw new HyracksDataException("No valid metadata found in this file.");
         }
         ICachedPage metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, getFirstMetadataPage()), true);
@@ -319,7 +318,7 @@
             metaFrame.setPage(confiscatedMetaNode);
             metaFrame.setValid(true);
             int finalMetaPage = getMaxPage(metaFrame) + 1;
-            bufferCache.setPageDiskId(confiscatedMetaNode, BufferedFileHandle.getDiskPageId(fileId,finalMetaPage));
+            bufferCache.setPageDiskId(confiscatedMetaNode, BufferedFileHandle.getDiskPageId(fileId, finalMetaPage));
             queue.put(confiscatedMetaNode);
             bufferCache.finishQueue();
             confiscatedMetaNode = null;
@@ -327,7 +326,7 @@
     }
 
     private void writeFilterPage(IFIFOPageQueue queue) throws HyracksDataException {
-        if(filterPage != null) {
+        if (filterPage != null) {
             ITreeIndexMetaDataFrame metaFrame = metaDataFrameFactory.createFrame();
             metaFrame.setPage(confiscatedMetaNode);
             int finalFilterPage = getFreePage(metaFrame);
@@ -354,7 +353,7 @@
 
         int pages = bufferCache.getNumPagesOfFile(fileId);
         //if there are no pages in the file yet, we're just initializing
-        if(pages == 0){
+        if (pages == 0) {
             return 0;
         }
         //look at the front (modify in-place index)
@@ -373,7 +372,7 @@
             bufferCache.unpin(metaNode);
         }
         //otherwise, look at the back. (append-only index)
-        page = pages-1 >0 ? pages -1 : 0;
+        page = pages - 1 > 0 ? pages - 1 : 0;
         metaNode = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, page), false);
         try {
             metaNode.acquireReadLatch();
@@ -388,10 +387,9 @@
             bufferCache.unpin(metaNode);
         }
         //if we find nothing, this isn't a tree (or isn't one yet).
-        if(pages>0){
+        if (pages > 0) {
             return IBufferCache.INVALID_PAGEID;
-        }
-        else{
+        } else {
             return 0;
         }
     }
@@ -454,5 +452,13 @@
     public boolean appendOnlyMode() {
         return appendOnly;
     }
-}
 
+    @Override
+    public long getLSNOffset() throws HyracksDataException {
+        int metadataPageNum = getFirstMetadataPage();
+        if (metadataPageNum != IBufferCache.INVALID_PAGEID) {
+            return (metadataPageNum * bufferCache.getPageSize()) + LIFOMetaDataFrame.lsnOff;
+        }
+        return IMetaDataPageManager.INVALID_LSN_OFFSET;
+    }
+}
diff --git a/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/freepage/VirtualMetaDataPageManager.java b/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/freepage/VirtualMetaDataPageManager.java
index 08ac2f8..cd28f0f 100644
--- a/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/freepage/VirtualMetaDataPageManager.java
+++ b/hyracks/hyracks-storage-am-lsm-common/src/main/java/org/apache/hyracks/storage/am/lsm/common/freepage/VirtualMetaDataPageManager.java
@@ -23,6 +23,7 @@
 
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.storage.am.common.api.IVirtualMetaDataPageManager;
+import org.apache.hyracks.storage.am.common.api.IMetaDataPageManager;
 import org.apache.hyracks.storage.am.common.api.ITreeIndexMetaDataFrame;
 import org.apache.hyracks.storage.am.common.api.ITreeIndexMetaDataFrameFactory;
 import org.apache.hyracks.storage.common.buffercache.ICachedPage;
@@ -150,7 +151,7 @@
         // Method doesn't make sense for this free page manager.
     }
 
-    public ICachedPage getFilterPage(){
+    public ICachedPage getFilterPage() {
         return null;
     }
 
@@ -159,4 +160,8 @@
         return false;
     }
 
+    @Override
+    public long getLSNOffset() throws HyracksDataException {
+        return IMetaDataPageManager.INVALID_LSN_OFFSET;
+    }
 }