コード例 #1
0
ファイル: AbstractBTree.cs プロジェクト: mrdotnet/NDatabase
        public virtual IKeyAndValue GetBiggest(IBTreeNode node, bool delete)
        {
            var lastKeyIndex   = node.GetNbKeys() - 1;
            var lastChildIndex = node.GetNbChildren() - 1;

            if (lastChildIndex > lastKeyIndex)
            {
                var child = node.GetChildAt(lastChildIndex, true);

                if (child.GetNbKeys() == _degree - 1)
                {
                    node = PrepareForDelete(node, child, lastChildIndex);
                }

                lastChildIndex = node.GetNbChildren() - 1;
                child          = node.GetChildAt(lastChildIndex, true);
                return(GetBiggest(child, delete));
            }

            var kav = node.GetKeyAndValueAt(lastKeyIndex);

            if (delete)
            {
                node.DeleteKeyAndValueAt(lastKeyIndex, false);
                _persister.SaveNode(node);
            }

            return(kav);
        }
コード例 #2
0
        /// <summary>
        ///   Can only merge node without intersection =&gt; the greater key of this must be smaller than the smallest key of the node
        /// </summary>
        public virtual void MergeWith(IBTreeNode node)
        {
            BTreeValidator.ValidateNode(this);
            BTreeValidator.ValidateNode(node);

            CheckIfCanMergeWith(node);

            var j = NbKeys;

            for (var i = 0; i < node.GetNbKeys(); i++)
            {
                SetKeyAndValueAt(node.GetKeyAt(i), node.GetValueAsObjectAt(i), j, false, false);
                SetChildAt(node, i, j, false);
                j++;
            }

            // in this, we have to take the last child
            if (node.GetNbChildren() > node.GetNbKeys())
            {
                SetChildAt(node, node.GetNbChildren() - 1, j, true);
            }

            NbKeys     += node.GetNbKeys();
            NbChildren += node.GetNbChildren();
            BTreeValidator.ValidateNode(this);
        }
コード例 #3
0
ファイル: BTreeValidator.cs プロジェクト: danfma/NDB
        public static void ValidateNode(IBTreeNode node)
        {
            if (!OdbConfiguration.IsBTreeValidationEnabled())
                return;

            var nbKeys = node.GetNbKeys();
            if (node.HasParent() && nbKeys < node.GetDegree() - 1)
            {
                var degree = (node.GetDegree() - 1).ToString();
                throw new BTreeNodeValidationException("Node with less than " + degree + " keys");
            }

            var maxNbKeys = node.GetDegree() * 2 - 1;
            var nbChildren = node.GetNbChildren();
            var maxNbChildren = node.GetDegree() * 2;

            if (nbChildren != 0 && nbKeys == 0)
                throw new BTreeNodeValidationException("Node with no key but with children : " + node);

            for (var i = 0; i < nbKeys; i++)
            {
                if (node.GetKeyAndValueAt(i) == null)
                {
                    var keyIndex = i.ToString();
                    throw new BTreeNodeValidationException("Null key at " + keyIndex + " on node " + node);
                }

                CheckValuesOfChild(node.GetKeyAndValueAt(i), node.GetChildAt(i, false));
            }

            for (var i = nbKeys; i < maxNbKeys; i++)
            {
                if (node.GetKeyAndValueAt(i) != null)
                    throw new BTreeNodeValidationException(string.Concat("Not Null key at ", i.ToString(), " on node " + node));
            }

            IBTreeNode previousNode = null;

            for (var i = 0; i < nbChildren; i++)
            {
                if (node.GetChildAt(i, false) == null)
                    throw new BTreeNodeValidationException(string.Concat("Null child at index ", i.ToString(), " on node " + node));

                if (previousNode != null && previousNode == node.GetChildAt(i, false))
                    throw new BTreeNodeValidationException(string.Concat("Two equals children at index ", i.ToString(), " : " + previousNode));

                previousNode = node.GetChildAt(i, false);
            }

            for (var i = nbChildren; i < maxNbChildren; i++)
            {
                if (node.GetChildAt(i, false) != null)
                    throw new BTreeNodeValidationException(string.Concat("Not Null child at ", i.ToString(), " on node " + node));
            }
        }
