public byte *Execute() { using (DisableFreeSpaceUsageIfSplittingRootTree()) { TreePage rightPage = _tree.NewPage(_page.TreeFlags, _page.PageNumber); if (_cursor.PageCount == 0) // we need to do a root split { TreePage newRootPage = _tree.NewPage(TreePageFlags.Branch, _page.PageNumber); _cursor.Push(newRootPage); _tree.State.RootPageNumber = newRootPage.PageNumber; _tree.State.Depth++; // now add implicit left page newRootPage.AddPageRefNode(0, Slices.BeforeAllKeys, _page.PageNumber); _parentPage = newRootPage; _parentPage.LastSearchPosition++; } else { // we already popped the page, so the current one on the stack is the parent of the page _parentPage = _tree.ModifyPage(_cursor.CurrentPage); _cursor.Update(_cursor.Pages, _parentPage); } if (_page.IsLeaf) { _tree.ClearPagesCache(); } if (_page.IsCompressed) { _pageDecompressed = _tree.DecompressPage(_page); _pageDecompressed.Search(_tx, _newKey); if (_pageDecompressed.LastMatch == 0) { // we are going to insert the value in a bit, but it might have // been in the compressed portion and not removed by the calling // code _tree.RemoveLeafNode(_pageDecompressed); } _page = _pageDecompressed; } using (_pageDecompressed) { if (_page.LastSearchPosition >= _page.NumberOfEntries) { var pos = OptimizedOnlyMoveNewValueToTheRightPage(rightPage); RecompressPageIfNeeded(wasModified: false); return(pos); } return(SplitPageInHalf(rightPage)); } } }
private void HandleTombstone(DecompressedLeafPage decompressedPage, Slice nodeKey, DecompressionUsage usage) { decompressedPage.Search(_llt, nodeKey); if (decompressedPage.LastMatch != 0) { return; } var node = decompressedPage.GetNode(decompressedPage.LastSearchPosition); if (usage == DecompressionUsage.Write) { State.NumberOfEntries--; if (node->Flags == TreeNodeFlags.PageRef) { var overflowPage = GetReadOnlyTreePage(node->PageNumber); FreePage(overflowPage); } } decompressedPage.RemoveNode(decompressedPage.LastSearchPosition); }
public byte *Execute() { using (DisableFreeSpaceUsageIfSplittingRootTree()) { TreePage rightPage = _tree.NewPage(_page.TreeFlags, 1); if (_cursor.PageCount == 0) // we need to do a root split { TreePage newRootPage = _tree.NewPage(TreePageFlags.Branch, 1); _cursor.Push(newRootPage); _tree.State.RootPageNumber = newRootPage.PageNumber; _tree.State.Depth++; // now add implicit left page newRootPage.AddPageRefNode(0, Slices.BeforeAllKeys, _page.PageNumber); _parentPage = newRootPage; _parentPage.LastSearchPosition++; } else { // we already popped the page, so the current one on the stack is the parent of the page _parentPage = _tree.ModifyPage(_cursor.CurrentPage); _cursor.Update(_cursor.Pages.First, _parentPage); } if (_page.IsLeaf) { _tree.ClearPagesCache(); } if (_page.IsCompressed) { _pageDecompressed = _tree.DecompressPage(_page); _pageDecompressed.Search(_tx, _newKey); _page = _pageDecompressed; } using (_pageDecompressed) { if (_page.LastSearchPosition >= _page.NumberOfEntries) { // when we get a split at the end of the page, we take that as a hint that the user is doing // sequential inserts, at that point, we are going to keep the current page as is and create a new // page, this will allow us to do minimal amount of work to get the best density TreePage branchOfSeparator; byte *pos; if (_page.IsBranch) { if (_page.NumberOfEntries > 2) { // here we steal the last entry from the current page so we maintain the implicit null left entry TreeNodeHeader *node = _page.GetNode(_page.NumberOfEntries - 1); Debug.Assert(node->Flags == TreeNodeFlags.PageRef); rightPage.AddPageRefNode(0, Slices.BeforeAllKeys, node->PageNumber); pos = AddNodeToPage(rightPage, 1); Slice separatorKey; using (TreeNodeHeader.ToSlicePtr(_tx.Allocator, node, out separatorKey)) { AddSeparatorToParentPage(rightPage.PageNumber, separatorKey, out branchOfSeparator); } _page.RemoveNode(_page.NumberOfEntries - 1); } else { _tree.FreePage(rightPage); // return the unnecessary right page pos = AddSeparatorToParentPage(_pageNumber, _newKey, out branchOfSeparator); if (_cursor.CurrentPage.PageNumber != branchOfSeparator.PageNumber) { _cursor.Push(branchOfSeparator); } return(pos); } } else { AddSeparatorToParentPage(rightPage.PageNumber, _newKey, out branchOfSeparator); pos = AddNodeToPage(rightPage, 0); } _cursor.Push(rightPage); return(pos); } return(SplitPageInHalf(rightPage)); } } }