Exemplo n.º 1
0
        public void InsertLeaf(Key newLeafKey, TreeLeaf newLeaf, bool before)
        {
            int leafSize = newLeaf.Length;

            if (leafSize <= 0)
            {
                throw new ArgumentException("size <= 0");
            }

            // The current absolute position and key
            Key newKey = newLeafKey;

            // The frame at the end of the stack,
            StackFrame frame = StackEnd(0);

            object[] info;
            object[] rInfo = new object[5];
            Key      leftKey;
            long     curAbsolutePos;

            // If we are inserting the new leaf after,
            if (!before)
            {
                info = new object[] {
                    currentLeaf.Id,
                    (long)currentLeaf.Length,
                    newLeafKey,
                    newLeaf.Id,
                    (long)newLeaf.Length
                };
                leftKey        = null;
                curAbsolutePos = frame.Offset + currentLeaf.Length;
            }
            // Otherwise we are inserting the new leaf before,
            else
            {
                // If before and current_leaf key is different than new_leaf key, we
                // generate an error
                if (!currentLeafKey.Equals(newLeafKey))
                {
                    throw new InvalidOperationException("Can't insert different new key before.");
                }

                info = new Object[] {
                    newLeaf.Id,
                    (long)newLeaf.Length,
                    currentLeafKey,
                    currentLeaf.Id,
                    (long)currentLeaf.Length
                };
                leftKey        = newLeafKey;
                curAbsolutePos = frame.Offset - 1;
            }

            bool insertTwoNodes = true;

            int sz = FrameCount;

            // Walk the stack from the end
            for (int i = 1; i < sz; ++i)
            {
                // child_i is the previous frame's child_i
                int childIndex = frame.ChildIndex;
                frame = StackEnd(i);
                // The child ref of this stack element
                NodeId childId = frame.NodeId;
                // Fetch it
                TreeBranch branch = (TreeBranch)UnfreezeNode(FetchNode(childId));

                // Do we have two nodes to insert into the branch?
                if (insertTwoNodes)
                {
                    TreeBranch insertBranch;
                    int        insertIndex = childIndex;
                    // If the branch is full,
                    if (branch.IsFull)
                    {
                        // Create a new node,
                        TreeBranch leftBranch  = branch;
                        TreeBranch rightBranch = CreateBranch();
                        // Split the branch,
                        Key midpointKey = leftBranch.MidPointKey;
                        // And move half of this branch into the new branch
                        leftBranch.MoveLastHalfInto(rightBranch);
                        // We split so we need to return a split flag,
                        rInfo[0] = leftBranch.Id;
                        rInfo[1] = leftBranch.LeafElementCount;
                        rInfo[2] = midpointKey;
                        rInfo[3] = rightBranch.Id;
                        rInfo[4] = rightBranch.LeafElementCount;
                        // Adjust insert_n and insert_branch
                        if (insertIndex >= leftBranch.ChildCount)
                        {
                            insertIndex -= leftBranch.ChildCount;
                            insertBranch = rightBranch;
                            rInfo[4]     = (long)rInfo[4] + newLeaf.Length;
                            // If insert_n == 0, we change the midpoint value to the left
                            // key value,
                            if (insertIndex == 0 && leftKey != null)
                            {
                                rInfo[2] = leftKey;
                                leftKey  = null;
                            }
                        }
                        else
                        {
                            insertBranch = leftBranch;
                            rInfo[1]     = (long)rInfo[1] + newLeaf.Length;
                        }
                    }
                    // If it's not full,
                    else
                    {
                        insertBranch   = branch;
                        rInfo[0]       = insertBranch.Id;
                        insertTwoNodes = false;
                    }
                    // Insert the two children nodes
                    insertBranch.Insert((NodeId)info[0], (long)info[1],
                                        (Key)info[2],
                                        (NodeId)info[3], (long)info[4],
                                        insertIndex);
                    // Copy r_nfo to nfo
                    for (int p = 0; p < rInfo.Length; ++p)
                    {
                        info[p] = rInfo[p];
                    }

                    // Adjust the left key reference if necessary
                    if (leftKey != null && insertIndex > 0)
                    {
                        insertBranch.SetKeyToLeft(leftKey, insertIndex);
                        leftKey = null;
                    }
                }
                else
                {
                    branch.SetChild((NodeId)info[0], childIndex);
                    info[0] = branch.Id;
                    branch.SetChildLeafElementCount(
                        branch.GetChildLeafElementCount(childIndex) + leafSize, childIndex);

                    // Adjust the left key reference if necessary
                    if (leftKey != null && childIndex > 0)
                    {
                        branch.SetKeyToLeft(leftKey, childIndex);
                        leftKey = null;
                    }
                }
            }             // For all elements in the stack,

            // At the end, if we still have a split then we make a new root and
            // adjust the stack accordingly
            if (insertTwoNodes)
            {
                TreeBranch newRoot = CreateBranch();
                newRoot.Set((NodeId)info[0], (long)info[1],
                            (Key)info[2],
                            (NodeId)info[3], (long)info[4]);
                RootNodeId = newRoot.Id;
                if (TreeHeight != -1)
                {
                    TreeHeight = TreeHeight + 1;
                }
            }
            else
            {
                RootNodeId = (NodeId)info[0];
            }

            // Now reset the position,
            Reset();
            SetupForPosition(newKey, curAbsolutePos);
        }