diff options
author | Jordi Serra Torrens <jordi.serra-torrens@mongodb.com> | 2022-02-11 08:35:23 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-02-11 09:27:41 +0000 |
commit | 58b7a5be37e56989f015d6964cb31df073b95168 (patch) | |
tree | 1113fde65757386782877c35faf5d303526546ef | |
parent | bf11296b533b07bd4b87f64e7477cc147c7697ea (diff) | |
download | mongo-58b7a5be37e56989f015d6964cb31df073b95168.tar.gz |
SERVER-63473 Create SetUserWriteBlockMode configsvr coordinator
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 |