// 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); }
public void Check_turning_on_the_btree_validation() { Assert.That(OdbConfiguration.IsBTreeValidationEnabled(), Is.False); OdbConfiguration.EnableBTreeValidation(); Assert.That(OdbConfiguration.IsBTreeValidationEnabled(), Is.True); OdbConfiguration.DisableBTreeValidation(); Assert.That(OdbConfiguration.IsBTreeValidationEnabled(), Is.False); }
public static void ValidateNode(IBTreeNode node, bool isRoot) { if (!OdbConfiguration.IsBTreeValidationEnabled()) { return; } ValidateNode(node); if (isRoot && node.HasParent()) { throw new BTreeNodeValidationException("Root node with a parent: " + node); } if (!isRoot && !node.HasParent()) { throw new BTreeNodeValidationException("Internal node without parent: " + node); } }
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 static void CheckValuesOfChild(IKeyAndValue key, IBTreeNode node) { if (!OdbConfiguration.IsBTreeValidationEnabled()) { return; } if (node == null) { return; } for (int i = 0; i < node.GetNbKeys(); i++) { if (node.GetKeyAndValueAt(i).GetKey().CompareTo(key.GetKey()) >= 0) { throw new BTreeNodeValidationException("Left child with values bigger than pivot " + key + " : " + node); } } }
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"); }
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)); } } }