Esempio n. 1
0
        internal static void copyNodeContent(MemPage pFrom, MemPage pTo, ref RC pRC)
        {
            if (pRC != RC.OK)
            {
                return;
            }
            var pBt      = pFrom.Shared;
            var aFrom    = pFrom.Data;
            var aTo      = pTo.Data;
            var iFromHdr = pFrom.HeaderOffset;
            var iToHdr   = (pTo.ID == 1 ? 100 : 0);

            Debug.Assert(pFrom.HasInit);
            Debug.Assert(pFrom.FreeBytes >= iToHdr);
            Debug.Assert(ConvertEx.Get2(aFrom, iFromHdr + 5) <= (int)pBt.UsableSize);
            // Copy the b-tree node content from page pFrom to page pTo.
            var iData = (int)ConvertEx.Get2(aFrom, iFromHdr + 5);

            Buffer.BlockCopy(aFrom, iData, aTo, iData, (int)pBt.UsableSize - iData);
            Buffer.BlockCopy(aFrom, iFromHdr, aTo, iToHdr, pFrom.CellOffset + 2 * pFrom.Cells);
            // Reinitialize page pTo so that the contents of the MemPage structure match the new data. The initialization of pTo can actually fail under
            // fairly obscure circumstances, even though it is a copy of initialized  page pFrom.
            pTo.HasInit = false;
            var rc = pTo.btreeInitPage();

            if (rc != RC.OK)
            {
                pRC = rc;
                return;
            }
            // If this is an auto-vacuum database, update the pointer-map entries for any b-tree or overflow pages that pTo now contains the pointers to.
#if !SQLITE_OMIT_AUTOVACUUM
            if (pBt.AutoVacuum)
#else
            if (false)
#endif
            {
                pRC = pTo.setChildPtrmaps();
            }
        }
Esempio n. 2
0
 internal static void copyNodeContent(MemPage pFrom, MemPage pTo, ref RC pRC)
 {
     if (pRC != RC.OK)
         return;
     var pBt = pFrom.Shared;
     var aFrom = pFrom.Data;
     var aTo = pTo.Data;
     var iFromHdr = pFrom.HeaderOffset;
     var iToHdr = (pTo.ID == 1 ? 100 : 0);
     Debug.Assert(pFrom.HasInit);
     Debug.Assert(pFrom.FreeBytes >= iToHdr);
     Debug.Assert(ConvertEx.Get2(aFrom, iFromHdr + 5) <= (int)pBt.UsableSize);
     // Copy the b-tree node content from page pFrom to page pTo.
     var iData = (int)ConvertEx.Get2(aFrom, iFromHdr + 5);
     Buffer.BlockCopy(aFrom, iData, aTo, iData, (int)pBt.UsableSize - iData);
     Buffer.BlockCopy(aFrom, iFromHdr, aTo, iToHdr, pFrom.CellOffset + 2 * pFrom.Cells);
     // Reinitialize page pTo so that the contents of the MemPage structure match the new data. The initialization of pTo can actually fail under
     // fairly obscure circumstances, even though it is a copy of initialized  page pFrom.
     pTo.HasInit = false;
     var rc = pTo.btreeInitPage();
     if (rc != RC.OK)
     {
         pRC = rc;
         return;
     }
     // If this is an auto-vacuum database, update the pointer-map entries for any b-tree or overflow pages that pTo now contains the pointers to.
     #if !SQLITE_OMIT_AUTOVACUUM
     if (pBt.AutoVacuum)
     #else
     if (false)
     #endif
     {
         pRC = pTo.setChildPtrmaps();
     }
 }
Esempio n. 3
0
        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;
 }