internal static RC sqlite3BtreeIncrVacuum(Btree p) { var pBt = p.Shared; p.sqlite3BtreeEnter(); Debug.Assert(pBt.InTransaction == TRANS.WRITE && p.InTransaction == TRANS.WRITE); RC rc; if (!pBt.AutoVacuum) { rc = RC.DONE; } else { Btree.invalidateAllOverflowCache(pBt); rc = incrVacuumStep(pBt, 0, pBt.btreePagecount()); if (rc == RC.OK) { rc = Pager.Write(pBt.Page1.DbPage); ConvertEx.Put4(pBt.Page1.Data, 28, pBt.Pages); } } p.sqlite3BtreeLeave(); return(rc); }
internal static RC autoVacuumCommit(BtShared pBt) { var rc = RC.OK; var pPager = pBt.Pager; #if DEBUG var nRef = pPager.RefCount; #else var nRef = 0; #endif Debug.Assert(MutexEx.Held(pBt.Mutex)); Btree.invalidateAllOverflowCache(pBt); Debug.Assert(pBt.AutoVacuum); if (!pBt.IncrVacuum) { var nOrig = pBt.btreePagecount(); // Database size before freeing if (PTRMAP_ISPAGE(pBt, nOrig) || nOrig == PENDING_BYTE_PAGE(pBt)) { // It is not possible to create a database for which the final page is either a pointer-map page or the pending-byte page. If one // is encountered, this indicates corruption. return(SysEx.SQLITE_CORRUPT_BKPT()); } var nFree = (Pgno)ConvertEx.Get4(pBt.Page1.Data, 36); // Number of pages on the freelist initially var nEntry = (int)pBt.UsableSize / 5; // Number of entries on one ptrmap page var nPtrmap = (Pgno)((nFree - nOrig + PTRMAP_PAGENO(pBt, nOrig) + (Pgno)nEntry) / nEntry); // Number of PtrMap pages to be freed var nFin = nOrig - nFree - nPtrmap; // Number of pages in database after autovacuuming if (nOrig > PENDING_BYTE_PAGE(pBt) && nFin < PENDING_BYTE_PAGE(pBt)) { nFin--; } while (PTRMAP_ISPAGE(pBt, nFin) || nFin == PENDING_BYTE_PAGE(pBt)) { nFin--; } if (nFin > nOrig) { return(SysEx.SQLITE_CORRUPT_BKPT()); } for (var iFree = nOrig; iFree > nFin && rc == RC.OK; iFree--) { rc = incrVacuumStep(pBt, nFin, iFree); } if ((rc == RC.DONE || rc == RC.OK) && nFree > 0) { rc = Pager.Write(pBt.Page1.DbPage); ConvertEx.Put4(pBt.Page1.Data, 32, 0); ConvertEx.Put4(pBt.Page1.Data, 36, 0); ConvertEx.Put4(pBt.Page1.Data, 28, nFin); pBt.Pager.TruncateImage(nFin); pBt.Pages = nFin; } if (rc != RC.OK) { pPager.Rollback(); } } Debug.Assert(nRef == pPager.RefCount); return(rc); }