// was:balance private RC Balance() { var rc = RC.OK; var nMin = (int)this.Shared.UsableSize * 2 / 3; var balance_quick_called = 0; var balance_deeper_called = 0; do { var pageID = this.PageID; var page = this.Pages[pageID]; if (pageID == 0) { if (page.NOverflows != 0) { // The root page of the b-tree is overfull. In this case call the balance_deeper() function to create a new child for the root-page // and copy the current contents of the root-page to it. The next iteration of the do-loop will balance the child page. Debug.Assert((balance_deeper_called++) == 0); rc = MemPage.balance_deeper(page, ref this.Pages[1]); if (rc == RC.OK) { this.PageID = 1; this.PagesIndexs[0] = 0; this.PagesIndexs[1] = 0; Debug.Assert(this.Pages[1].NOverflows != 0); } } else { break; } } else if (page.NOverflows == 0 && page.FreeBytes <= nMin) { break; } else { var pParent = this.Pages[pageID - 1]; var iIdx = this.PagesIndexs[pageID - 1]; rc = Pager.Write(pParent.DbPage); if (rc == RC.OK) { #if !SQLITE_OMIT_QUICKBALANCE if (page.HasData != 0 && page.NOverflows == 1 && page.Overflows[0].Index == page.Cells && pParent.ID != 1 && pParent.Cells == iIdx) { // Call balance_quick() to create a new sibling of pPage on which to store the overflow cell. balance_quick() inserts a new cell // into pParent, which may cause pParent overflow. If this happens, the next interation of the do-loop will balance pParent // use either balance_nonroot() or balance_deeper(). Until this happens, the overflow cell is stored in the aBalanceQuickSpace[] // buffer. // The purpose of the following Debug.Assert() is to check that only a single call to balance_quick() is made for each call to this // function. If this were not verified, a subtle bug involving reuse of the aBalanceQuickSpace[] might sneak in. Debug.Assert((balance_quick_called++) == 0); rc = MemPage.balance_quick(pParent, page, _balanceQuickSpaces); } else #endif { // In this case, call balance_nonroot() to redistribute cells between pPage and up to 2 of its sibling pages. This involves // modifying the contents of pParent, which may cause pParent to become overfull or underfull. The next iteration of the do-loop // will balance the parent page to correct this. // If the parent page becomes overfull, the overflow cell or cells are stored in the pSpace buffer allocated immediately below. // A subsequent iteration of the do-loop will deal with this by calling balance_nonroot() (balance_deeper() may be called first, // but it doesn't deal with overflow cells - just moves them to a different page). Once this subsequent call to balance_nonroot() // has completed, it is safe to release the pSpace buffer used by the previous call, as the overflow cell data will have been // copied either into the body of a database page or into the new pSpace buffer passed to the latter call to balance_nonroot(). var pSpace = new byte[this.Shared.PageSize];// u8 pSpace = sqlite3PageMalloc( pCur.pBt.pageSize ); rc = MemPage.balance_nonroot(pParent, iIdx, null, pageID == 1 ? 1 : 0); // The pSpace buffer will be freed after the next call to balance_nonroot(), or just before this function returns, whichever comes first. } } page.NOverflows = 0; // The next iteration of the do-loop balances the parent page. page.releasePage(); this.PageID--; } } while (rc == RC.OK); return(rc); }