public bool RedistributeFromLeft(ulong txnId, ILeafNode leftNode) { var left = leftNode as LeafNode; if (left == null) { throw new ArgumentException("Expected a LeafNode instance", "leftNode"); } int copyCount = (KeyCount + left.KeyCount) / 2 - KeyCount; if (copyCount > 0) { EnsureWriteable(txnId); RightShift(copyCount); // Copy keys and data from left node int keyOffset = KeyOffset(left.KeyCount - copyCount); _page.SetData(left.GetData(), keyOffset, KeyOffset(0), copyCount * _config.KeySize); if (_config.ValueSize > 0) { int valueOffset = ValueOffset(left.KeyCount - copyCount); _page.SetData(left.GetData(), valueOffset, ValueOffset(0), copyCount * _config.ValueSize); } KeyCount += copyCount; left.KeyCount -= copyCount; return(true); } return(false); }
public bool RedistributeFromRight(ulong txnId, ILeafNode rightNode) { var right = rightNode as LeafNode; if (right == null) { throw new ArgumentException("Expected a LeafNode instance", "rightNode"); } int copyCount = (KeyCount + rightNode.KeyCount) / 2 - KeyCount; if (copyCount > 0) { EnsureWriteable(txnId); // Copy keys and data from right _page.SetData(right.GetData(), BPlusTreeConfiguration.LeafNodeHeaderSize, KeyOffset(KeyCount), copyCount * _config.KeySize); if (_config.ValueSize > 0) { _page.SetData(right.GetData(), _config.LeafDataStartOffset, ValueOffset(KeyCount), copyCount * _config.ValueSize); } // Shift up the remaining keys in the right right.LeftShift(copyCount); // Update my key count KeyCount += copyCount; return(true); } return(false); }
private IEnumerable <KeyValuePair <byte[], ulong> > MakeLeafNodes(ulong txnId, IEnumerator <KeyValuePair <byte[], byte[]> > orderedValues, BrightstarProfiler profiler = null) { ILeafNode prevNode = MakeLeafNode(txnId, orderedValues.Next(_leafLoadFactor)); if (prevNode.KeyCount < _leafLoadFactor) { // There were only enough values to fill a single leaf node yield return(WriteNode(txnId, prevNode, profiler)); yield break; } ILeafNode nextNode = MakeLeafNode(txnId, orderedValues.Next(_leafLoadFactor)); do { if (nextNode.KeyCount >= _config.LeafSplitIndex) { yield return(WriteNode(txnId, prevNode, profiler)); } else { // Final leaf node needs to share some values from the previous node we created nextNode.RedistributeFromLeft(txnId, prevNode); yield return(WriteNode(txnId, prevNode, profiler)); } prevNode = nextNode; var nextKeys = orderedValues.Next(_leafLoadFactor).ToList(); nextNode = nextKeys.Count > 0 ? MakeLeafNode(txnId, nextKeys) : null; } while (nextNode != null); yield return(WriteNode(txnId, prevNode, profiler)); }
private KeyValuePair<byte[], ulong> WriteNode(ulong txnId, ILeafNode node, BrightstarProfiler profiler = null) { //_pageStore.Write(txnId, node.PageId, node.GetData(), profiler: profiler); return new KeyValuePair<byte[], ulong>(node.LeftmostKey, node.PageId); }
private KeyValuePair <byte[], ulong> WriteNode(ulong txnId, ILeafNode node, BrightstarProfiler profiler = null) { //_pageStore.Write(txnId, node.PageId, node.GetData(), profiler: profiler); return(new KeyValuePair <byte[], ulong>(node.LeftmostKey, node.PageId)); }
private Tuple <Expression, IEnumerable <Expression> > CreateIndexExpression(ILeafNode <Expression> leaf, List <int> indexes) { var indexExpressions = indexes.Select(i => Expression.Constant(i, TypeSystem.Int)); return(Tuple.Create <Expression, IEnumerable <Expression> >(leaf.Value, indexExpressions.ToList())); }
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, ILeafNode rightNode) { var right = rightNode as LeafNode; if (right == null) throw new ArgumentException("Expected a LeafNode instance", "rightNode"); int copyCount = (KeyCount + rightNode.KeyCount)/2 - KeyCount; if (copyCount > 0) { EnsureWriteable(txnId); // Copy keys and data from right _page.SetData(right.GetData(), BPlusTreeConfiguration.LeafNodeHeaderSize, KeyOffset(KeyCount), copyCount*_config.KeySize); if (_config.ValueSize > 0) { _page.SetData(right.GetData(), _config.LeafDataStartOffset, ValueOffset(KeyCount), copyCount * _config.ValueSize); } // Shift up the remaining keys in the right right.LeftShift(copyCount); // Update my key count KeyCount += copyCount; return true; } return false; }
public bool RedistributeFromLeft(ulong txnId, ILeafNode leftNode) { var left = leftNode as LeafNode; if (left == null) throw new ArgumentException("Expected a LeafNode instance", "leftNode"); int copyCount = (KeyCount + left.KeyCount)/2 - KeyCount; if (copyCount > 0) { EnsureWriteable(txnId); RightShift(copyCount); // Copy keys and data from left node int keyOffset = KeyOffset(left.KeyCount - copyCount); _page.SetData(left.GetData(), keyOffset, KeyOffset(0), copyCount*_config.KeySize); if (_config.ValueSize > 0) { int valueOffset = ValueOffset(left.KeyCount - copyCount); _page.SetData(left.GetData(), valueOffset, ValueOffset(0), copyCount*_config.ValueSize); } KeyCount += copyCount; left.KeyCount -= copyCount; return true; } return false; }
private Tuple<Expression, IEnumerable<Expression>> CreateIndexExpression(ILeafNode<Expression> leaf, List<int> indexes) { var indexExpressions = indexes.Select(i => Expression.Constant(i, TypeSystem.Int)); return Tuple.Create<Expression, IEnumerable<Expression>>(leaf.Value, indexExpressions.ToList()); }