From 11f2f90d6a91bef0d1baafde3115aad5f244218a Mon Sep 17 00:00:00 2001 From: Cheahuychou Mao Date: Wed, 19 Nov 2025 16:53:47 -0500 Subject: [PATCH] SERVER-114004 Add command stub for _shardsvrReshardRecipientCriticalSectionStarted (#44064) GitOrigin-RevId: be397396d296fc391ba279cc6ec769f576d6ebb1 --- .../auth/internal_command_auth_validation.js | 6 + jstests/auth/lib/commands_lib.js | 17 ++ .../core/catalog/views/views_all_commands.js | 1 + jstests/libs/write_concern_all_commands.js | 2 + .../all_commands_downgrading_to_upgraded.js | 1 + .../db_reads_while_recovering_all_commands.js | 1 + ...l_commands_direct_shard_connection_auth.js | 1 + .../database_versioning_all_commands.js | 15 ++ .../sharding/libs/last_lts_mongod_commands.js | 1 + ...read_write_concern_defaults_application.js | 1 + src/mongo/db/s/BUILD.bazel | 1 + ...recipient_critical_section_started_cmd.cpp | 151 ++++++++++++++++++ .../s/request_types/reshard_collection.idl | 24 ++- 13 files changed, 216 insertions(+), 6 deletions(-) create mode 100644 src/mongo/db/s/shardsvr_reshard_recipient_critical_section_started_cmd.cpp diff --git a/jstests/auth/internal_command_auth_validation.js b/jstests/auth/internal_command_auth_validation.js index c645c4dd828..e123af4a68e 100644 --- a/jstests/auth/internal_command_auth_validation.js +++ b/jstests/auth/internal_command_auth_validation.js @@ -736,6 +736,12 @@ const internalCommandsMap = { donorShards: [], }, }, + _shardsvrReshardRecipientCriticalSectionStarted: { + testname: "_shardsvrReshardRecipientCriticalSectionStarted", + command: { + _shardsvrReshardRecipientCriticalSectionStarted: UUID(), + }, + }, _shardsvrRefineCollectionShardKey: { testname: "_shardsvrRefineCollectionShardKey", command: {_shardsvrRefineCollectionShardKey: "test.x", newShardKey: {}}, diff --git a/jstests/auth/lib/commands_lib.js b/jstests/auth/lib/commands_lib.js index a5c887b16dd..acfa31293b9 100644 --- a/jstests/auth/lib/commands_lib.js +++ b/jstests/auth/lib/commands_lib.js @@ -3513,6 +3513,23 @@ export const authCommandsLib = { {runOnDb: secondDbName, roles: {}}, ], }, + { + testname: "_shardsvrReshardRecipientCriticalSectionStarted", + command: { + _shardsvrReshardRecipientCriticalSectionStarted: UUID(), + }, + skipSharded: true, + testcases: [ + { + runOnDb: adminDbName, + roles: {__system: 1}, + privileges: [{resource: {cluster: true}, actions: ["internal"]}], + expectFail: true, + }, + {runOnDb: firstDbName, roles: {}}, + {runOnDb: secondDbName, roles: {}}, + ], + }, { testname: "clusterCommitTransaction", command: {clusterCommitTransaction: 1}, diff --git a/jstests/core/catalog/views/views_all_commands.js b/jstests/core/catalog/views/views_all_commands.js index d8a67bba00d..e1a05a3d850 100644 --- a/jstests/core/catalog/views/views_all_commands.js +++ b/jstests/core/catalog/views/views_all_commands.js @@ -206,6 +206,7 @@ let viewsCommandTests = { _shardsvrReshardingDonorStartChangeStreamsMonitor: {skip: isAnInternalCommand}, _shardsvrReshardingOperationTime: {skip: isAnInternalCommand}, _shardsvrReshardRecipientClone: {skip: isAnInternalCommand}, + _shardsvrReshardRecipientCriticalSectionStarted: {skip: isAnInternalCommand}, _shardsvrSetAllowMigrations: {skip: isAnInternalCommand}, _shardsvrResolveView: {skip: isAnInternalCommand}, _shardsvrRunSearchIndexCommand: {skip: isAnInternalCommand}, diff --git a/jstests/libs/write_concern_all_commands.js b/jstests/libs/write_concern_all_commands.js index 517ff272810..1cdba843a25 100644 --- a/jstests/libs/write_concern_all_commands.js +++ b/jstests/libs/write_concern_all_commands.js @@ -193,6 +193,7 @@ const wcCommandsTests = { _shardsvrReshardingDonorStartChangeStreamsMonitor: {skip: "internal command"}, _shardsvrReshardingOperationTime: {skip: "internal command"}, _shardsvrReshardRecipientClone: {skip: "internal command"}, + _shardsvrReshardRecipientCriticalSectionStarted: {skip: "internal command"}, _shardsvrResolveView: {skip: "internal command"}, _shardsvrRunSearchIndexCommand: {skip: "internal command"}, _shardsvrSetAllowMigrations: {skip: "internal command"}, @@ -3405,6 +3406,7 @@ const wcTimeseriesViewsCommandsTests = { _shardsvrReshardingDonorStartChangeStreamsMonitor: {skip: "internal command"}, _shardsvrReshardingOperationTime: {skip: "internal command"}, _shardsvrReshardRecipientClone: {skip: "internal command"}, + _shardsvrReshardRecipientCriticalSectionStarted: {skip: "internal command"}, _shardsvrResolveView: {skip: "internal command"}, _shardsvrRunSearchIndexCommand: {skip: "internal command"}, _shardsvrSetAllowMigrations: {skip: "internal command"}, diff --git a/jstests/replsets/all_commands_downgrading_to_upgraded.js b/jstests/replsets/all_commands_downgrading_to_upgraded.js index 4d62b790f7c..53c3012f14f 100644 --- a/jstests/replsets/all_commands_downgrading_to_upgraded.js +++ b/jstests/replsets/all_commands_downgrading_to_upgraded.js @@ -144,6 +144,7 @@ const allCommands = { _shardsvrReshardingDonorStartChangeStreamsMonitor: {skip: isAnInternalCommand}, _shardsvrReshardingOperationTime: {skip: isAnInternalCommand}, _shardsvrReshardRecipientClone: {skip: isAnInternalCommand}, + _shardsvrReshardRecipientCriticalSectionStarted: {skip: isAnInternalCommand}, _shardsvrRefineCollectionShardKey: {skip: isAnInternalCommand}, _shardsvrSetAllowMigrations: {skip: isAnInternalCommand}, _shardsvrSetClusterParameter: {skip: isAnInternalCommand}, diff --git a/jstests/replsets/db_reads_while_recovering_all_commands.js b/jstests/replsets/db_reads_while_recovering_all_commands.js index 6a620e452b4..ded69a8d054 100644 --- a/jstests/replsets/db_reads_while_recovering_all_commands.js +++ b/jstests/replsets/db_reads_while_recovering_all_commands.js @@ -131,6 +131,7 @@ const allCommands = { _shardsvrReshardCollection: {skip: isPrimaryOnly}, _shardsvrReshardingOperationTime: {skip: isPrimaryOnly}, _shardsvrReshardRecipientClone: {skip: isPrimaryOnly}, + _shardsvrReshardRecipientCriticalSectionStarted: {skip: isPrimaryOnly}, _shardsvrRefineCollectionShardKey: {skip: isPrimaryOnly}, _shardsvrSetAllowMigrations: {skip: isPrimaryOnly}, _shardsvrSetClusterParameter: {skip: isAnInternalCommand}, diff --git a/jstests/sharding/all_commands_direct_shard_connection_auth.js b/jstests/sharding/all_commands_direct_shard_connection_auth.js index 53751fa983e..3e2363fc0c1 100644 --- a/jstests/sharding/all_commands_direct_shard_connection_auth.js +++ b/jstests/sharding/all_commands_direct_shard_connection_auth.js @@ -140,6 +140,7 @@ const allCommands = { _shardsvrReshardCollection: {skip: isAnInternalCommand}, _shardsvrReshardingOperationTime: {skip: isAnInternalCommand}, _shardsvrReshardRecipientClone: {skip: isAnInternalCommand}, + _shardsvrReshardRecipientCriticalSectionStarted: {skip: isAnInternalCommand}, _shardsvrRefineCollectionShardKey: {skip: isAnInternalCommand}, _shardsvrSetAllowMigrations: {skip: isAnInternalCommand}, _shardsvrSetClusterParameter: {skip: isAnInternalCommand}, diff --git a/jstests/sharding/database_versioning_all_commands.js b/jstests/sharding/database_versioning_all_commands.js index 6863135248d..2f8e06e9e7e 100644 --- a/jstests/sharding/database_versioning_all_commands.js +++ b/jstests/sharding/database_versioning_all_commands.js @@ -1019,6 +1019,21 @@ const allTestCases = { _shardsvrRenameIndexMetadata: {skip: "TODO"}, _shardsvrReshardCollection: {skip: "TODO"}, _shardsvrReshardRecipientClone: {skip: "TODO"}, + _shardsvrReshardRecipientCriticalSectionStarted: { + run: { + sendsDbVersion: false, + runsAgainstAdminDb: true, + command: function (dbName, collName) { + return { + _shardsvrReshardRecipientCriticalSectionStarted: UUID(), + }; + }, + // When the resharding recipient state machine does not exist, we throw + // NotWritablePrimary under the assumption that the request was delayed and the + // node is no longer the primary. + expectedFailureCode: ErrorCodes.NotWritablePrimary, + }, + }, _shardsvrReshardingDonorFetchFinalCollectionStats: {skip: "TODO"}, _shardsvrReshardingDonorStartChangeStreamsMonitor: {skip: "TODO"}, _shardsvrReshardingOperationTime: {skip: "TODO"}, diff --git a/jstests/sharding/libs/last_lts_mongod_commands.js b/jstests/sharding/libs/last_lts_mongod_commands.js index ab04eb6f84c..315998b77bd 100644 --- a/jstests/sharding/libs/last_lts_mongod_commands.js +++ b/jstests/sharding/libs/last_lts_mongod_commands.js @@ -55,6 +55,7 @@ export const commandsAddedToMongodSinceLastLTS = [ "_shardsvrRenameIndexMetadata", "getTrafficRecordingStatus", "_shardsvrReshardRecipientClone", + "_shardsvrReshardRecipientCriticalSectionStarted", "_shardsvrResolveView", "_configsvrStartShardDraining", "_shardsvrDropIndexesParticipant", diff --git a/jstests/sharding/read_write_concern_defaults_application.js b/jstests/sharding/read_write_concern_defaults_application.js index 9f3fe8b23d9..33bba4e7971 100644 --- a/jstests/sharding/read_write_concern_defaults_application.js +++ b/jstests/sharding/read_write_concern_defaults_application.js @@ -197,6 +197,7 @@ let testCases = { _shardsvrReshardingDonorStartChangeStreamsMonitor: {skip: "internal command"}, _shardsvrReshardingOperationTime: {skip: "internal command"}, _shardsvrReshardRecipientClone: {skip: "internal command"}, + _shardsvrReshardRecipientCriticalSectionStarted: {skip: "internal command"}, _shardsvrResolveView: {skip: "internal command"}, _shardsvrRunSearchIndexCommand: {skip: "internal command"}, _shardsvrSetAllowMigrations: {skip: "internal command"}, diff --git a/src/mongo/db/s/BUILD.bazel b/src/mongo/db/s/BUILD.bazel index 3621d317940..1aa942fc4af 100644 --- a/src/mongo/db/s/BUILD.bazel +++ b/src/mongo/db/s/BUILD.bazel @@ -716,6 +716,7 @@ mongo_cc_library( "shardsvr_get_stats_for_balancing_command.cpp", "shardsvr_move_range_command.cpp", "shardsvr_reshard_recipient_clone_cmd.cpp", + "shardsvr_reshard_recipient_critical_section_started_cmd.cpp", "shardsvr_resharding_donor_fetch_final_collection_stats_command.cpp", "shardsvr_resharding_donor_start_change_streams_monitor_command.cpp", "shardsvr_resharding_operation_time_command.cpp", diff --git a/src/mongo/db/s/shardsvr_reshard_recipient_critical_section_started_cmd.cpp b/src/mongo/db/s/shardsvr_reshard_recipient_critical_section_started_cmd.cpp new file mode 100644 index 00000000000..b688e67ed33 --- /dev/null +++ b/src/mongo/db/s/shardsvr_reshard_recipient_critical_section_started_cmd.cpp @@ -0,0 +1,151 @@ +/** + * Copyright (C) 2025-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + + +#include "mongo/base/error_codes.h" +#include "mongo/bson/bsonmisc.h" +#include "mongo/db/auth/action_type.h" +#include "mongo/db/auth/authorization_session.h" +#include "mongo/db/auth/resource_pattern.h" +#include "mongo/db/commands.h" +#include "mongo/db/database_name.h" +#include "mongo/db/namespace_string.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/s/resharding/resharding_donor_recipient_common.h" +#include "mongo/db/s/resharding/resharding_recipient_service.h" +#include "mongo/db/s/resharding/resharding_util.h" +#include "mongo/db/server_options.h" +#include "mongo/db/service_context.h" +#include "mongo/db/topology/cluster_role.h" +#include "mongo/logv2/log.h" +#include "mongo/logv2/log_attr.h" +#include "mongo/logv2/log_component.h" +#include "mongo/rpc/op_msg.h" +#include "mongo/s/request_types/reshard_collection_gen.h" +#include "mongo/s/resharding/common_types_gen.h" +#include "mongo/util/assert_util.h" +#include "mongo/util/future.h" +#include "mongo/util/uuid.h" + +#include +#include +#include + +#include +#include + +#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand + +namespace mongo { +namespace { + +class ShardsvrReshardRecipientCriticalSectionStartedCommand final + : public TypedCommand { +public: + using Request = ShardsvrReshardRecipientCriticalSectionStarted; + + class Invocation final : public InvocationBase { + public: + using InvocationBase::InvocationBase; + + void typedRun(OperationContext* opCtx) { + opCtx->setAlwaysInterruptAtStepDownOrUp_UNSAFE(); + + uassert( + ErrorCodes::IllegalOperation, + "_shardsvrReshardRecipientCriticalSectionStarted can only be run on shard servers", + serverGlobalParams.clusterRole.has(ClusterRole::ShardServer)); + + if (auto machine = resharding::tryGetReshardingStateMachineAndThrowIfShuttingDown< + ReshardingRecipientService, + ReshardingRecipientService::RecipientStateMachine, + ReshardingRecipientDocument>(opCtx, uuid())) { + + LOGV2(11400401, + "Resharding recipient start executing " + "_shardsvrRecipientCriticalSectionStarted command.", + "reshardingUUID"_attr = uuid()); + + LOGV2(11400402, + "Resharding recipient finished executing " + "_shardsvrRecipientCriticalSectionStarted command.", + "reshardingUUID"_attr = uuid()); + } else { + // If state machine does not exist, either this message was delayed and the + // resharding operation is done, or this node is no longer a primary. + uasserted(ErrorCodes::NotWritablePrimary, + "Internal Error: No matching resharding operation."); + } + } + + private: + UUID uuid() const { + return request().getCommandParameter(); + } + + NamespaceString ns() const override { + return {}; + } + + bool supportsWriteConcern() const override { + return true; + } + + void doCheckAuthorization(OperationContext* opCtx) const override { + uassert(ErrorCodes::Unauthorized, + "Unauthorized", + AuthorizationSession::get(opCtx->getClient()) + ->isAuthorizedForActionsOnResource( + ResourcePattern::forClusterResource(request().getDbName().tenantId()), + ActionType::internal)); + } + }; + + bool skipApiVersionCheck() const override { + // Internal command (server to server). + return true; + } + + std::string help() const override { + return "Internal command run by coordinator against recipients to notify them that the " + "critical section has started. Do not call directly."; + } + + bool adminOnly() const override { + return true; + } + + AllowedOnSecondary secondaryAllowed(ServiceContext*) const override { + return AllowedOnSecondary::kNever; + } +}; +MONGO_REGISTER_COMMAND(ShardsvrReshardRecipientCriticalSectionStartedCommand).forShard(); + +} // namespace +} // namespace mongo diff --git a/src/mongo/s/request_types/reshard_collection.idl b/src/mongo/s/request_types/reshard_collection.idl index 592a70de9b2..70f224cf625 100644 --- a/src/mongo/s/request_types/reshard_collection.idl +++ b/src/mongo/s/request_types/reshard_collection.idl @@ -114,8 +114,8 @@ commands: demoMode: type: optionalBool description: >- - "When set to true, overrides reshardingMinimumOperationDurationMillis - and reshardingDelayBeforeRemainingOperationTimeQueryMillis values to 0 + "When set to true, overrides reshardingMinimumOperationDurationMillis + and reshardingDelayBeforeRemainingOperationTimeQueryMillis values to 0 for quick demo of reshardCollection operation" _configsvrReshardCollection: @@ -194,8 +194,8 @@ commands: demoMode: type: optionalBool description: >- - "When set to true, overrides reshardingMinimumOperationDurationMillis - and reshardingDelayBeforeRemainingOperationTimeQueryMillis values to 0 + "When set to true, overrides reshardingMinimumOperationDurationMillis + and reshardingDelayBeforeRemainingOperationTimeQueryMillis values to 0 for quick demo of reshardCollection operation" rewriteCollection: @@ -225,8 +225,8 @@ commands: demoMode: type: optionalBool description: >- - "When set to true, overrides reshardingMinimumOperationDurationMillis - and reshardingDelayBeforeRemainingOperationTimeQueryMillis values to 0 + "When set to true, overrides reshardingMinimumOperationDurationMillis + and reshardingDelayBeforeRemainingOperationTimeQueryMillis values to 0 for quick demo of reshardCollection operation" moveCollection: @@ -337,3 +337,15 @@ commands: approxCopySize: type: ReshardingApproxCopySize description: "Not meant to be used directly. Only use internal fields." + + _shardsvrReshardRecipientCriticalSectionStarted: + description: + "The internal command run by coordinator against recipients to notify them that the + critical section has started." + command_name: _shardsvrReshardRecipientCriticalSectionStarted + cpp_name: ShardsvrReshardRecipientCriticalSectionStarted + type: uuid + strict: false + namespace: type + reply_type: OkReply + api_version: ""