private byte *AddNodeToPage(TreePage page, int index, Slice alreadyPreparedNewKey = default(Slice)) { var newKeyToInsert = alreadyPreparedNewKey.HasValue ? alreadyPreparedNewKey : _newKey; switch (_nodeType) { case TreeNodeFlags.PageRef: return(page.AddPageRefNode(index, newKeyToInsert, _pageNumber)); case TreeNodeFlags.Data: return(page.AddDataNode(index, newKeyToInsert, _len)); case TreeNodeFlags.MultiValuePageRef: return(page.AddMultiValueNode(index, newKeyToInsert, _len)); default: throw new NotSupportedException("Unknown node type"); } }
private void MoveLeafNode(TreePage parentPage, TreePage from, TreePage to) { Debug.Assert(from.IsBranch == false); Slice originalFromKeyStart; using (GetActualKey(from, from.LastSearchPositionOrLastEntry, out originalFromKeyStart)) { var fromNode = from.GetNode(from.LastSearchPosition); byte *val = @from.Base + @from.KeysOffsets[@from.LastSearchPosition] + Constants.Tree.NodeHeaderSize + originalFromKeyStart.Size; byte *dataPos; var fromDataSize = fromNode->DataSize; switch (fromNode->Flags) { case TreeNodeFlags.PageRef: to.EnsureHasSpaceFor(_tx, originalFromKeyStart, -1); dataPos = to.AddPageRefNode(to.LastSearchPosition, originalFromKeyStart, fromNode->PageNumber); break; case TreeNodeFlags.Data: to.EnsureHasSpaceFor(_tx, originalFromKeyStart, fromDataSize); dataPos = to.AddDataNode(to.LastSearchPosition, originalFromKeyStart, fromDataSize); break; case TreeNodeFlags.MultiValuePageRef: to.EnsureHasSpaceFor(_tx, originalFromKeyStart, fromDataSize); dataPos = to.AddMultiValueNode(to.LastSearchPosition, originalFromKeyStart, fromDataSize); break; default: throw new NotSupportedException("Invalid node type to move: " + fromNode->Flags); } if (dataPos != null && fromDataSize > 0) { Memory.Copy(dataPos, val, fromDataSize); } from.RemoveNode(from.LastSearchPositionOrLastEntry); var pos = parentPage.LastSearchPositionOrLastEntry; parentPage.RemoveNode(pos); Slice newSeparatorKey; var scope = GetActualKey(to, 0, out newSeparatorKey); // get the next smallest key it has now try { var pageNumber = to.PageNumber; if (parentPage.GetNode(0)->PageNumber == to.PageNumber) { pageNumber = from.PageNumber; scope.Dispose(); scope = GetActualKey(from, 0, out newSeparatorKey); } AddSeparatorToParentPage(to, parentPage, pageNumber, newSeparatorKey, pos); } finally { scope.Dispose(); } } }
private void MoveLeafNode(TreePage parentPage, TreePage from, TreePage to) { Debug.Assert(from.IsBranch == false); var originalFromKeyStart = GetActualKey(from, from.LastSearchPositionOrLastEntry); var fromNode = from.GetNode(from.LastSearchPosition); byte *val = @from.Base + @from.KeysOffsets[@from.LastSearchPosition] + Constants.NodeHeaderSize + originalFromKeyStart.Size; var nodeVersion = fromNode->Version; // every time new node is allocated the version is increased, but in this case we do not want to increase it if (nodeVersion > 0) { nodeVersion -= 1; } byte *dataPos; var fromDataSize = fromNode->DataSize; switch (fromNode->Flags) { case TreeNodeFlags.PageRef: to.EnsureHasSpaceFor(_tx, originalFromKeyStart, -1); dataPos = to.AddPageRefNode(to.LastSearchPosition, originalFromKeyStart, fromNode->PageNumber); break; case TreeNodeFlags.Data: to.EnsureHasSpaceFor(_tx, originalFromKeyStart, fromDataSize); dataPos = to.AddDataNode(to.LastSearchPosition, originalFromKeyStart, fromDataSize, nodeVersion); break; case TreeNodeFlags.MultiValuePageRef: to.EnsureHasSpaceFor(_tx, originalFromKeyStart, fromDataSize); dataPos = to.AddMultiValueNode(to.LastSearchPosition, originalFromKeyStart, fromDataSize, nodeVersion); break; default: throw new NotSupportedException("Invalid node type to move: " + fromNode->Flags); } if (dataPos != null && fromDataSize > 0) { Memory.Copy(dataPos, val, fromDataSize); } from.RemoveNode(from.LastSearchPositionOrLastEntry); var pos = parentPage.LastSearchPositionOrLastEntry; parentPage.RemoveNode(pos); var newSeparatorKey = GetActualKey(to, 0); // get the next smallest key it has now var pageNumber = to.PageNumber; if (parentPage.GetNode(0)->PageNumber == to.PageNumber) { pageNumber = from.PageNumber; newSeparatorKey = GetActualKey(from, 0); } AddSeparatorToParentPage(to, parentPage, pageNumber, newSeparatorKey, pos); }