public Page Execute(Page page) { _tree.ClearRecentFoundPages(); if (_cursor.PageCount <= 1) // the root page { RebalanceRoot(page); return(null); } var parentPage = _tx.ModifyPage(_cursor.ParentPage.PageNumber, _tree, _cursor.ParentPage); _cursor.Update(_cursor.Pages.First.Next, parentPage); if (page.NumberOfEntries == 0) // empty page, just delete it and fixup parent { // need to change the implicit left page if (parentPage.LastSearchPosition == 0 && parentPage.NumberOfEntries > 2) { var newImplicit = parentPage.GetNode(1)->PageNumber; parentPage.RemoveNode(0); parentPage.ChangeImplicitRefPageNode(newImplicit); } else // will be set to rights by the next rebalance call { parentPage.RemoveNode(parentPage.LastSearchPositionOrLastEntry); } _tree.FreePage(page); _cursor.Pop(); return(parentPage); } if (page.IsBranch && page.NumberOfEntries == 1) { RemoveBranchWithOneEntry(page, parentPage); _cursor.Pop(); return(parentPage); } var minKeys = page.IsBranch ? 2 : 1; if ((page.UseMoreSizeThan(_tx.DataPager.PageMinSpace)) && page.NumberOfEntries >= minKeys) { return(null); // above space/keys thresholds } Debug.Assert(parentPage.NumberOfEntries >= 2); // if we have less than 2 entries in the parent, the tree is invalid var sibling = SetupMoveOrMerge(page, parentPage); Debug.Assert(sibling.PageNumber != page.PageNumber); if (page.Flags != sibling.Flags) { return(null); } minKeys = sibling.IsBranch ? 2 : 1; // branch must have at least 2 keys if (sibling.UseMoreSizeThan(_tx.DataPager.PageMinSpace) && sibling.NumberOfEntries > minKeys) { _cursor.Pop(); // neighbor is over the min size and has enough key, can move just one key to the current page if (page.IsBranch) { MoveBranchNode(parentPage, sibling, page); } else { MoveLeafNode(parentPage, sibling, page); } return(parentPage); } if (page.LastSearchPosition == 0) // this is the right page, merge left { if (TryMergePages(parentPage, sibling, page) == false) { return(null); } } else // this is the left page, merge right { if (TryMergePages(parentPage, page, sibling) == false) { return(null); } } _cursor.Pop(); return(parentPage); }
public Page Execute(Page page) { _tree.ClearRecentFoundPages(); if (_cursor.PageCount <= 1) // the root page { RebalanceRoot(page); return null; } var parentPage = _tx.ModifyPage(_cursor.ParentPage.PageNumber, _tree, _cursor.ParentPage); _cursor.Update(_cursor.Pages.First.Next, parentPage); if (page.NumberOfEntries == 0) // empty page, just delete it and fixup parent { // need to change the implicit left page if (parentPage.LastSearchPosition == 0 && parentPage.NumberOfEntries > 2) { var newImplicit = parentPage.GetNode(1)->PageNumber; parentPage.RemoveNode(0); parentPage.ChangeImplicitRefPageNode(newImplicit); } else // will be set to rights by the next rebalance call { parentPage.RemoveNode(parentPage.LastSearchPositionOrLastEntry); } _tx.FreePage(page.PageNumber); _cursor.Pop(); return parentPage; } if (page.IsBranch && page.NumberOfEntries == 1) { RemoveBranchWithOneEntry(page, parentPage); _cursor.Pop(); return parentPage; } var minKeys = page.IsBranch ? 2 : 1; if ((page.UseMoreSizeThan(_tx.DataPager.PageMinSpace)) && page.NumberOfEntries >= minKeys) return null; // above space/keys thresholds Debug.Assert(parentPage.NumberOfEntries >= 2); // if we have less than 2 entries in the parent, the tree is invalid var sibling = SetupMoveOrMerge(page, parentPage); Debug.Assert(sibling.PageNumber != page.PageNumber); if (page.Flags != sibling.Flags) return null; minKeys = sibling.IsBranch ? 2 : 1; // branch must have at least 2 keys if (sibling.UseMoreSizeThan(_tx.DataPager.PageMinSpace) && sibling.NumberOfEntries > minKeys) { _cursor.Pop(); // neighbor is over the min size and has enough key, can move just one key to the current page if (page.IsBranch) MoveBranchNode(parentPage, sibling, page); else MoveLeafNode(parentPage, sibling, page); return parentPage; } if (page.LastSearchPosition == 0) // this is the right page, merge left { if (TryMergePages(parentPage, sibling, page) == false) return null; } else // this is the left page, merge right { if (TryMergePages(parentPage, page, sibling) == false) return null; } _cursor.Pop(); return parentPage; }