Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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);
 }
Example #5
0
 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));
 }
Example #6
0
        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()));
        }
Example #7
0
        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()));
            }
        }
Example #8
0
        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;
        }
Example #9
0
        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());
        }