Exemple #1
0
        /// <summary>
        /// Internal method that is used when splitting pages
        /// No need to do any work here, we are always adding at the end
        /// </summary>
        internal void CopyNodeDataToEndOfPage(TreeNodeHeader *other, Slice key)
        {
            var index = NumberOfEntries;

            Debug.Assert(HasSpaceFor(TreeSizeOf.NodeEntryWithAnotherKey(other, key) + Constants.Tree.NodeOffsetSize));

            var nodeSize = TreeSizeOf.NodeEntryWithAnotherKey(other, key);

            Debug.Assert(IsBranch == false || index != 0 || key.Size == 0);// branch page's first item must be the implicit ref

            var newNode = AllocateNewNode(index, nodeSize);

            Debug.Assert(key.Size <= ushort.MaxValue);
            newNode->KeySize = (ushort)key.Size;
            newNode->Flags   = other->Flags;

            if (key.Options == SliceOptions.Key && key.Size > 0)
            {
                key.CopyTo((byte *)newNode + Constants.Tree.NodeHeaderSize);
            }

            if (IsBranch || other->Flags == (TreeNodeFlags.PageRef))
            {
                newNode->PageNumber = other->PageNumber;
                newNode->Flags      = TreeNodeFlags.PageRef;
                return;
            }
            newNode->DataSize = other->DataSize;
            Memory.Copy((byte *)newNode + Constants.Tree.NodeHeaderSize + key.Size,
                        (byte *)other + Constants.Tree.NodeHeaderSize + other->KeySize,
                        other->DataSize);
        }
Exemple #2
0
        private bool TryMergePages(TreePage parentPage, TreePage left, TreePage right)
        {
            TemporaryPage tmp;

            using (_tx.Environment.GetTemporaryPage(_tx, out tmp))
            {
                var mergedPage = tmp.GetTempPage();
                Memory.Copy(mergedPage.Base, left.Base, left.PageSize);

                var previousSearchPosition = right.LastSearchPosition;

                for (int i = 0; i < right.NumberOfEntries; i++)
                {
                    right.LastSearchPosition = i;

                    var key  = GetActualKey(right, right.LastSearchPositionOrLastEntry);
                    var node = right.GetNode(i);

                    if (mergedPage.HasSpaceFor(_tx, TreeSizeOf.NodeEntryWithAnotherKey(node, key) + Constants.NodeOffsetSize) == false)
                    {
                        right.LastSearchPosition = previousSearchPosition; //previous position --> prevent mutation of parameter
                        return(false);
                    }

                    mergedPage.CopyNodeDataToEndOfPage(node, key);
                }

                Memory.Copy(left.Base, mergedPage.Base, left.PageSize);
            }

            parentPage.RemoveNode(parentPage.LastSearchPositionOrLastEntry); // unlink the right sibling
            _tree.FreePage(right);

            return(true);
        }