internal static RC relocatePage(BtShared pBt, MemPage pDbPage, PTRMAP eType, Pgno iPtrPage, Pgno iFreePage, int isCommit)
        {
            var pPtrPage = new MemPage();   // The page that contains a pointer to pDbPage
            var iDbPage  = pDbPage.ID;
            var pPager   = pBt.Pager;

            Debug.Assert(eType == PTRMAP.OVERFLOW2 || eType == PTRMAP.OVERFLOW1 || eType == PTRMAP.BTREE || eType == PTRMAP.ROOTPAGE);
            Debug.Assert(MutexEx.Held(pBt.Mutex));
            Debug.Assert(pDbPage.Shared == pBt);
            // Move page iDbPage from its current location to page number iFreePage
            Btree.TRACE("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", iDbPage, iFreePage, iPtrPage, eType);
            var rc = pPager.sqlite3PagerMovepage(pDbPage.DbPage, iFreePage, isCommit);

            if (rc != RC.OK)
            {
                return(rc);
            }
            pDbPage.ID = iFreePage;
            // If pDbPage was a btree-page, then it may have child pages and/or cells that point to overflow pages. The pointer map entries for all these
            // pages need to be changed.
            // If pDbPage is an overflow page, then the first 4 bytes may store a pointer to a subsequent overflow page. If this is the case, then
            // the pointer map needs to be updated for the subsequent overflow page.
            if (eType == PTRMAP.BTREE || eType == PTRMAP.ROOTPAGE)
            {
                rc = pDbPage.setChildPtrmaps();
                if (rc != RC.OK)
                {
                    return(rc);
                }
            }
            else
            {
                var nextOvfl = (Pgno)ConvertEx.Get4(pDbPage.Data);
                if (nextOvfl != 0)
                {
                    pBt.ptrmapPut(nextOvfl, PTRMAP.OVERFLOW2, iFreePage, ref rc);
                    if (rc != RC.OK)
                    {
                        return(rc);
                    }
                }
            }
            // Fix the database pointer on page iPtrPage that pointed at iDbPage so that it points at iFreePage. Also fix the pointer map entry for iPtrPage.
            if (eType != PTRMAP.ROOTPAGE)
            {
                rc = pBt.btreeGetPage(iPtrPage, ref pPtrPage, 0);
                if (rc != RC.OK)
                {
                    return(rc);
                }
                rc = Pager.Write(pPtrPage.DbPage);
                if (rc != RC.OK)
                {
                    pPtrPage.releasePage();
                    return(rc);
                }
                rc = pPtrPage.modifyPagePointer(iDbPage, iFreePage, eType);
                pPtrPage.releasePage();
                if (rc == RC.OK)
                {
                    pBt.ptrmapPut(iFreePage, eType, iPtrPage, ref rc);
                }
            }
            return(rc);
        }
 internal static RC relocatePage(BtShared pBt, MemPage pDbPage, PTRMAP eType, Pgno iPtrPage, Pgno iFreePage, int isCommit)
 {
     var pPtrPage = new MemPage();   // The page that contains a pointer to pDbPage
     var iDbPage = pDbPage.ID;
     var pPager = pBt.Pager;
     Debug.Assert(eType == PTRMAP.OVERFLOW2 || eType == PTRMAP.OVERFLOW1 || eType == PTRMAP.BTREE || eType == PTRMAP.ROOTPAGE);
     Debug.Assert(MutexEx.Held(pBt.Mutex));
     Debug.Assert(pDbPage.Shared == pBt);
     // Move page iDbPage from its current location to page number iFreePage
     Btree.TRACE("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", iDbPage, iFreePage, iPtrPage, eType);
     var rc = pPager.sqlite3PagerMovepage(pDbPage.DbPage, iFreePage, isCommit);
     if (rc != RC.OK)
         return rc;
     pDbPage.ID = iFreePage;
     // If pDbPage was a btree-page, then it may have child pages and/or cells that point to overflow pages. The pointer map entries for all these
     // pages need to be changed.
     // If pDbPage is an overflow page, then the first 4 bytes may store a pointer to a subsequent overflow page. If this is the case, then
     // the pointer map needs to be updated for the subsequent overflow page.
     if (eType == PTRMAP.BTREE || eType == PTRMAP.ROOTPAGE)
     {
         rc = pDbPage.setChildPtrmaps();
         if (rc != RC.OK)
             return rc;
     }
     else
     {
         var nextOvfl = (Pgno)ConvertEx.Get4(pDbPage.Data);
         if (nextOvfl != 0)
         {
             pBt.ptrmapPut(nextOvfl, PTRMAP.OVERFLOW2, iFreePage, ref rc);
             if (rc != RC.OK)
                 return rc;
         }
     }
     // Fix the database pointer on page iPtrPage that pointed at iDbPage so that it points at iFreePage. Also fix the pointer map entry for iPtrPage.
     if (eType != PTRMAP.ROOTPAGE)
     {
         rc = pBt.btreeGetPage(iPtrPage, ref pPtrPage, 0);
         if (rc != RC.OK)
             return rc;
         rc = Pager.Write(pPtrPage.DbPage);
         if (rc != RC.OK)
         {
             pPtrPage.releasePage();
             return rc;
         }
         rc = pPtrPage.modifyPagePointer(iDbPage, iFreePage, eType);
         pPtrPage.releasePage();
         if (rc == RC.OK)
             pBt.ptrmapPut(iFreePage, eType, iPtrPage, ref rc);
     }
     return rc;
 }