示例#1
0
        private void MoveBranchNode(TreePage parentPage, TreePage from, TreePage to)
        {
            Debug.Assert(from.IsBranch);

            Slice originalFromKey;

            using (GetActualKey(from, from.LastSearchPositionOrLastEntry, out originalFromKey))
            {
                to.EnsureHasSpaceFor(_tx, originalFromKey, -1);

                var  fromNode = from.GetNode(from.LastSearchPosition);
                long pageNum  = fromNode->PageNumber;

                if (to.LastSearchPosition == 0)
                {
                    // cannot add to left implicit side, adjust by moving the left node
                    // to the right by one, then adding the new one as the left

                    TreeNodeHeader *actualKeyNode;
                    Slice           implicitLeftKey;
                    using (GetActualKey(to, 0, out actualKeyNode, out implicitLeftKey))
                    {
                        var implicitLeftNode = to.GetNode(0);
                        var leftPageNumber   = implicitLeftNode->PageNumber;

                        Slice implicitLeftKeyToInsert;
                        ByteStringContext.ExternalScope?externalScope;

                        if (implicitLeftNode == actualKeyNode)
                        {
                            externalScope = TreeNodeHeader.ToSlicePtr(_tx.Allocator, actualKeyNode, out implicitLeftKeyToInsert);
                        }
                        else
                        {
                            implicitLeftKeyToInsert = implicitLeftKey;
                            externalScope           = null;
                        }

                        to.EnsureHasSpaceFor(_tx, implicitLeftKeyToInsert, -1);
                        to.AddPageRefNode(1, implicitLeftKeyToInsert, leftPageNumber);
                        externalScope?.Dispose();

                        to.ChangeImplicitRefPageNode(pageNum); // setup the new implicit node
                    }
                }
                else
                {
                    to.AddPageRefNode(to.LastSearchPosition, originalFromKey, pageNum);
                }
            }

            if (from.LastSearchPositionOrLastEntry == 0)
            {
                var rightPageNumber = from.GetNode(1)->PageNumber;
                from.RemoveNode(0);                              // remove the original implicit node
                from.ChangeImplicitRefPageNode(rightPageNumber); // setup the new implicit node
                Debug.Assert(from.NumberOfEntries >= 2);
            }
            else
            {
                from.RemoveNode(from.LastSearchPositionOrLastEntry);
            }

            var pos = parentPage.LastSearchPositionOrLastEntry;

            parentPage.RemoveNode(pos);
            Slice newSeparatorKey;
            var   scope = GetActualKey(to, 0, out newSeparatorKey); // get the next smallest key it has now

            try
            {
                var pageNumber = to.PageNumber;
                if (parentPage.GetNode(0)->PageNumber == to.PageNumber)
                {
                    pageNumber = from.PageNumber;
                    scope.Dispose();
                    scope = GetActualKey(from, 0, out newSeparatorKey);
                }

                AddSeparatorToParentPage(to, parentPage, pageNumber, newSeparatorKey, pos);
            }
            finally
            {
                scope.Dispose();
            }
        }