Exemple #1
0
        private bool RedistributeBranchElements(TreeBranch branch, int childIndex, TreeBranch child)
        {
            // We distribute the nodes in the child branch with the branch
            // immediately to the right.  If that's not possible, then we distribute
            // with the left.

            // If branch has only a single value, return immediately
            int branchSize = branch.ChildCount;

            if (branchSize == 1)
            {
                return(false);
            }

            int        leftI, rightI;
            TreeBranch left, right;

            if (childIndex < branchSize - 1)
            {
                // Distribute with the right
                leftI  = childIndex;
                rightI = childIndex + 1;
                left   = child;
                right  = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex + 1)));
                branch.SetChild(right.Id, childIndex + 1);
            }
            else
            {
                // Distribute with the left
                leftI  = childIndex - 1;
                rightI = childIndex;
                left   = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex - 1)));
                right  = child;
                branch.SetChild(left.Id, childIndex - 1);
            }

            // Get the mid value key reference
            Key midKey = branch.GetKey(rightI);

            // Perform the merge,
            Key newMidKey = left.Merge(right, midKey);

            // Reset the leaf element count
            branch.SetChildLeafElementCount(left.LeafElementCount, leftI);
            branch.SetChildLeafElementCount(right.LeafElementCount, rightI);

            // If after the merge the right branch is empty, we need to remove it
            if (right.IsEmpty)
            {
                // Delete the node
                DeleteNode(right.Id);
                // And remove it from the branch,
                branch.RemoveChild(rightI);
                return(true);
            }

            // Otherwise set the key reference
            branch.SetKeyToLeft(newMidKey, rightI);
            return(false);
        }
Exemple #2
0
        public void DeleteLeaf(Key key)
        {
            // Set up the state
            StackFrame frame          = StackEnd(0);
            NodeId     thisRef        = frame.NodeId;
            TreeBranch branchNode     = null;
            int        deleteNodeSize = -1;
            Key        leftKey        = null;

            // Walk back through the rest of the stack
            int sz = FrameCount;

            for (int i = 1; i < sz; ++i)
            {
                // Find the child_i for the child
                // This is the child_i of the child in the current branch
                int childIndex = frame.ChildIndex;

                // Move the stack frame,
                frame = StackEnd(i);

                NodeId childId = thisRef;
                thisRef = frame.NodeId;
                TreeBranch childBranch = branchNode;
                branchNode = (TreeBranch)UnfreezeNode(FetchNode(thisRef));

                if (deleteNodeSize == -1)
                {
                    deleteNodeSize =
                        (int)branchNode.GetChildLeafElementCount(childIndex);
                }

                // If the child branch is empty,
                if (childBranch == null || childBranch.IsEmpty)
                {
                    // Delete the reference to it,
                    if (childIndex == 0 && branchNode.ChildCount > 1)
                    {
                        leftKey = branchNode.GetKey(1);
                    }
                    branchNode.RemoveChild(childIndex);
                    // Delete the child branch,
                    DeleteNode(childId);
                }
                // Not empty,
                else
                {
                    // Replace with the new child node reference
                    branchNode.SetChild(childBranch.Id, childIndex);
                    // Set the element count
                    long newChildSize =
                        branchNode.GetChildLeafElementCount(childIndex) -
                        deleteNodeSize;
                    branchNode.SetChildLeafElementCount(newChildSize, childIndex);
                    // Can we set the left key reference?
                    if (childIndex > 0 && leftKey != null)
                    {
                        branchNode.SetKeyToLeft(leftKey, childIndex);
                        leftKey = null;
                    }

                    // Has the size of the child reached the lower threshold?
                    if (childBranch.ChildCount <= 2)
                    {
                        // If it has, we need to redistribute the children,
                        RedistributeBranchElements(branchNode, childIndex, childBranch);
                    }
                }
            }

            // Finally, set the root node
            // If the branch node is a single element, we set the root as the child,
            if (branchNode.ChildCount == 1)
            {
                // This shrinks the height of the tree,
                RootNodeId = branchNode.GetChild(0);
                DeleteNode(branchNode.Id);
                if (TreeHeight != -1)
                {
                    TreeHeight = TreeHeight - 1;
                }
            }
            else
            {
                // Otherwise, we set the branch node.
                RootNodeId = branchNode.Id;
            }

            // Reset the object
            Reset();
        }
Exemple #3
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);
        }
        private bool RedistributeBranchElements(TreeBranch branch, int childIndex, TreeBranch child)
        {
            // We distribute the nodes in the child branch with the branch
            // immediately to the right.  If that's not possible, then we distribute
            // with the left.

            // If branch has only a single value, return immediately
            int branchSize = branch.ChildCount;
            if (branchSize == 1) {
                return false;
            }

            int leftI, rightI;
            TreeBranch left, right;
            if (childIndex < branchSize - 1) {
                // Distribute with the right
                leftI = childIndex;
                rightI = childIndex + 1;
                left = child;
                right = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex + 1)));
                branch.SetChild(right.Id, childIndex + 1);
            } else {
                // Distribute with the left
                leftI = childIndex - 1;
                rightI = childIndex;
                left = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex - 1)));
                right = child;
                branch.SetChild(left.Id, childIndex - 1);
            }

            // Get the mid value key reference
            Key midKey = branch.GetKey(rightI);

            // Perform the merge,
            Key newMidKey = left.Merge(right, midKey);
            // Reset the leaf element count
            branch.SetChildLeafElementCount(left.LeafElementCount, leftI);
            branch.SetChildLeafElementCount(right.LeafElementCount, rightI);

            // If after the merge the right branch is empty, we need to remove it
            if (right.IsEmpty) {
                // Delete the node
                DeleteNode(right.Id);
                // And remove it from the branch,
                branch.RemoveChild(rightI);
                return true;
            }

            // Otherwise set the key reference
            branch.SetKeyToLeft(newMidKey, rightI);
            return false;
        }