コード例 #4
0
ファイル: BTreeDisplay.cs プロジェクト: Sinoprise/NDatabase
        private void BuildDisplay(IBTreeNode node, int currentHeight, object parentId, bool withIds)
        {
            if (currentHeight > _lines.Length - 1)
            {
                return;
            }

            // get string buffer of this line
            var line = _lines[currentHeight];

            if (withIds)
            {
                line.Append(node.GetId()).Append(":[");
            }
            else
            {
                line.Append("[");
            }

            for (var i = 0; i < node.GetNbKeys(); i++)
            {
                if (i > 0)
                {
                    line.Append(" , ");
                }

                var keyAndValue = node.GetKeyAndValueAt(i);
                line.Append(keyAndValue.GetKey());
            }

            if (withIds)
            {
                line.Append("]:").Append(node.GetParentId()).Append("/").Append(parentId).Append("    ");
            }
            else
            {
                line.Append("]  ");
            }

            for (var i = 0; i < node.GetNbChildren(); i++)
            {
                var child = node.GetChildAt(i, false);

                if (child != null)
                {
                    BuildDisplay(child, currentHeight + 1, node.GetId(), withIds);
                }
                else
                {
                    _lines[currentHeight + 1].Append(string.Concat("[Child {0} null!] ", (i + 1).ToString()));
                }
            }
        }
コード例 #5
0
        private static int IndexOfChild(IBTreeNode parent, IBTreeNode child)
        {
            for (var i = 0; i < parent.GetNbChildren(); i++)
            {
                if (parent.GetChildAt(i, true).GetId().Equals(child.GetId()))
                {
                    return(i);
                }
            }

            var errorMessage = string.Format("parent {0} does not have the specified child : {1}", parent, child);

            throw new OdbRuntimeException(NDatabaseError.InternalError.AddParameter(errorMessage));
        }
コード例 #6
0
ファイル: BTreeValidator.cs プロジェクト: danfma/NDB
        public static void CheckDuplicateChildren(IBTreeNode node1, IBTreeNode node2)
        {
            if (!OdbConfiguration.IsBTreeValidationEnabled())
                return;

            for (var i = 0; i < node1.GetNbChildren(); i++)
            {
                var child1 = node1.GetChildAt(i, true);

                for (var j = 0; j < node2.GetNbChildren(); j++)
                {
                    if (child1 == node2.GetChildAt(j, true))
                        throw new BTreeNodeValidationException("Duplicated node : " + child1);
                }
            }
        }
コード例 #7
0
        public static void CheckDuplicateChildren(IBTreeNode node1, IBTreeNode node2)
        {
            if (!OdbConfiguration.IsBTreeValidationEnabled())
            {
                return;
            }

            for (int i = 0; i < node1.GetNbChildren(); i++)
            {
                IBTreeNode child1 = node1.GetChildAt(i, true);

                for (int j = 0; j < node2.GetNbChildren(); j++)
                {
                    if (child1 == node2.GetChildAt(j, true))
                    {
                        throw new BTreeNodeValidationException("Duplicated node : " + child1);
                    }
                }
            }
        }
コード例 #8
0
ファイル: BTreeDisplay.cs プロジェクト: danfma/NDB
        private void BuildDisplay(IBTreeNode node, int currentHeight, object parentId, bool withIds)
        {
            if (currentHeight > _lines.Length - 1)
                return;

            // get string buffer of this line
            var line = _lines[currentHeight];
            if (withIds)
                line.Append(node.GetId()).Append(":[");
            else
                line.Append("[");

            for (var i = 0; i < node.GetNbKeys(); i++)
            {
                if (i > 0)
                    line.Append(" , ");

                var keyAndValue = node.GetKeyAndValueAt(i);
                line.Append(keyAndValue.GetKey());
            }

            if (withIds)
                line.Append("]:").Append(node.GetParentId()).Append("/").Append(parentId).Append("    ");
            else
                line.Append("]  ");

            for (var i = 0; i < node.GetNbChildren(); i++)
            {
                var child = node.GetChildAt(i, false);

                if (child != null)
                    BuildDisplay(child, currentHeight + 1, node.GetId(), withIds);
                else
                    _lines[currentHeight + 1].Append(string.Concat("[Child {0} null!] ", (i + 1).ToString()));
            }
        }
