/// <summary> /// Can only merge node without intersection => 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); }
public virtual void Insert(IComparable key, object value) { if (_root.IsFull()) { var newRoot = BuildNode(); var oldRoot = _root; newRoot.SetChildAt(_root, 0); newRoot.SetNbChildren(1); _root = newRoot; Split(newRoot, oldRoot, 0); _height++; _persister.SaveNode(oldRoot); // TODO Remove the save of the new root : the save on the btree // should do the save on the new root(after introspector // refactoring) _persister.SaveNode(newRoot); _persister.SaveBTree(this); BTreeValidator.ValidateNode(newRoot, true); } InsertNonFull(_root, key, value); _size++; _persister.SaveBTree(this); }
// 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); }
/// <summary> /// Creates a new node with the right part of this node. /// </summary> /// <remarks> /// Creates a new node with the right part of this node. This should only be called on a full node /// </remarks> public virtual IBTreeNode ExtractRightPart() { if (!IsFull()) { throw new BTreeException("extract right part called on non full node"); } // Creates an empty new node var rightPartNode = Btree.BuildNode(); var j = 0; for (var i = _degree; i < _maxNbKeys; i++) { rightPartNode.SetKeyAndValueAt(Keys[i], Values[i], j, false, false); Keys[i] = null; Values[i] = null; rightPartNode.SetChildAt(this, i, j, false); // TODO must we load all nodes to set new parent var bTreeNode = rightPartNode.GetChildAt(j, false); if (bTreeNode != null) { bTreeNode.SetParent(rightPartNode); } SetNullChildAt(i); j++; } rightPartNode.SetChildAt(this, MaxNbChildren - 1, j, false); // correct father id var c1TreeNode = rightPartNode.GetChildAt(j, false); if (c1TreeNode != null) { c1TreeNode.SetParent(rightPartNode); } SetNullChildAt(MaxNbChildren - 1); // resets last child Keys[_degree - 1] = null; // resets median element Values[_degree - 1] = null; // set numbers NbKeys = _degree - 1; var originalNbChildren = NbChildren; NbChildren = Math.Min(NbChildren, _degree); rightPartNode.SetNbKeys(_degree - 1); rightPartNode.SetNbChildren(originalNbChildren - NbChildren); BTreeValidator.ValidateNode(this); BTreeValidator.ValidateNode(rightPartNode); BTreeValidator.CheckDuplicateChildren(this, rightPartNode); return(rightPartNode); }
public virtual object DeleteKeyForLeafNode(IKeyAndValue keyAndValue) { var position = GetPositionOfKey(keyAndValue.GetKey()); if (position < 0) { return(null); } var realPosition = position - 1; var value = Values[realPosition]; LeftShiftFrom(realPosition, false); NbKeys--; BTreeValidator.ValidateNode(this); return(value); }
public override object DeleteKeyForLeafNode(IKeyAndValue keyAndValue) { var objectHasBeenFound = false; var positionOfKey = GetPositionOfKey(keyAndValue.GetKey()); if (positionOfKey < 0) { return(null); } var realPosition = positionOfKey - 1; // In Multiple Values per key, the value is a list var value = (IList)Values[realPosition]; // Here we must search for the right object. The list can contains more than 1 object var size = value.Count; for (var i = 0; i < size && !objectHasBeenFound; i++) { if (!value[i].Equals(keyAndValue.GetValue())) { continue; } value.Remove(i); objectHasBeenFound = true; } if (!objectHasBeenFound) { return(null); } // If after removal, the list is empty, then remove the key from the node if (value.Count == 0) { // If we get there LeftShiftFrom(realPosition, false); NbKeys--; } BTreeValidator.ValidateNode(this); return(keyAndValue.GetValue()); }
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)); }