예제 #1
0
        // Commented by Olivier 05/11/2007
        // persister.flush();

        /// <summary>
        ///   <pre>1 take median element
        ///     2 insert the median in the parent  (shifting necessary elements)
        ///     3 create a new node with right part elements (moving keys and values and children)
        ///     4 set this new node as a child of parent</pre>
        /// </summary>
        public virtual void Split(IBTreeNode parent, IBTreeNode node2Split, int childIndex)
        {
            // BTreeValidator.validateNode(parent, parent == root);
            // BTreeValidator.validateNode(node2Split, false);
            // 1
            var medianValue = node2Split.GetMedian();

            // 2
            parent.SetKeyAndValueAt(medianValue, childIndex, true, true);
            // 3
            var rightPartTreeNode = node2Split.ExtractRightPart();

            // 4
            parent.SetChildAt(rightPartTreeNode, childIndex + 1);
            parent.SetChildAt(node2Split, childIndex);
            parent.IncrementNbChildren();
            _persister.SaveNode(parent);
            _persister.SaveNode(rightPartTreeNode);
            _persister.SaveNode(node2Split);

            if (!OdbConfiguration.IsBTreeValidationEnabled())
            {
                return;
            }

            BTreeValidator.ValidateNode(parent, parent == _root);
            BTreeValidator.ValidateNode(rightPartTreeNode, false);
            BTreeValidator.ValidateNode(node2Split, false);
        }