コード例 #9
0
ファイル: AbstractBTree.cs プロジェクト: mrdotnet/NDatabase
        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");
        }
コード例 #10
0
        public static void ValidateNode(IBTreeNode node)
        {
            if (!OdbConfiguration.IsBTreeValidationEnabled())
            {
                return;
            }

            int nbKeys = node.GetNbKeys();

            if (node.HasParent() && nbKeys < node.GetDegree() - 1)
            {
                string degree = (node.GetDegree() - 1).ToString();
                throw new BTreeNodeValidationException("Node with less than " + degree + " keys");
            }

            int maxNbKeys     = node.GetDegree() * 2 - 1;
            int nbChildren    = node.GetNbChildren();
            int maxNbChildren = node.GetDegree() * 2;

            if (nbChildren != 0 && nbKeys == 0)
            {
                throw new BTreeNodeValidationException("Node with no key but with children : " + node);
            }

            for (int i = 0; i < nbKeys; i++)
            {
                if (node.GetKeyAndValueAt(i) == null)
                {
                    string keyIndex = i.ToString();
                    throw new BTreeNodeValidationException("Null key at " + keyIndex + " on node " + node);
                }

                CheckValuesOfChild(node.GetKeyAndValueAt(i), node.GetChildAt(i, false));
            }

            for (int i = nbKeys; i < maxNbKeys; i++)
            {
                if (node.GetKeyAndValueAt(i) != null)
                {
                    throw new BTreeNodeValidationException(string.Concat("Not Null key at ", i.ToString(),
                                                                         " on node " + node));
                }
            }

            IBTreeNode previousNode = null;

            for (int i = 0; i < nbChildren; i++)
            {
                if (node.GetChildAt(i, false) == null)
                {
                    throw new BTreeNodeValidationException(string.Concat("Null child at index ", i.ToString(),
                                                                         " on node " + node));
                }

                if (previousNode != null && previousNode == node.GetChildAt(i, false))
                {
                    throw new BTreeNodeValidationException(string.Concat("Two equals children at index ", i.ToString(),
                                                                         " : " + previousNode));
                }

                previousNode = node.GetChildAt(i, false);
            }

            for (int i = nbChildren; i < maxNbChildren; i++)
            {
                if (node.GetChildAt(i, false) != null)
                {
                    throw new BTreeNodeValidationException(string.Concat("Not Null child at ", i.ToString(),
                                                                         " on node " + node));
                }
            }
        }
コード例 #11
0
        /// <summary>
        ///   Can only merge node without intersection =&gt; the greater key of this must be smaller than the smallest key of the node
        /// </summary>
        public virtual void MergeWith(IBTreeNode node)
        {
            BTreeValidator.ValidateNode(this);
            BTreeValidator.ValidateNode(node);

            CheckIfCanMergeWith(node);

            var j = NbKeys;
            for (var i = 0; i < node.GetNbKeys(); i++)
            {
                SetKeyAndValueAt(node.GetKeyAt(i), node.GetValueAsObjectAt(i), j, false, false);
                SetChildAt(node, i, j, false);
                j++;
            }

            // in this, we have to take the last child
            if (node.GetNbChildren() > node.GetNbKeys())
                SetChildAt(node, node.GetNbChildren() - 1, j, true);

            NbKeys += node.GetNbKeys();
            NbChildren += node.GetNbChildren();
            BTreeValidator.ValidateNode(this);
        }