summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordi Serra Torrens <jordi.serra-torrens@mongodb.com>2022-02-11 08:35:23 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-02-11 09:27:41 +0000
commit58b7a5be37e56989f015d6964cb31df073b95168 (patch)
tree1113fde65757386782877c35faf5d303526546ef
parentbf11296b533b07bd4b87f64e7477cc147c7697ea (diff)
downloadmongo-58b7a5be37e56989f015d6964cb31df073b95168.tar.gz
SERVER-63473 Create SetUserWriteBlockMode configsvr coordinator
-rw-r--r--jstests/core/views/views_all_commands.js1
-rw-r--r--jstests/replsets/db_reads_while_recovering_all_commands.js1
-rw-r--r--jstests/sharding/read_write_concern_defaults_application.js1
-rw-r--r--jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js1
-rw-r--r--jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js1
-rw-r--r--src/mongo/db/mongod_main.cpp2
-rw-r--r--src/mongo/db/namespace_string.cpp5
-rw-r--r--src/mongo/db/namespace_string.h3
-rw-r--r--src/mongo/db/s/SConscript7
-rw-r--r--src/mongo/db/s/config/configsvr_coordinator.cpp134
-rw-r--r--src/mongo/db/s/config/configsvr_coordinator.h74
-rw-r--r--src/mongo/db/s/config/configsvr_coordinator.idl64
-rw-r--r--src/mongo/db/s/config/configsvr_coordinator_service.cpp68
-rw-r--r--src/mongo/db/s/config/configsvr_coordinator_service.h68
-rw-r--r--src/mongo/db/s/config/configsvr_set_user_write_block_mode_command.cpp116
-rw-r--r--src/mongo/db/s/config/set_user_write_block_mode_coordinator.cpp98
-rw-r--r--src/mongo/db/s/config/set_user_write_block_mode_coordinator.h82
-rw-r--r--src/mongo/db/s/config/set_user_write_block_mode_coordinator_document.idl58
-rw-r--r--src/mongo/s/request_types/sharded_ddl_commands.idl9
19 files changed, 793 insertions, 0 deletions
diff --git a/jstests/core/views/views_all_commands.js b/jstests/core/views/views_all_commands.js
index 943e83d1115..f0f800da668 100644
--- a/jstests/core/views/views_all_commands.js
+++ b/jstests/core/views/views_all_commands.js
@@ -114,6 +114,7 @@ let viewsCommandTests = {
_configsvrRepairShardedCollectionChunksHistory: {skip: isAnInternalCommand},
_configsvrReshardCollection: {skip: isAnInternalCommand},
_configsvrSetAllowMigrations: {skip: isAnInternalCommand},
+ _configsvrSetUserWriteBlockMode: {skip: isAnInternalCommand},
_configsvrShardCollection:
{skip: isAnInternalCommand}, // TODO SERVER-58843: Remove once 6.0 becomes last LTS
_configsvrUpdateZoneKeyRange: {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 cc929dd1bbc..aabcdf83a5a 100644
--- a/jstests/replsets/db_reads_while_recovering_all_commands.js
+++ b/jstests/replsets/db_reads_while_recovering_all_commands.js
@@ -51,6 +51,7 @@ const allCommands = {
_configsvrRenameCollectionMetadata: {skip: isPrimaryOnly},
_configsvrReshardCollection: {skip: isPrimaryOnly},
_configsvrSetAllowMigrations: {skip: isPrimaryOnly},
+ _configsvrSetUserWriteBlockMode: {skip: isPrimaryOnly},
_configsvrUpdateZoneKeyRange: {skip: isPrimaryOnly},
_flushDatabaseCacheUpdates: {skip: isPrimaryOnly},
_flushDatabaseCacheUpdatesWithWriteConcern: {skip: isPrimaryOnly},
diff --git a/jstests/sharding/read_write_concern_defaults_application.js b/jstests/sharding/read_write_concern_defaults_application.js
index 1a066f1e265..caa0f5b1451 100644
--- a/jstests/sharding/read_write_concern_defaults_application.js
+++ b/jstests/sharding/read_write_concern_defaults_application.js
@@ -117,6 +117,7 @@ let testCases = {
_configsvrRepairShardedCollectionChunksHistory: {skip: "internal command"},
_configsvrReshardCollection: {skip: "internal command"},
_configsvrSetAllowMigrations: {skip: "internal command"},
+ _configsvrSetUserWriteBlockMode: {skip: "internal command"},
_configsvrShardCollection:
{skip: "internal command"}, // TODO SERVER-58843: Remove once 6.0 becomes last LTS
_configsvrUpdateZoneKeyRange: {skip: "internal command"},
diff --git a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js
index fa6b2f2e7d9..f13ac0a66b2 100644
--- a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js
+++ b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js
@@ -76,6 +76,7 @@ let testCases = {
_configsvrRemoveTags: {skip: "primary only"},
_configsvrReshardCollection: {skip: "primary only"},
_configsvrSetAllowMigrations: {skip: "primary only"},
+ _configsvrSetUserWriteBlockMode: {skip: "primary only"},
_configsvrShardCollection:
{skip: "primary only"}, // TODO SERVER-58843: Remove once 6.0 becomes last LTS
_configsvrUpdateZoneKeyRange: {skip: "primary only"},
diff --git a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js
index 4921cce3bc8..e496e549918 100644
--- a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js
+++ b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js
@@ -68,6 +68,7 @@ let testCases = {
_configsvrRemoveTags: {skip: "primary only"},
_configsvrReshardCollection: {skip: "primary only"},
_configsvrSetAllowMigrations: {skip: "primary only"},
+ _configsvrSetUserWriteBlockMode: {skip: "primary only"},
_configsvrShardCollection:
{skip: "primary only"}, // TODO SERVER-58843: Remove once 6.0 becomes last LTS
_configsvrUpdateZoneKeyRange: {skip: "primary only"},
diff --git a/src/mongo/db/mongod_main.cpp b/src/mongo/db/mongod_main.cpp
index fea45167926..0b1b5fa0287 100644
--- a/src/mongo/db/mongod_main.cpp
+++ b/src/mongo/db/mongod_main.cpp
@@ -137,6 +137,7 @@
#include "mongo/db/repl_set_member_in_standalone_mode.h"
#include "mongo/db/s/collection_sharding_state_factory_shard.h"
#include "mongo/db/s/collection_sharding_state_factory_standalone.h"
+#include "mongo/db/s/config/configsvr_coordinator_service.h"
#include "mongo/db/s/config/sharding_catalog_manager.h"
#include "mongo/db/s/config_server_op_observer.h"
#include "mongo/db/s/migration_util.h"
@@ -322,6 +323,7 @@ void registerPrimaryOnlyServices(ServiceContext* serviceContext) {
if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
services.push_back(std::make_unique<ReshardingCoordinatorService>(serviceContext));
+ services.push_back(std::make_unique<ConfigsvrCoordinatorService>(serviceContext));
} else if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
services.push_back(std::make_unique<RenameCollectionParticipantService>(serviceContext));
services.push_back(std::make_unique<ShardingDDLCoordinatorService>(serviceContext));
diff --git a/src/mongo/db/namespace_string.cpp b/src/mongo/db/namespace_string.cpp
index a836a0b4560..cdbe1e742f1 100644
--- a/src/mongo/db/namespace_string.cpp
+++ b/src/mongo/db/namespace_string.cpp
@@ -142,6 +142,9 @@ const NamespaceString NamespaceString::kForceOplogBatchBoundaryNamespace(
const NamespaceString NamespaceString::kConfigImagesNamespace(NamespaceString::kConfigDb,
"image_collection");
+const NamespaceString NamespaceString::kConfigsvrCoordinatorsNamespace(
+ NamespaceString::kConfigDb, "sharding_configsvr_coordinators");
+
bool NamespaceString::isListCollectionsCursorNS() const {
return coll() == listCollectionsCursorCol;
}
@@ -170,6 +173,8 @@ bool NamespaceString::isLegalClientSystemNS(
return true;
if (coll() == kShardingDDLCoordinatorsNamespace.coll())
return true;
+ if (coll() == kConfigsvrCoordinatorsNamespace.coll())
+ return true;
} else if (db() == kLocalDb) {
if (coll() == kSystemReplSetNamespace.coll())
return true;
diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h
index c9fc9e85c6a..ff7b93a983a 100644
--- a/src/mongo/db/namespace_string.h
+++ b/src/mongo/db/namespace_string.h
@@ -198,6 +198,9 @@ public:
// Namespace used for storing retryable findAndModify images.
static const NamespaceString kConfigImagesNamespace;
+ // Namespace used for persisting ConfigsvrCoordinator state documents.
+ static const NamespaceString kConfigsvrCoordinatorsNamespace;
+
/**
* Constructs an empty NamespaceString.
*/
diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript
index aa1367cefba..bf3001d84cd 100644
--- a/src/mongo/db/s/SConscript
+++ b/src/mongo/db/s/SConscript
@@ -284,16 +284,22 @@ env.Library(
'clone_collection_options_from_primary_shard_cmd.cpp',
'collmod_coordinator.cpp',
'collmod_coordinator_document.idl',
+ 'config/set_user_write_block_mode_coordinator.cpp',
+ 'config/set_user_write_block_mode_coordinator_document.idl',
'config/configsvr_abort_reshard_collection_command.cpp',
'config/configsvr_add_shard_command.cpp',
'config/configsvr_add_shard_to_zone_command.cpp',
'config/configsvr_balancer_collection_status_command.cpp',
+ 'config/configsvr_set_user_write_block_mode_command.cpp',
'config/configsvr_cleanup_reshard_collection_command.cpp',
'config/configsvr_clear_jumbo_flag_command.cpp',
'config/configsvr_commit_chunk_migration_command.cpp',
'config/configsvr_commit_reshard_collection_command.cpp',
'config/configsvr_configure_collection_balancing.cpp',
'config/configsvr_control_balancer_command.cpp',
+ 'config/configsvr_coordinator.idl',
+ 'config/configsvr_coordinator_service.cpp',
+ 'config/configsvr_coordinator.cpp',
'config/configsvr_create_database_command.cpp',
'config/configsvr_ensure_chunk_version_is_greater_than_command.cpp',
'config/configsvr_merge_chunks_command.cpp',
@@ -383,6 +389,7 @@ env.Library(
'$BUILD_DIR/mongo/db/repl/primary_only_service',
'$BUILD_DIR/mongo/db/repl/repl_coordinator_interface',
'$BUILD_DIR/mongo/db/repl/replica_set_messages',
+ '$BUILD_DIR/mongo/db/server_feature_flags',
'$BUILD_DIR/mongo/db/timeseries/catalog_helper',
'$BUILD_DIR/mongo/db/timeseries/timeseries_collmod',
'$BUILD_DIR/mongo/db/timeseries/timeseries_conversion_util',
diff --git a/src/mongo/db/s/config/configsvr_coordinator.cpp b/src/mongo/db/s/config/configsvr_coordinator.cpp
new file mode 100644
index 00000000000..960ade4a72b
--- /dev/null
+++ b/src/mongo/db/s/config/configsvr_coordinator.cpp
@@ -0,0 +1,134 @@
+/**
+ * Copyright (C) 2022-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
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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.
+ */
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kSharding
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/s/config/configsvr_coordinator.h"
+
+#include "mongo/db/s/config/configsvr_coordinator_gen.h"
+#include "mongo/logv2/log.h"
+#include "mongo/util/future_util.h"
+
+namespace mongo {
+
+namespace {
+
+const Backoff kExponentialBackoff(Seconds(1), Milliseconds::max());
+
+} // namespace
+
+ConfigsvrCoordinatorMetadata extractConfigsvrCoordinatorMetadata(const BSONObj& stateDoc) {
+ return ConfigsvrCoordinatorMetadata::parse(
+ IDLParserErrorContext("ConfigsvrCoordinatorMetadata"), stateDoc);
+}
+
+ConfigsvrCoordinator::ConfigsvrCoordinator(const BSONObj& stateDoc)
+ : _coordId(extractConfigsvrCoordinatorMetadata(stateDoc).getId()) {}
+
+ConfigsvrCoordinator::~ConfigsvrCoordinator() {
+ invariant(_completionPromise.getFuture().isReady());
+}
+
+void ConfigsvrCoordinator::_removeStateDocument(OperationContext* opCtx) {
+ LOGV2_DEBUG(6347304,
+ 2,
+ "Removing state document for ConfigsvrCoordinator instance",
+ "coordId"_attr = _coordId);
+
+ PersistentTaskStore<ConfigsvrCoordinatorMetadata> store(
+ NamespaceString::kConfigsvrCoordinatorsNamespace);
+ store.remove(opCtx,
+ BSON(ConfigsvrCoordinatorMetadata::kIdFieldName << _coordId.toBSON()),
+ WriteConcerns::kMajorityWriteConcernNoTimeout);
+}
+
+void ConfigsvrCoordinator::interrupt(Status status) noexcept {
+ LOGV2_DEBUG(6347303,
+ 1,
+ "ConfigsvrCoordinator received an interrupt",
+ "coordinatorId"_attr = _coordId,
+ "reason"_attr = redact(status));
+
+ // Resolve any unresolved promises to avoid hanging.
+ stdx::lock_guard<Latch> lg(_mutex);
+ if (!_completionPromise.getFuture().isReady()) {
+ _completionPromise.setError(status);
+ }
+}
+
+SemiFuture<void> ConfigsvrCoordinator::run(std::shared_ptr<executor::ScopedTaskExecutor> executor,
+ const CancellationToken& token) noexcept {
+ return ExecutorFuture<void>(**executor)
+ .then([this, executor, token, anchor = shared_from_this()] {
+ return AsyncTry([this, executor, token] { return _runImpl(executor, token); })
+ .until([this, token](Status status) { return status.isOK() || token.isCanceled(); })
+ .withBackoffBetweenIterations(kExponentialBackoff)
+ .on(**executor, CancellationToken::uncancelable());
+ })
+ .onCompletion([this, executor, token, anchor = shared_from_this()](const Status& status) {
+ if (!status.isOK()) {
+ if (!status.isA<ErrorCategory::NotPrimaryError>() &&
+ !status.isA<ErrorCategory::ShutdownError>()) {
+ LOGV2_ERROR(6347301,
+ "Error executing ConfigsvrCoordinator",
+ "error"_attr = redact(status));
+ }
+
+ return status;
+ }
+
+ try {
+ auto opCtxHolder = cc().makeOperationContext();
+ auto* opCtx = opCtxHolder.get();
+ _removeStateDocument(opCtx);
+ } catch (DBException& ex) {
+ LOGV2_WARNING(6347302,
+ "Failed to remove ConfigsvrCoordinator state document",
+ "error"_attr = redact(ex));
+ ex.addContext("Failed to remove ConfigsvrCoordinator state document"_sd);
+ stdx::lock_guard<Latch> lg(_mutex);
+ if (!_completionPromise.getFuture().isReady()) {
+ _completionPromise.setError(ex.toStatus());
+ }
+ throw;
+ }
+
+ stdx::lock_guard<Latch> lg(_mutex);
+ if (!_completionPromise.getFuture().isReady()) {
+ _completionPromise.emplaceValue();
+ }
+
+ return status;
+ })
+ .semi();
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/s/config/configsvr_coordinator.h b/src/mongo/db/s/config/configsvr_coordinator.h
new file mode 100644
index 00000000000..2f93d39afb8
--- /dev/null
+++ b/src/mongo/db/s/config/configsvr_coordinator.h
@@ -0,0 +1,74 @@
+/**
+ * Copyright (C) 2022-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
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "mongo/db/internal_session_pool.h"
+#include "mongo/db/persistent_task_store.h"
+#include "mongo/db/repl/primary_only_service.h"
+#include "mongo/db/s/config/set_user_write_block_mode_coordinator_document_gen.h"
+
+namespace mongo {
+
+ConfigsvrCoordinatorMetadata extractConfigsvrCoordinatorMetadata(const BSONObj& stateDoc);
+
+/**
+ * ConfigsvrCoordinators are POS instances that run on the configsvr and represent cluster
+ * operations that are driven by the configsvr. ConfigsvrCoordinator implements common framework for
+ * such operations. Concrete operations extend ConfigsvrCoordinator and implement their specific
+ * bussiness logic on '_runImpl'
+ */
+class ConfigsvrCoordinator : public repl::PrimaryOnlyService::TypedInstance<ConfigsvrCoordinator> {
+public:
+ explicit ConfigsvrCoordinator(const BSONObj& stateDoc);
+
+ ~ConfigsvrCoordinator();
+
+ SharedSemiFuture<void> getCompletionFuture() {
+ return _completionPromise.getFuture();
+ }
+
+protected:
+ const ConfigsvrCoordinatorId _coordId;
+
+ SemiFuture<void> run(std::shared_ptr<executor::ScopedTaskExecutor> executor,
+ const CancellationToken& token) noexcept override final;
+
+ virtual ExecutorFuture<void> _runImpl(std::shared_ptr<executor::ScopedTaskExecutor> executor,
+ const CancellationToken& token) noexcept = 0;
+
+ void interrupt(Status status) noexcept override final;
+
+ void _removeStateDocument(OperationContext* opCtx);
+
+ Mutex _mutex = MONGO_MAKE_LATCH("ConfigsvrCoordinator::_mutex");
+ SharedPromise<void> _completionPromise;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/s/config/configsvr_coordinator.idl b/src/mongo/db/s/config/configsvr_coordinator.idl
new file mode 100644
index 00000000000..5ad0c2dc985
--- /dev/null
+++ b/src/mongo/db/s/config/configsvr_coordinator.idl
@@ -0,0 +1,64 @@
+# Copyright (C) 2022-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
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# 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.
+#
+
+
+global:
+ cpp_namespace: "mongo"
+
+imports:
+ - "mongo/db/logical_session_id.idl"
+ - "mongo/idl/basic_types.idl"
+
+enums:
+ ConfigsvrCoordinatorType:
+ description: "Coordinator type"
+ type: string
+ values:
+ kSetUserWriteBlockMode: "setUserWriteBlockMode"
+
+structs:
+ ConfigsvrCoordinatorId:
+ description: "Identifier for a specific instance of ConfigsvrCoordinator"
+ generate_comparison_operators: false
+ strict: false
+ fields:
+ coordinatorType:
+ description: "Type of the ConfigsvrCoordinator"
+ type: ConfigsvrCoordinatorType
+
+ ConfigsvrCoordinatorMetadata:
+ description: "Common metadata for all ConfigsvrCoordinators"
+ generate_comparison_operators: false
+ strict: false
+ fields:
+ _id:
+ cpp_name: id
+ type: ConfigsvrCoordinatorId
+ recoveredFromDisk:
+ type: bool
+ default: false
diff --git a/src/mongo/db/s/config/configsvr_coordinator_service.cpp b/src/mongo/db/s/config/configsvr_coordinator_service.cpp
new file mode 100644
index 00000000000..9dfbd73a457
--- /dev/null
+++ b/src/mongo/db/s/config/configsvr_coordinator_service.cpp
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2022-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
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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.
+ */
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kSharding
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/s/config/configsvr_coordinator_service.h"
+
+#include "mongo/base/checked_cast.h"
+#include "mongo/db/s/config/configsvr_coordinator.h"
+#include "mongo/db/s/config/set_user_write_block_mode_coordinator.h"
+#include "mongo/logv2/log.h"
+
+namespace mongo {
+
+ConfigsvrCoordinatorService* ConfigsvrCoordinatorService::getService(OperationContext* opCtx) {
+ auto registry = repl::PrimaryOnlyServiceRegistry::get(opCtx->getServiceContext());
+ auto service = registry->lookupServiceByName(kServiceName);
+ return checked_cast<ConfigsvrCoordinatorService*>(std::move(service));
+}
+
+std::shared_ptr<ConfigsvrCoordinatorService::Instance>
+ConfigsvrCoordinatorService::constructInstance(BSONObj initialState) {
+ LOGV2_DEBUG(6347300,
+ 2,
+ "Constructing new ConfigsvrCoordinator instance",
+ "initialState"_attr = initialState);
+
+ const auto op = extractConfigsvrCoordinatorMetadata(initialState);
+ switch (op.getId().getCoordinatorType()) {
+ case ConfigsvrCoordinatorTypeEnum::kSetUserWriteBlockMode:
+ return std::make_shared<SetUserWriteBlockModeCoordinator>(std::move(initialState));
+ default:
+ uasserted(ErrorCodes::BadValue,
+ str::stream()
+ << "Encountered unknown ConfigsvrCoordinator operation type: "
+ << ConfigsvrCoordinatorType_serializer(op.getId().getCoordinatorType()));
+ }
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/s/config/configsvr_coordinator_service.h b/src/mongo/db/s/config/configsvr_coordinator_service.h
new file mode 100644
index 00000000000..86944a73c3d
--- /dev/null
+++ b/src/mongo/db/s/config/configsvr_coordinator_service.h
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2022-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
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "mongo/db/repl/primary_only_service.h"
+#include "mongo/db/s/config/configsvr_coordinator_gen.h"
+
+namespace mongo {
+
+class ConfigsvrCoordinatorService final : public repl::PrimaryOnlyService {
+public:
+ static constexpr StringData kServiceName = "ConfigsvrCoordinatorService"_sd;
+
+ explicit ConfigsvrCoordinatorService(ServiceContext* serviceContext)
+ : PrimaryOnlyService(serviceContext) {}
+
+ ~ConfigsvrCoordinatorService() = default;
+
+ static ConfigsvrCoordinatorService* getService(OperationContext* opCtx);
+
+ StringData getServiceName() const override {
+ return kServiceName;
+ }
+
+ NamespaceString getStateDocumentsNS() const override {
+ return NamespaceString::kConfigsvrCoordinatorsNamespace;
+ }
+
+ ThreadPool::Limits getThreadPoolLimits() const override {
+ return ThreadPool::Limits();
+ }
+
+ void checkIfConflictsWithOtherInstances(
+ OperationContext* opCtx,
+ BSONObj initialState,
+ const std::vector<const PrimaryOnlyService::Instance*>& existingInstances) override{};
+
+ std::shared_ptr<Instance> constructInstance(BSONObj initialState) override;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/s/config/configsvr_set_user_write_block_mode_command.cpp b/src/mongo/db/s/config/configsvr_set_user_write_block_mode_command.cpp
new file mode 100644
index 00000000000..6d43eeda0dc
--- /dev/null
+++ b/src/mongo/db/s/config/configsvr_set_user_write_block_mode_command.cpp
@@ -0,0 +1,116 @@
+/**
+ * Copyright (C) 2022-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
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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.
+ */
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kSharding
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/commands.h"
+#include "mongo/db/s/config/configsvr_coordinator_service.h"
+#include "mongo/db/s/config/set_user_write_block_mode_coordinator.h"
+#include "mongo/db/server_feature_flags_gen.h"
+#include "mongo/logv2/log.h"
+#include "mongo/s/grid.h"
+#include "mongo/s/request_types/sharded_ddl_commands_gen.h"
+
+namespace mongo {
+namespace {
+
+class ConfigsvrSetUserWriteBlockModeCommand final
+ : public TypedCommand<ConfigsvrSetUserWriteBlockModeCommand> {
+public:
+ using Request = ConfigsvrSetUserWriteBlockMode;
+
+ class Invocation final : public InvocationBase {
+ public:
+ using InvocationBase::InvocationBase;
+
+ void typedRun(OperationContext* opCtx) {
+ uassert(ErrorCodes::IllegalOperation,
+ str::stream() << Request::kCommandName << " can only be run on config servers",
+ serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
+ uassert(
+ ErrorCodes::IllegalOperation,
+ "featureFlagUserWriteBlocking not enabled",
+ gFeatureFlagUserWriteBlocking.isEnabled(serverGlobalParams.featureCompatibility));
+
+ const auto startBlocking = request().getCommandParameter();
+
+ SetUserWriteBlockModeCoordinatorDocument coordinatorDoc{startBlocking};
+ coordinatorDoc.setConfigsvrCoordinatorMetadata(
+ {ConfigsvrCoordinatorTypeEnum::kSetUserWriteBlockMode});
+ const auto coordinatorDocBSON = coordinatorDoc.toBSON();
+
+ const auto service = ConfigsvrCoordinatorService::getService(opCtx);
+ const auto instance = checked_pointer_cast<SetUserWriteBlockModeCoordinator>(
+ SetUserWriteBlockModeCoordinator::getOrCreate(opCtx, service, coordinatorDocBSON));
+ uassert(ErrorCodes::ConflictingOperationInProgress,
+ "Another SetUserWriteBlockMode with different arguments is already running",
+ instance->hasSameOptions(coordinatorDocBSON));
+
+ instance->getCompletionFuture().get(opCtx);
+ }
+
+ private:
+ NamespaceString ns() const override {
+ return NamespaceString(request().getDbName());
+ }
+
+ bool supportsWriteConcern() const override {
+ return true;
+ }
+
+ void doCheckAuthorization(OperationContext* opCtx) const override {
+ uassert(ErrorCodes::Unauthorized,
+ "Unauthorized",
+ AuthorizationSession::get(opCtx->getClient())
+ ->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
+ ActionType::internal));
+ }
+ };
+
+ std::string help() const override {
+ return "Internal command, which is exported by the config servers. Do not call "
+ "directly. Sets the user write blocking mode on a sharded cluster.";
+ }
+
+ bool adminOnly() const override {
+ return true;
+ }
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kNever;
+ }
+} configsvrSetUserWriteBlockModeCmd;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/db/s/config/set_user_write_block_mode_coordinator.cpp b/src/mongo/db/s/config/set_user_write_block_mode_coordinator.cpp
new file mode 100644
index 00000000000..9d4c1fbc9be
--- /dev/null
+++ b/src/mongo/db/s/config/set_user_write_block_mode_coordinator.cpp
@@ -0,0 +1,98 @@
+/**
+ * Copyright (C) 2022-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
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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.
+ */
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kSharding
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/s/config/set_user_write_block_mode_coordinator.h"
+
+#include "mongo/base/checked_cast.h"
+#include "mongo/db/persistent_task_store.h"
+#include "mongo/logv2/log.h"
+#include "mongo/s/request_types/sharded_ddl_commands_gen.h"
+
+namespace mongo {
+
+bool SetUserWriteBlockModeCoordinator::hasSameOptions(const BSONObj& otherDocBSON) {
+ const auto otherDoc = StateDoc::parse(
+ IDLParserErrorContext("SetUserWriteBlockModeCoordinatorDocument"), otherDocBSON);
+
+ return _doc.getBlock() == otherDoc.getBlock();
+}
+
+boost::optional<BSONObj> SetUserWriteBlockModeCoordinator::reportForCurrentOp(
+ MongoProcessInterface::CurrentOpConnectionsMode connMode,
+ MongoProcessInterface::CurrentOpSessionsMode sessionMode) noexcept {
+
+ BSONObjBuilder bob;
+ bob.append("type", "op");
+ bob.append("desc", "SetUserWriteBlockModeCoordinator");
+ bob.append("op", "command");
+ bob.append("currentPhase", _doc.getPhase());
+ bob.append("active", true);
+ return bob.obj();
+}
+
+void SetUserWriteBlockModeCoordinator::_enterPhase(Phase newPhase) {
+ StateDoc newDoc(_doc);
+ newDoc.setPhase(newPhase);
+
+ LOGV2_DEBUG(
+ 6347305,
+ 2,
+ "SetUserWriteBlockModeCoordinator phase transition",
+ "newPhase"_attr = SetUserWriteBlockModeCoordinatorPhase_serializer(newDoc.getPhase()),
+ "oldPhase"_attr = SetUserWriteBlockModeCoordinatorPhase_serializer(_doc.getPhase()));
+
+ auto opCtx = cc().makeOperationContext();
+ PersistentTaskStore<StateDoc> store(NamespaceString::kConfigsvrCoordinatorsNamespace);
+
+ if (_doc.getPhase() == Phase::kUnset) {
+ store.add(opCtx.get(), newDoc, WriteConcerns::kMajorityWriteConcernShardingTimeout);
+ } else {
+ store.update(opCtx.get(),
+ BSON(StateDoc::kIdFieldName << _coordId.toBSON()),
+ newDoc.toBSON(),
+ WriteConcerns::kMajorityWriteConcernNoTimeout);
+ }
+
+ _doc = std::move(newDoc);
+}
+
+ExecutorFuture<void> SetUserWriteBlockModeCoordinator::_runImpl(
+ std::shared_ptr<executor::ScopedTaskExecutor> executor,
+ const CancellationToken& token) noexcept {
+ return ExecutorFuture<void>(**executor)
+ .then(_executePhase(Phase::kSetUserWriteBlockMode, [this, anchor = shared_from_this()] {
+ // TODO Implement
+ }));
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/s/config/set_user_write_block_mode_coordinator.h b/src/mongo/db/s/config/set_user_write_block_mode_coordinator.h
new file mode 100644
index 00000000000..f6128e9cc23
--- /dev/null
+++ b/src/mongo/db/s/config/set_user_write_block_mode_coordinator.h
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2022-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
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "mongo/db/internal_session_pool.h"
+#include "mongo/db/s/config/configsvr_coordinator.h"
+#include "mongo/db/s/config/set_user_write_block_mode_coordinator_document_gen.h"
+
+namespace mongo {
+
+class SetUserWriteBlockModeCoordinator : public ConfigsvrCoordinator {
+public:
+ using StateDoc = SetUserWriteBlockModeCoordinatorDocument;
+ using Phase = SetUserWriteBlockModeCoordinatorPhaseEnum;
+
+ explicit SetUserWriteBlockModeCoordinator(const BSONObj& stateDoc)
+ : ConfigsvrCoordinator(stateDoc),
+ _doc(StateDoc::parse(IDLParserErrorContext("SetUserWriteBlockModeCoordinatorDocument"),
+ stateDoc)) {}
+
+ bool hasSameOptions(const BSONObj& participantDoc);
+
+ boost::optional<BSONObj> reportForCurrentOp(
+ MongoProcessInterface::CurrentOpConnectionsMode connMode,
+ MongoProcessInterface::CurrentOpSessionsMode sessionMode) noexcept override;
+
+private:
+ StateDoc _doc;
+
+ ExecutorFuture<void> _runImpl(std::shared_ptr<executor::ScopedTaskExecutor> executor,
+ const CancellationToken& token) noexcept override;
+
+ template <typename Func>
+ auto _executePhase(const Phase& newPhase, Func&& func) {
+ return [=] {
+ const auto& currPhase = _doc.getPhase();
+
+ if (currPhase > newPhase) {
+ // Do not execute this phase if we already reached a subsequent one.
+ return;
+ }
+ if (currPhase < newPhase) {
+ // Persist the new phase if this is the first time we are executing it.
+ _enterPhase(newPhase);
+ }
+ return func();
+ };
+ }
+
+ void _removeStateDocument(OperationContext* opCtx);
+ void _enterPhase(Phase newPhase);
+ void _invalidateFutures(const Status& errStatus);
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/s/config/set_user_write_block_mode_coordinator_document.idl b/src/mongo/db/s/config/set_user_write_block_mode_coordinator_document.idl
new file mode 100644
index 00000000000..cf9f2a2dcd5
--- /dev/null
+++ b/src/mongo/db/s/config/set_user_write_block_mode_coordinator_document.idl
@@ -0,0 +1,58 @@
+# Copyright (C) 2022-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
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# 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.
+#
+
+
+global:
+ cpp_namespace: "mongo"
+
+imports:
+ - "mongo/db/s/config/configsvr_coordinator.idl"
+ - "mongo/idl/basic_types.idl"
+ - "mongo/s/request_types/sharded_ddl_commands.idl"
+
+enums:
+ SetUserWriteBlockModeCoordinatorPhase:
+ description: "Current refine collection shard key coordinator's operation state."
+ type: string
+ values:
+ kUnset: "unset"
+ kSetUserWriteBlockMode: "setUserWriteBlockMode"
+
+structs:
+ SetUserWriteBlockModeCoordinatorDocument:
+ description: ""
+ generate_comparison_operators: false
+ strict: false
+ chained_structs:
+ ConfigsvrCoordinatorMetadata: ConfigsvrCoordinatorMetadata
+ fields:
+ block: bool
+ phase:
+ type: SetUserWriteBlockModeCoordinatorPhase
+ description: "Coordinator phase."
+ default: kUnset
diff --git a/src/mongo/s/request_types/sharded_ddl_commands.idl b/src/mongo/s/request_types/sharded_ddl_commands.idl
index c3a7a7f15be..d21a1da70b7 100644
--- a/src/mongo/s/request_types/sharded_ddl_commands.idl
+++ b/src/mongo/s/request_types/sharded_ddl_commands.idl
@@ -368,3 +368,12 @@ commands:
namespace: concatenate_with_db
chained_structs:
CollModRequest: CollModRequest
+
+ _configsvrSetUserWriteBlockMode:
+ command_name: _configsvrSetUserWriteBlockMode
+ cpp_name: ConfigsvrSetUserWriteBlockMode
+ description: "internal _configsvrSetUserWriteBlockMode command"
+ namespace: type
+ api_version: ""
+ type: bool
+ strict: false