private IEnumerable <KeyValuePair <byte[], ulong> > MakeInternalNodes(ulong txnId, IEnumerable <KeyValuePair <byte[], ulong> > children, BrightstarProfiler profiler) { var enumerator = children.GetEnumerator(); var childList = enumerator.Next(_internalBranchFactor).ToList(); if (childList.Count == 1) { yield return(childList[0]); yield break; } byte[] prevNodeKey = childList[0].Key; IInternalNode prevNode = MakeInternalNode(txnId, childList); childList = enumerator.Next(_internalBranchFactor).ToList(); while (childList.Count > 0) { IInternalNode nextNode = MakeInternalNode(txnId, childList); var nextNodeKey = childList[0].Key; if (nextNode.NeedJoin) { nextNodeKey = new byte[_config.KeySize]; nextNode.RedistributeFromLeft(txnId, prevNode, childList[0].Key, nextNodeKey); } yield return(WriteNode(txnId, prevNode, prevNodeKey, profiler)); prevNode = nextNode; prevNodeKey = nextNodeKey; childList = enumerator.Next(_internalBranchFactor).ToList(); } yield return(WriteNode(txnId, prevNode, prevNodeKey, profiler)); }
internal IEnumerable <INode <T> > GetDescendants(IInternalNode <T> startNode, Func <IInternalNode <T>, bool> predicate) { ComputeLevels(); var visitedNodes = new HashSet <IInternalNode <T> >(); var stack = new Stack <IInternalNode <T> >(); stack.Push(startNode); while (stack.Count != 0) { var node = stack.Pop(); visitedNodes.Add(node); if (predicate(node)) { yield return(node); } foreach (var child in node.Edges) { if (visitedNodes.Contains(child)) { continue; } stack.Push(child); } } }
internal IEnumerable <INode <T> > GetPrecedents(IInternalNode <T> startNode, Func <IInternalNode <T>, bool> predicate) { this.ComputeLevels(); var visitedNodes = new HashSet <IInternalNode <T> >(); var stack = new Stack <IInternalNode <T> >(); stack.Push(startNode); while (stack.Count != 0) { var node = stack.Pop(); visitedNodes.Add(node); if (predicate(node)) { yield return(node); } foreach (var parent in node.Parents) { if (visitedNodes.Contains(parent)) { continue; } stack.Push(parent); } } }
public bool RedistributeFromRight(ulong txnId, IInternalNode rightSibling, byte[] joinKey, byte[] newJoinKey) { var right = rightSibling as InternalNode; if (right == null) { throw new ArgumentException("Expected a DirectInternalNode as right sibling", "rightSibling"); } int required = _config.InternalSplitIndex - _keyCount; if (rightSibling.KeyCount - required < _config.InternalSplitIndex) { return(false); } EnsureWriteable(txnId); right.EnsureWriteable(txnId); // Copy keys and child pointers _page.SetData(joinKey, 0, KeyOffset(KeyCount), _config.KeySize); // Set key[KeyCount+1] to joinKey _page.SetData(right.GetData(), KeyOffset(0), KeyOffset(KeyCount + 1), (required - 1) * _config.KeySize); _page.SetData(right.GetData(), PointerOffset(0), PointerOffset(KeyCount + 1), required * 8); Array.Copy(right.GetData(), KeyOffset(required - 1), newJoinKey, 0, _config.KeySize); right.LeftShift(required); KeyCount += required; return(true); }
internal IEnumerable <INode <T> > GetDescendants(IInternalNode <T> startNode, Func <IInternalNode <T>, bool> predicate) { ComputeLevels(); var visitedNodes = new bool[_nodes.Count]; var stack = new Stack <InternalNodeFast <T> >(); stack.Push(startNode as InternalNodeFast <T>); while (stack.Count != 0) { var node = stack.Pop(); visitedNodes[node.Key] = true; if (predicate(node)) { yield return(node); } foreach (var child in node.Edges) { if (visitedNodes[child.Key]) { continue; } stack.Push(child); } } }
internal IEnumerable <INode <T> > GetPrecedents(IInternalNode <T> startNode, Func <IInternalNode <T>, bool> predicate) { this.ComputeLevels(); var visitedNodes = new bool[this._nodes.Count]; var stack = new Stack <InternalNodeFast <T> >(); stack.Push(startNode as InternalNodeFast <T>); while (stack.Count != 0) { var node = stack.Pop(); visitedNodes[node.Key] = true; if (predicate(node)) { yield return(node); } foreach (var parent in node.Parents) { if (visitedNodes[parent.Key]) { continue; } stack.Push(parent); } } }
/// <summary> /// Attempts to ensure that the minimum size for this node is achieved by transferring entries from the left-hand sibling /// </summary> /// <param name="txnId"></param> /// <param name="leftSibling">The left-hand sibling that will provide entries</param> /// <param name="joinKey">The value of the key that is present in the parent node between the pointer to this node and its left sibling</param> /// <param name="newJoinKey">The replacement value for the join key in the parent node</param> /// <returns>True if the node achieves its minimum size by the redistribution process, false otherwise</returns> public bool RedistributeFromLeft(ulong txnId, IInternalNode leftSibling, byte[] joinKey, byte[] newJoinKey) { InternalNode left = leftSibling as InternalNode; if (left == null) { throw new ArgumentException("Expected a InternalNode as left sibling", "leftSibling"); } int required = _config.InternalSplitIndex - KeyCount; if (leftSibling.KeyCount - required < _config.InternalSplitIndex) { // Can't fulfill requirements with a borrow from left sibling return(false); } int evenOut = (KeyCount + left.KeyCount) / 2 - KeyCount; if (leftSibling.KeyCount - evenOut > _config.InternalSplitIndex) { required = evenOut; } EnsureWriteable(txnId); left.EnsureWriteable(txnId); // Make space for new keys and child pointers RightShift(required); _page.SetData(joinKey, 0, KeyOffset(required - 1), _config.KeySize); _page.SetData(left.GetData(), KeyOffset(left.KeyCount - (required - 1)), KeyOffset(0), (required - 1) * _config.KeySize); _page.SetData(left.GetData(), PointerOffset(left.KeyCount - (required - 1)), PointerOffset(0), (required) * 8); Array.Copy(left.GetData(), KeyOffset(left.KeyCount - required), newJoinKey, 0, _config.KeySize); KeyCount += required; left.KeyCount -= required; return(true); }
private KeyValuePair<byte[], ulong > WriteNode(ulong txnId, IInternalNode node, byte[] lowestLeafKey, BrightstarProfiler profiler) { //_pageStore.Write(txnId, node.PageId, node.GetData(), profiler:profiler); return new KeyValuePair<byte[], ulong>(lowestLeafKey, node.PageId); }
private KeyValuePair <byte[], ulong> WriteNode(ulong txnId, IInternalNode node, byte[] lowestLeafKey, BrightstarProfiler profiler) { //_pageStore.Write(txnId, node.PageId, node.GetData(), profiler:profiler); return(new KeyValuePair <byte[], ulong>(lowestLeafKey, node.PageId)); }
private void Delete(ulong txnId, IInternalNode parentInternalNode, byte[] key, out bool underAllocation, BrightstarProfiler profiler) { if (parentInternalNode.RightmostKey == null) { throw new ArgumentException("Parent node right key is null"); } var childNodeId = parentInternalNode.GetChildNodeId(key); var childNode = GetNode(childNodeId, profiler); if (childNode is ILeafNode) { var childLeafNode = childNode as ILeafNode; // Delete the key and mark the node as updated. This may update the child node id childLeafNode.Delete(txnId, key); MarkDirty(txnId, childLeafNode, profiler); if (childLeafNode.PageId != childNodeId) { parentInternalNode.UpdateChildPointer(txnId, childNodeId, childLeafNode.PageId); childNodeId = childLeafNode.PageId; } if (childLeafNode.NeedsJoin) { ulong leftSiblingId, rightSiblingId; ILeafNode leftSibling = null, rightSibling = null; bool hasLeftSibling = parentInternalNode.GetLeftSibling(childNodeId, out leftSiblingId); if (hasLeftSibling) { leftSibling = GetNode(leftSiblingId, profiler) as ILeafNode; if (childLeafNode.RedistributeFromLeft(txnId, leftSibling)) { parentInternalNode.SetLeftKey(txnId, childLeafNode.PageId, childLeafNode.LeftmostKey); MarkDirty(txnId, parentInternalNode, profiler); MarkDirty(txnId, leftSibling, null); parentInternalNode.UpdateChildPointer(txnId, leftSiblingId, leftSibling.PageId); underAllocation = false; return; } } bool hasRightSibling = parentInternalNode.GetRightSiblingId(childNodeId, out rightSiblingId); if (hasRightSibling) { rightSibling = GetNode(rightSiblingId, profiler) as ILeafNode; #if DEBUG if (rightSibling.LeftmostKey.Compare(childLeafNode.RightmostKey) <= 0) { throw new Exception("Right-hand sibling has a left key lower than this nodes right key."); } #endif if (childLeafNode.RedistributeFromRight(txnId, rightSibling)) { MarkDirty(txnId, rightSibling, profiler); parentInternalNode.UpdateChildPointer(txnId, rightSiblingId, rightSibling.PageId); parentInternalNode.SetLeftKey(txnId, rightSibling.PageId, rightSibling.LeftmostKey); MarkDirty(txnId, parentInternalNode, profiler); underAllocation = false; return; } } if (hasLeftSibling && childLeafNode.Merge(txnId, leftSibling)) { parentInternalNode.RemoveChildPointer(txnId, leftSiblingId); parentInternalNode.SetLeftKey(txnId, childLeafNode.PageId, childLeafNode.LeftmostKey); MarkDirty(txnId, parentInternalNode, profiler); underAllocation = parentInternalNode.NeedJoin; return; } if (hasRightSibling && childLeafNode.Merge(txnId, rightSibling)) { byte[] nodeKey = parentInternalNode.RemoveChildPointer(txnId, rightSiblingId); if (nodeKey == null) { // We merged in the right-most node, so we need to generate a key nodeKey = new byte[_config.KeySize]; Array.Copy(rightSibling.RightmostKey, nodeKey, _config.KeySize); ByteArrayHelper.Increment(nodeKey); } parentInternalNode.SetKey(txnId, childLeafNode.PageId, nodeKey); MarkDirty(txnId, parentInternalNode, profiler); underAllocation = parentInternalNode.NeedJoin; return; } } underAllocation = false; return; } if (childNode is IInternalNode) { bool childUnderAllocated; var childInternalNode = childNode as IInternalNode; Delete(txnId, childInternalNode, key, out childUnderAllocated, profiler); if (childInternalNode.PageId != childNodeId) { // Child node page changed parentInternalNode.UpdateChildPointer(txnId, childNodeId, childInternalNode.PageId); MarkDirty(txnId, parentInternalNode, profiler); childNodeId = childInternalNode.PageId; } if (childUnderAllocated) { IInternalNode leftSibling = null, rightSibling = null; ulong leftSiblingId, rightSiblingId; // Redistribute values from left-hand sibling bool hasLeftSibling = parentInternalNode.GetLeftSibling(childNodeId, out leftSiblingId); if (hasLeftSibling) { leftSibling = GetNode(leftSiblingId, profiler) as IInternalNode; byte[] joinKey = parentInternalNode.GetKey(leftSiblingId); var newJoinKey = new byte[_config.KeySize]; if (childInternalNode.RedistributeFromLeft(txnId, leftSibling, joinKey, newJoinKey)) { MarkDirty(txnId, leftSibling, profiler); parentInternalNode.UpdateChildPointer(txnId, leftSiblingId, leftSibling.PageId); parentInternalNode.SetKey(txnId, leftSibling.PageId, newJoinKey); MarkDirty(txnId, parentInternalNode, profiler); underAllocation = false; return; } } // Redistribute values from right-hand sibling bool hasRightSibling = parentInternalNode.GetRightSiblingId(childNodeId, out rightSiblingId); if (hasRightSibling) { rightSibling = GetNode(rightSiblingId, profiler) as IInternalNode; byte[] joinKey = parentInternalNode.GetKey(childInternalNode.PageId); byte[] newJoinKey = new byte[_config.KeySize]; if (childInternalNode.RedistributeFromRight(txnId, rightSibling, joinKey, newJoinKey)) { MarkDirty(txnId, rightSibling, profiler); parentInternalNode.UpdateChildPointer(txnId, rightSiblingId, rightSibling.PageId); // parentInternalNode.SetKey(rightSibling.PageId, newJoinKey); -- think this is wrong should be: parentInternalNode.SetKey(txnId, childInternalNode.PageId, newJoinKey); MarkDirty(txnId, parentInternalNode, profiler); underAllocation = false; return; } } // Merge with left-hand sibling if (hasLeftSibling) { // Attempt to merge child node into its left sibling var joinKey = parentInternalNode.GetKey(leftSibling.PageId); var mergedNodeKey = parentInternalNode.GetKey(childInternalNode.PageId); if (mergedNodeKey == null) { mergedNodeKey = new byte[_config.KeySize]; Array.Copy(childInternalNode.RightmostKey, mergedNodeKey, _config.KeySize); ByteArrayHelper.Increment(mergedNodeKey); } if (leftSibling.Merge(txnId, childInternalNode, joinKey)) { MarkDirty(txnId, leftSibling, profiler); if (leftSibling.PageId != leftSiblingId) { // We have a new page id (append-only stores will do this) parentInternalNode.UpdateChildPointer(txnId, leftSiblingId, leftSibling.PageId); } parentInternalNode.RemoveChildPointer(txnId, childInternalNode.PageId); parentInternalNode.SetKey(txnId, leftSibling.PageId, mergedNodeKey); MarkDirty(txnId, parentInternalNode, profiler); underAllocation = parentInternalNode.NeedJoin; return; } } // Merge with right-hand sibling if (hasRightSibling) { // Attempt to merge right sibling into child node var joinKey = parentInternalNode.GetKey(childNodeId); if (childInternalNode.Merge(txnId, rightSibling, joinKey)) { MarkDirty(txnId, childInternalNode, profiler); var nodeKey = parentInternalNode.RemoveChildPointer(txnId, rightSiblingId); if (childInternalNode.PageId != childNodeId) { // We have a new page id for the child node (append-only stores will do this) parentInternalNode.UpdateChildPointer(txnId, childNodeId, childInternalNode.PageId); } if (nodeKey == null) { // We merged in the right-most node, so we need to generate a key nodeKey = new byte[_config.KeySize]; Array.Copy(rightSibling.RightmostKey, nodeKey, _config.KeySize); ByteArrayHelper.Increment(nodeKey); } parentInternalNode.SetKey(txnId, childInternalNode.PageId, nodeKey); MarkDirty(txnId, parentInternalNode, profiler); underAllocation = parentInternalNode.NeedJoin; return; } } throw new NotImplementedException( "Not yet implemented handling for internal node becoming under allocated"); } underAllocation = false; } else { throw new BrightstarInternalException(String.Format("Unrecognised B+ Tree node class : {0}", childNode.GetType())); } }
public bool RedistributeFromRight(ulong txnId, IInternalNode rightSibling, byte[] joinKey, byte[] newJoinKey) { var right = rightSibling as InternalNode; if (right == null) throw new ArgumentException("Expected a DirectInternalNode as right sibling", "rightSibling"); int required = _config.InternalSplitIndex - _keyCount; if (rightSibling.KeyCount - required < _config.InternalSplitIndex) { return false; } EnsureWriteable(txnId); right.EnsureWriteable(txnId); // Copy keys and child pointers _page.SetData(joinKey, 0, KeyOffset(KeyCount), _config.KeySize); // Set key[KeyCount+1] to joinKey _page.SetData(right.GetData(), KeyOffset(0), KeyOffset(KeyCount + 1), (required - 1)*_config.KeySize); _page.SetData(right.GetData(), PointerOffset(0), PointerOffset(KeyCount + 1), required*8); Array.Copy(right.GetData(), KeyOffset(required - 1), newJoinKey, 0, _config.KeySize); right.LeftShift(required); KeyCount += required; return true; }
/// <summary> /// Attempts to ensure that the minimum size for this node is achieved by transferring entries from the left-hand sibling /// </summary> /// <param name="txnId"></param> /// <param name="leftSibling">The left-hand sibling that will provide entries</param> /// <param name="joinKey">The value of the key that is present in the parent node between the pointer to this node and its left sibling</param> /// <param name="newJoinKey">The replacement value for the join key in the parent node</param> /// <returns>True if the node achieves its minimum size by the redistribution process, false otherwise</returns> public bool RedistributeFromLeft(ulong txnId, IInternalNode leftSibling, byte[] joinKey, byte[] newJoinKey) { InternalNode left = leftSibling as InternalNode; if (left == null) { throw new ArgumentException("Expected a InternalNode as left sibling", "leftSibling"); } int required = _config.InternalSplitIndex - KeyCount; if (leftSibling.KeyCount - required < _config.InternalSplitIndex) { // Can't fulfill requirements with a borrow from left sibling return false; } int evenOut = (KeyCount + left.KeyCount)/2 - KeyCount; if (leftSibling.KeyCount - evenOut > _config.InternalSplitIndex) { required = evenOut; } EnsureWriteable(txnId); left.EnsureWriteable(txnId); // Make space for new keys and child pointers RightShift(required); _page.SetData(joinKey, 0, KeyOffset(required - 1), _config.KeySize); _page.SetData(left.GetData(), KeyOffset(left.KeyCount - (required - 1)), KeyOffset(0), (required - 1)*_config.KeySize); _page.SetData(left.GetData(), PointerOffset(left.KeyCount - (required - 1)), PointerOffset(0), (required)*8); Array.Copy(left.GetData(), KeyOffset(left.KeyCount-required), newJoinKey, 0, _config.KeySize); KeyCount += required; left.KeyCount -= required; return true; }