Пример #1
0
        /// <summary>
        /// Inserts a new value and leaf into the specified BTree node at the specified position. Existing value(s) and leaves are moved.
        /// </summary>
        /// <param name="nodeIndex">The index of the node to insert into.</param>
        /// <param name="valueIndex">The index of the value to move forward.</param>
        /// <param name="value">The BTreeValue containing information on the value. It must be fully filled in.</param>
        /// <param name="leaf">The leaf associated with the new value.</param>
        private void Insert(long nodeIndex, uint valueIndex, ref BTreeValue value, ref BTreeLeaf leaf)
        {
            using (var range = PrepareForInsert(nodeIndex, valueIndex)) {
                var pNode   = (BTreeNode *)range.Pointer;
                var pValues = (BTreeValue *)(range.Pointer + BTreeNode.OffsetOfValues);
                var pLeaves = (BTreeLeaf *)(range.Pointer + BTreeNode.OffsetOfLeaves);

                pValues[valueIndex]     = value;
                pLeaves[valueIndex + 1] = leaf;

                UnlockNode(range);
            }
        }
Пример #2
0
        /// <summary>
        /// Splits a BTree leaf node into two nodes. The median value from the node moves upward into the parent, with the two new nodes each recieving half of the remaining values and leaves.
        /// </summary>
        /// <param name="parentNodeIndex">The index of the node's parent node.</param>
        /// <param name="leafValueIndex">The index within the parent node's values where the median value should be inserted.</param>
        /// <param name="leafNodeIndex">The index of the leaf node to split.</param>
        public void SplitLeafNode(long parentNodeIndex, uint leafValueIndex, long leafNodeIndex)
        {
            const int tMinus1 = BTreeNode.T - 1;

            long newIndex = CreateNode();

            using (var leafRange = AccessNode(leafNodeIndex, true))
                using (var newRange = AccessNode(newIndex, true)) {
                    var pLeaf       = (BTreeNode *)leafRange.Pointer;
                    var pLeafValues = (BTreeValue *)(leafRange.Pointer + BTreeNode.OffsetOfValues);
                    var pLeafLeaves = (BTreeLeaf *)(leafRange.Pointer + BTreeNode.OffsetOfLeaves);

                    var pNew       = (BTreeNode *)newRange.Pointer;
                    var pNewValues = (BTreeValue *)(newRange.Pointer + BTreeNode.OffsetOfValues);
                    var pNewLeaves = (BTreeLeaf *)(newRange.Pointer + BTreeNode.OffsetOfLeaves);

                    if (pLeaf->NumValues != BTreeNode.MaxValues)
                    {
                        throw new InvalidDataException();
                    }

                    *pNew = new BTreeNode {
                        NumValues = (ushort)tMinus1,
                        HasLeaves = pLeaf->HasLeaves,
                        IsValid   = 0
                    };

                    pLeaf->NumValues = (ushort)tMinus1;

                    Native.memmove((byte *)pNewValues, (byte *)&pLeafValues[BTreeNode.T], new UIntPtr(tMinus1 * BTreeValue.Size));

                    if (pLeaf->HasLeaves == 1)
                    {
                        Native.memmove((byte *)pNewLeaves, (byte *)&pLeafLeaves[BTreeNode.T], new UIntPtr(BTreeNode.T * BTreeLeaf.Size));
                    }

                    var newLeaf = new BTreeLeaf(newIndex);
                    Insert(
                        parentNodeIndex, leafValueIndex,
                        ref pLeafValues[tMinus1], ref newLeaf
                        );

                    UnlockNode(newRange);
                    UnlockNode(leafRange);
                }
        }