private void MoveLeafNode(Page parentPage, Page from, Page 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; switch (fromNode->Flags) { case NodeFlags.PageRef: to.EnsureHasSpaceFor(_tx, originalFromKeyStart, -1); dataPos = to.AddPageRefNode(to.LastSearchPosition, originalFromKeyStart, fromNode->PageNumber); break; case NodeFlags.Data: to.EnsureHasSpaceFor(_tx, originalFromKeyStart, fromNode->DataSize); dataPos = to.AddDataNode(to.LastSearchPosition, originalFromKeyStart, fromNode->DataSize, nodeVersion); break; case NodeFlags.MultiValuePageRef: to.EnsureHasSpaceFor(_tx, originalFromKeyStart, fromNode->DataSize); dataPos = to.AddMultiValueNode(to.LastSearchPosition, originalFromKeyStart, fromNode->DataSize, nodeVersion); break; default: throw new NotSupportedException("Invalid node type to move: " + fromNode->Flags); } if (dataPos != null) { NativeMethods.memcpy(dataPos, val, fromNode->DataSize); } from.RemoveNode(from.LastSearchPositionOrLastEntry); var pos = parentPage.LastSearchPositionOrLastEntry; parentPage.RemoveNode(pos); var newKey = 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; newKey = GetActualKey(from, 0); } parentPage.EnsureHasSpaceFor(_tx, newKey, -1); parentPage.AddPageRefNode(pos, newKey, pageNumber); }
private void MoveBranchNode(Page parentPage, Page from, Page to) { Debug.Assert(from.IsBranch); var originalFromKeyStart = GetActualKey(from, from.LastSearchPositionOrLastEntry); to.EnsureHasSpaceFor(_tx, originalFromKeyStart, -1); var fromNode = from.GetNode(from.LastSearchPosition); long pageNum = fromNode->PageNumber; if (to.LastSearchPosition == 0) { // cannot add to left implicit side, adjust by moving the left node // to the right by one, then adding the new one as the left var implicitLeftKey = GetActualKey(to, 0); var leftPageNumber = to.GetNode(0)->PageNumber; to.AddPageRefNode(1, implicitLeftKey, leftPageNumber); to.AddPageRefNode(0, Slice.BeforeAllKeys, pageNum); to.RemoveNode(1); } else { to.AddPageRefNode(to.LastSearchPosition, originalFromKeyStart, pageNum); } if (from.LastSearchPositionOrLastEntry == 0) { // cannot just remove the left node, need to adjust those var rightPageNumber = from.GetNode(1)->PageNumber; from.RemoveNode(0); // remove the original implicit node from.RemoveNode(0); // remove the next node that we now turned into implicit from.EnsureHasSpaceFor(_tx, Slice.BeforeAllKeys, -1); from.AddPageRefNode(0, Slice.BeforeAllKeys, rightPageNumber); Debug.Assert(from.NumberOfEntries >= 2); } else { from.RemoveNode(from.LastSearchPositionOrLastEntry); } var pos = parentPage.LastSearchPositionOrLastEntry; parentPage.RemoveNode(pos); var newKey = 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; newKey = GetActualKey(from, 0); } parentPage.EnsureHasSpaceFor(_tx, newKey, -1); parentPage.AddPageRefNode(pos, newKey, pageNumber); }
private void MoveBranchNode(Page parentPage, Page from, Page to) { Debug.Assert(from.IsBranch); var originalFromKey = to.PrepareKeyToInsert(GetActualKey(from, from.LastSearchPositionOrLastEntry), to.LastSearchPosition); to.EnsureHasSpaceFor(_tx, originalFromKey, -1); var fromNode = from.GetNode(from.LastSearchPosition); long pageNum = fromNode->PageNumber; if (to.LastSearchPosition == 0) { // cannot add to left implicit side, adjust by moving the left node // to the right by one, then adding the new one as the left NodeHeader *actualKeyNode; var implicitLeftKey = GetActualKey(to, 0, out actualKeyNode); var implicitLeftNode = to.GetNode(0); var leftPageNumber = implicitLeftNode->PageNumber; MemorySlice implicitLeftKeyToInsert; if (implicitLeftNode == actualKeyNode) { // no need to create a prefix, just use the existing prefixed key from the node // this also prevents from creating a prefix which is the full key given in 'implicitLeftKey' if (_tree.KeysPrefixing) { implicitLeftKeyToInsert = new PrefixedSlice(actualKeyNode); } else { implicitLeftKeyToInsert = new Slice(actualKeyNode); } } else { implicitLeftKeyToInsert = to.PrepareKeyToInsert(implicitLeftKey, 1); } to.EnsureHasSpaceFor(_tx, implicitLeftKeyToInsert, -1); to.AddPageRefNode(1, implicitLeftKeyToInsert, leftPageNumber); to.ChangeImplicitRefPageNode(pageNum); // setup the new implicit node } else { to.AddPageRefNode(to.LastSearchPosition, originalFromKey, pageNum); } if (from.LastSearchPositionOrLastEntry == 0) { var rightPageNumber = from.GetNode(1)->PageNumber; from.RemoveNode(0); // remove the original implicit node from.ChangeImplicitRefPageNode(rightPageNumber); // setup the new implicit node Debug.Assert(from.NumberOfEntries >= 2); } else { 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(parentPage, pageNumber, newSeparatorKey, pos); }
private void MoveBranchNode(Page parentPage, Page from, Page to) { Debug.Assert(from.IsBranch); var originalFromKey = to.PrepareKeyToInsert(GetActualKey(from, from.LastSearchPositionOrLastEntry), to.LastSearchPosition); to.EnsureHasSpaceFor(_tx, originalFromKey, -1); var fromNode = from.GetNode(from.LastSearchPosition); long pageNum = fromNode->PageNumber; if (to.LastSearchPosition == 0) { // cannot add to left implicit side, adjust by moving the left node // to the right by one, then adding the new one as the left NodeHeader* actualKeyNode; var implicitLeftKey = GetActualKey(to, 0, out actualKeyNode); var implicitLeftNode = to.GetNode(0); var leftPageNumber = implicitLeftNode->PageNumber; MemorySlice implicitLeftKeyToInsert; if (implicitLeftNode == actualKeyNode) { // no need to create a prefix, just use the existing prefixed key from the node // this also prevents from creating a prefix which is the full key given in 'implicitLeftKey' if (_tree.KeysPrefixing) implicitLeftKeyToInsert = new PrefixedSlice(actualKeyNode); else implicitLeftKeyToInsert = new Slice(actualKeyNode); } else implicitLeftKeyToInsert = to.PrepareKeyToInsert(implicitLeftKey, 1); to.EnsureHasSpaceFor(_tx, implicitLeftKeyToInsert, -1); to.AddPageRefNode(1, implicitLeftKeyToInsert, leftPageNumber); to.ChangeImplicitRefPageNode(pageNum); // setup the new implicit node } else { to.AddPageRefNode(to.LastSearchPosition, originalFromKey, pageNum); } if (from.LastSearchPositionOrLastEntry == 0) { var rightPageNumber = from.GetNode(1)->PageNumber; from.RemoveNode(0); // remove the original implicit node from.ChangeImplicitRefPageNode(rightPageNumber); // setup the new implicit node Debug.Assert(from.NumberOfEntries >= 2); } else { 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(parentPage, pageNumber, newSeparatorKey, pos); }
private void MoveLeafNode(Page parentPage, Page from, Page 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; var prefixedOriginalFromKey = to.PrepareKeyToInsert(originalFromKeyStart, to.LastSearchPosition); byte* dataPos; var fromDataSize = fromNode->DataSize; switch (fromNode->Flags) { case NodeFlags.PageRef: to.EnsureHasSpaceFor(_tx, prefixedOriginalFromKey, -1); dataPos = to.AddPageRefNode(to.LastSearchPosition, prefixedOriginalFromKey, fromNode->PageNumber); break; case NodeFlags.Data: to.EnsureHasSpaceFor(_tx, prefixedOriginalFromKey, fromDataSize); dataPos = to.AddDataNode(to.LastSearchPosition, prefixedOriginalFromKey, fromDataSize, nodeVersion); break; case NodeFlags.MultiValuePageRef: to.EnsureHasSpaceFor(_tx, prefixedOriginalFromKey, fromDataSize); dataPos = to.AddMultiValueNode(to.LastSearchPosition, prefixedOriginalFromKey, 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(parentPage, pageNumber, newSeparatorKey, pos); }