예제 #2
0
        private IBTreeNode PrepareForDelete(IBTreeNode parent, IBTreeNode child, int childIndex)
        {
            BTreeValidator.ValidateNode(parent);
            BTreeValidator.ValidateNode(child);

            // case 3a
            IBTreeNode leftSibling  = null;
            IBTreeNode rightSibling = null;

            if (childIndex > 0 && parent.GetNbChildren() > 0)
            {
                leftSibling = parent.GetChildAt(childIndex - 1, false);
            }

            if (childIndex < parent.GetNbChildren() - 1)
            {
                rightSibling = parent.GetChildAt(childIndex + 1, false);
            }

            // case 3a left
            if (leftSibling != null && leftSibling.GetNbKeys() >= _degree)
            {
                var elementToMoveDown = parent.GetKeyAndValueAt(childIndex - 1);
                var elementToMoveUp   = leftSibling.GetLastKeyAndValue();

                parent.SetKeyAndValueAt(elementToMoveUp, childIndex - 1);
                child.InsertKeyAndValue(elementToMoveDown.GetKey(), elementToMoveDown.GetValue());

                if (leftSibling.GetNbChildren() > leftSibling.GetNbKeys())
                {
                    // Take the last child of the left sibling and set it the
                    // first child of the 'child' (incoming parameter)
                    // child.setChildAt(leftSibling.getChildAt(leftSibling.getNbChildren()
                    // - 1, true), 0);
                    child.SetChildAt(leftSibling, leftSibling.GetNbChildren() - 1, 0, true);
                    child.IncrementNbChildren();
                }

                leftSibling.DeleteKeyAndValueAt(leftSibling.GetNbKeys() - 1, false);

                if (!leftSibling.IsLeaf())
                {
                    leftSibling.DeleteChildAt(leftSibling.GetNbChildren() - 1);
                }

                _persister.SaveNode(parent);
                _persister.SaveNode(child);
                _persister.SaveNode(leftSibling);

                if (OdbConfiguration.IsBTreeValidationEnabled())
                {
                    BTreeValidator.ValidateNode(parent, parent == _root);
                    BTreeValidator.ValidateNode(child, false);
                    BTreeValidator.ValidateNode(leftSibling, false);
                    BTreeValidator.CheckDuplicateChildren(leftSibling, child);
                }

                return(parent);
            }

            // case 3a right
            if (rightSibling != null && rightSibling.GetNbKeys() >= _degree)
            {
                var elementToMoveDown = parent.GetKeyAndValueAt(childIndex);
                var elementToMoveUp   = rightSibling.GetKeyAndValueAt(0);

                parent.SetKeyAndValueAt(elementToMoveUp, childIndex);
                child.InsertKeyAndValue(elementToMoveDown.GetKey(), elementToMoveDown.GetValue());

                if (rightSibling.GetNbChildren() > 0)
                {
                    // Take the first child of the right sibling and set it the
                    // last child of the 'child' (incoming parameter)
                    child.SetChildAt(rightSibling, 0, child.GetNbChildren(), true);
                    child.IncrementNbChildren();
                }

                rightSibling.DeleteKeyAndValueAt(0, true);
                _persister.SaveNode(parent);
                _persister.SaveNode(child);
                _persister.SaveNode(rightSibling);

                if (OdbConfiguration.IsBTreeValidationEnabled())
                {
                    BTreeValidator.ValidateNode(parent, parent == _root);
                    BTreeValidator.ValidateNode(child, false);
                    BTreeValidator.ValidateNode(rightSibling, false);
                    BTreeValidator.CheckDuplicateChildren(rightSibling, child);
                }

                return(parent);
            }

            // case 3b
            var isCase3B = (leftSibling != null && leftSibling.GetNbKeys() == _degree - 1) ||
                           (rightSibling != null && rightSibling.GetNbKeys() >= _degree - 1);

            var parentWasSetToNull = false;

            if (isCase3B)
            {
                // choose left sibling to execute merge
                if (leftSibling != null)
                {
                    var elementToMoveDown = parent.GetKeyAndValueAt(childIndex - 1);
                    leftSibling.InsertKeyAndValue(elementToMoveDown.GetKey(), elementToMoveDown.GetValue());
                    leftSibling.MergeWith(child);
                    parent.DeleteKeyAndValueAt(childIndex - 1, true);

                    if (parent.GetNbKeys() == 0)
                    {
                        // this is the root
                        if (!parent.HasParent())
                        {
                            _root = leftSibling;
                            _root.SetParent(null);
                            _height--;
                            parentWasSetToNull = true;
                        }
                        else
                        {
                            const string errorMessage = "Unexpected empty node that is node the root!";
                            throw new BTreeNodeValidationException(errorMessage);
                        }
                    }
                    else
                    {
                        parent.SetChildAt(leftSibling, childIndex - 1);
                    }

                    if (parentWasSetToNull)
                    {
                        _persister.DeleteNode(parent);
                    }
                    else
                    {
                        _persister.SaveNode(parent);
                        BTreeValidator.ValidateNode(parent, parent == _root);
                    }

                    // child was merged with another node it must be deleted
                    _persister.DeleteNode(child);
                    _persister.SaveNode(leftSibling);

                    // Validator.validateNode(child, child == root);
                    BTreeValidator.ValidateNode(leftSibling, leftSibling == _root);

                    // Validator.checkDuplicateChildren(leftSibling, child);
                    return(parentWasSetToNull
                               ? _root
                               : parent);
                }

                // choose right sibling to execute merge
                {
                    var elementToMoveDown = parent.GetKeyAndValueAt(childIndex);
                    child.InsertKeyAndValue(elementToMoveDown.GetKey(), elementToMoveDown.GetValue());
                    child.MergeWith(rightSibling);
                    parent.DeleteKeyAndValueAt(childIndex, true);
                    if (parent.GetNbKeys() == 0)
                    {
                        // this is the root
                        if (!parent.HasParent())
                        {
                            _root = child;
                            _root.SetParent(null);
                            _height--;
                            parentWasSetToNull = true;
                        }
                        else
                        {
                            throw new BTreeNodeValidationException("Unexpected empty root node!");
                        }
                    }
                    else
                    {
                        parent.SetChildAt(child, childIndex);
                    }

                    if (parentWasSetToNull)
                    {
                        _persister.DeleteNode(parent);
                    }
                    else
                    {
                        _persister.SaveNode(parent);
                        BTreeValidator.ValidateNode(parent, parent == _root);
                    }

                    _persister.DeleteNode(rightSibling);
                    _persister.SaveNode(child);
                    BTreeValidator.ValidateNode(child, child == _root);
                    // Validator.validateNode(rightSibling, rightSibling ==
                    // root);
                    // Validator.checkDuplicateChildren(rightSibling, child);
                    return(parentWasSetToNull
                               ? _root
                               : parent);
                }
            }

            throw new BTreeNodeValidationException("Unexpected case in executing prepare for delete");
        }