public virtual IKeyAndValue GetSmallest(IBTreeNode node, bool delete) { if (!node.IsLeaf()) { var childTreeNode = node.GetChildAt(0, true); if (childTreeNode.GetNbKeys() == _degree - 1) { node = PrepareForDelete(node, childTreeNode, 0); } childTreeNode = node.GetChildAt(0, true); return(GetSmallest(childTreeNode, delete)); } var keyAndValue = node.GetKeyAndValueAt(0); if (delete) { node.DeleteKeyAndValueAt(0, true); _persister.SaveNode(node); } return(keyAndValue); }
private T NextAsc() { // Try to go down till a leaf while (!CurrentNode.IsLeaf()) { CurrentNode = CurrentNode.GetChildAt(_currentKeyIndex, true); _currentKeyIndex = 0; } // If leaf has more keys if (_currentKeyIndex < CurrentNode.GetNbKeys()) { NbReturnedElements++; var nodeValue = GetValueAt(CurrentNode, _currentKeyIndex); _currentKeyIndex++; return((T)nodeValue); } // else go up till a node with keys while (_currentKeyIndex >= CurrentNode.GetNbKeys()) { var child = CurrentNode; CurrentNode = CurrentNode.GetParent(); _currentKeyIndex = IndexOfChild(CurrentNode, child); } NbReturnedElements++; var value = GetValueAt(CurrentNode, _currentKeyIndex); _currentKeyIndex++; return((T)value); }
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); }
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)); } }
public override void SetChildAt(IBTreeNode node, int childIndex, int index, bool throwExceptionIfDoesNotExist) { var childTreeNode = node.GetChildAt(childIndex, throwExceptionIfDoesNotExist); _children[index] = childTreeNode; if (childTreeNode != null) childTreeNode.SetParent(this); }
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())); } } }
public override void SetChildAt(IBTreeNode node, int childIndex, int index, bool throwExceptionIfDoesNotExist) { var childTreeNode = node.GetChildAt(childIndex, throwExceptionIfDoesNotExist); _children[index] = childTreeNode; if (childTreeNode != null) { childTreeNode.SetParent(this); } }
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)); }
private void InsertNonFull(IBTreeNode node, IComparable key, object value) { if (node.IsLeaf()) { node.InsertKeyAndValue(key, value); _persister.SaveNode(node); return; } var position = node.GetPositionOfKey(key); // return an index starting // from 1 instead of 0 var realPosition = -position - 1; // If position is positive, the key must be inserted in this node if (position >= 0) { node.InsertKeyAndValue(key, value); _persister.SaveNode(node); return; } // descend var nodeToDescend = node.GetChildAt(realPosition, true); if (nodeToDescend.IsFull()) { Split(node, nodeToDescend, realPosition); if (node.GetKeyAt(realPosition).CompareTo(key) < 0) { nodeToDescend = node.GetChildAt(realPosition + 1, true); } } InsertNonFull(nodeToDescend, key, value); }
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); } } }
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); } } } }
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())); } }
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"); }
/// <summary> /// Returns the value of the deleted key /// </summary> /// <param name="node"> </param> /// <param name="keyAndValue"> </param> /// <returns> </returns> /// <exception cref="System.Exception">System.Exception</exception> private object InternalDelete(IBTreeNode node, IKeyAndValue keyAndValue) { var positionOfKey = node.GetPositionOfKey(keyAndValue.GetKey()); var keyIsHere = positionOfKey > 0; if (node.IsLeaf()) { if (keyIsHere) { var deletedValue = node.DeleteKeyForLeafNode(keyAndValue); GetPersister().SaveNode(node); return(deletedValue); } // key does not exist return(null); } int realPosition; if (!keyIsHere) { // descend realPosition = -positionOfKey - 1; var childTreeNode = node.GetChildAt(realPosition, true); if (childTreeNode.GetNbKeys() == _degree - 1) { node = PrepareForDelete(node, childTreeNode, realPosition); return(InternalDelete(node, keyAndValue)); } return(InternalDelete(childTreeNode, keyAndValue)); } // Here,the node is not a leaf and contains the key realPosition = positionOfKey - 1; var currentKey = node.GetKeyAt(realPosition); var currentValue = node.GetValueAsObjectAt(realPosition); // case 2a var leftNode = node.GetChildAt(realPosition, true); if (leftNode.GetNbKeys() >= _degree) { var prevKeyAndValue = GetBiggest(leftNode, true); node.SetKeyAndValueAt(prevKeyAndValue, realPosition); BTreeValidator.ValidateNode(node, node == _root); GetPersister().SaveNode(node); return(currentValue); } // case 2b var rightNode = node.GetChildAt(realPosition + 1, true); if (rightNode.GetNbKeys() >= _degree) { var nextKeyAndValue = GetSmallest(rightNode, true); node.SetKeyAndValueAt(nextKeyAndValue, realPosition); BTreeValidator.ValidateNode(node, node == _root); GetPersister().SaveNode(node); return(currentValue); } // case 2c // Here, both left and right part have degree-1 keys // remove the element to be deleted from node (shifting left all // right // elements, link to right link does not exist anymore) // insert the key to be deleted in left child and merge the 2 nodes. // rightNode should be deleted // if node is root, then leftNode becomes the new root and node // should be deleted // node.DeleteKeyAndValueAt(realPosition, true); leftNode.InsertKeyAndValue(currentKey, currentValue); leftNode.MergeWith(rightNode); // If node is the root and is empty if (!node.HasParent() && node.GetNbKeys() == 0) { _persister.DeleteNode(node); _root = leftNode; leftNode.SetParent(null); // The height has been decreased. No need to save btree here. // The calling delete method will save it. _height--; } else { node.SetChildAt(leftNode, realPosition); // Node must only be validated if it is not the root BTreeValidator.ValidateNode(node, node == _root); } _persister.DeleteNode(rightNode); BTreeValidator.ValidateNode(leftNode, leftNode == _root); GetPersister().SaveNode(node); GetPersister().SaveNode(leftNode); return(InternalDelete(leftNode, keyAndValue)); }
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)); } } }