/// <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); }
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); }