From 4ff5abf776772827db06bcc941382e3822731d3a Mon Sep 17 00:00:00 2001 From: Jaume Moragues Date: Wed, 25 Nov 2020 09:38:55 +0000 Subject: SERVER-52810 Create the _shardsvrDropDatabase command --- jstests/core/views/views_all_commands.js | 1 + .../db_reads_while_recovering_all_commands.js | 1 + .../read_write_concern_defaults_application.js | 1 + src/mongo/db/s/SConscript | 1 + src/mongo/db/s/shardsvr_drop_database_command.cpp | 107 +++++++++++++++++++++ src/mongo/s/SConscript | 1 + src/mongo/s/commands/cluster_drop_database_cmd.cpp | 63 +++++++----- src/mongo/s/request_types/sharded_ddl_commands.idl | 44 +++++++++ 8 files changed, 196 insertions(+), 23 deletions(-) create mode 100644 src/mongo/db/s/shardsvr_drop_database_command.cpp create mode 100644 src/mongo/s/request_types/sharded_ddl_commands.idl diff --git a/jstests/core/views/views_all_commands.js b/jstests/core/views/views_all_commands.js index 125c9904e18..fe39fe6fc33 100644 --- a/jstests/core/views/views_all_commands.js +++ b/jstests/core/views/views_all_commands.js @@ -119,6 +119,7 @@ let viewsCommandTests = { _shardsvrMovePrimary: {skip: isAnInternalCommand}, _shardsvrRenameCollection: {skip: isAnInternalCommand}, _shardsvrShardCollection: {skip: isAnInternalCommand}, + _shardsvrDropDatabase: {skip: isAnInternalCommand}, _transferMods: {skip: isAnInternalCommand}, _vectorClockPersist: {skip: isAnInternalCommand}, abortTransaction: {skip: isUnrelated}, diff --git a/jstests/replsets/db_reads_while_recovering_all_commands.js b/jstests/replsets/db_reads_while_recovering_all_commands.js index 1d91b91e00a..bbcc3a03db2 100644 --- a/jstests/replsets/db_reads_while_recovering_all_commands.js +++ b/jstests/replsets/db_reads_while_recovering_all_commands.js @@ -66,6 +66,7 @@ const allCommands = { _shardsvrCloneCatalogData: {skip: isPrimaryOnly}, _shardsvrMovePrimary: {skip: isPrimaryOnly}, _shardsvrShardCollection: {skip: isPrimaryOnly}, + _shardsvrDropDatabase: {skip: isPrimaryOnly}, _transferMods: {skip: isPrimaryOnly}, _vectorClockPersist: {skip: isPrimaryOnly}, abortTransaction: {skip: isPrimaryOnly}, diff --git a/jstests/sharding/read_write_concern_defaults_application.js b/jstests/sharding/read_write_concern_defaults_application.js index 49dc5e526fb..0ba92d245fc 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 = { _shardsvrMovePrimary: {skip: "internal command"}, _shardsvrRenameCollection: {skip: "internal command"}, _shardsvrShardCollection: {skip: "internal command"}, + _shardsvrDropDatabase: {skip: "internal command"}, _transferMods: {skip: "internal command"}, _vectorClockPersist: {skip: "internal command"}, abortTransaction: { diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript index 373be39e030..f554ffc9933 100644 --- a/src/mongo/db/s/SConscript +++ b/src/mongo/db/s/SConscript @@ -336,6 +336,7 @@ env.Library( 'set_shard_version_command.cpp', 'sharding_server_status.cpp', 'sharding_state_command.cpp', + 'shardsvr_drop_database_command.cpp', 'shardsvr_shard_collection.cpp', 'split_chunk_command.cpp', 'split_vector_command.cpp', diff --git a/src/mongo/db/s/shardsvr_drop_database_command.cpp b/src/mongo/db/s/shardsvr_drop_database_command.cpp new file mode 100644 index 00000000000..5d8095ce197 --- /dev/null +++ b/src/mongo/db/s/shardsvr_drop_database_command.cpp @@ -0,0 +1,107 @@ +/** + * Copyright (C) 2018-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. + */ + +#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kSharding + +#include "mongo/db/auth/authorization_session.h" +#include "mongo/db/commands.h" +#include "mongo/db/drop_database_gen.h" +#include "mongo/db/s/config/sharding_catalog_manager.h" +#include "mongo/db/s/sharding_logging.h" +#include "mongo/s/catalog/dist_lock_manager.h" +#include "mongo/s/catalog/type_database.h" +#include "mongo/s/catalog_cache.h" +#include "mongo/s/grid.h" +#include "mongo/s/request_types/sharded_ddl_commands_gen.h" +#include "mongo/s/sharded_collections_ddl_parameters_gen.h" + +namespace mongo { +namespace { + +class ShardsvrDropDatabaseCommand final : public TypedCommand { +public: + bool acceptsAnyApiVersionParameters() const override { + return true; + } + + AllowedOnSecondary secondaryAllowed(ServiceContext*) const override { + return Command::AllowedOnSecondary::kNever; + } + + std::string help() const override { + return "Internal command, which is exported by the primary sharding server. Do not call " + "directly. Drops a database."; + } + + using Request = ShardsvrDropDatabase; + using Response = DropDatabaseReply; + + class Invocation final : public InvocationBase { + public: + using InvocationBase::InvocationBase; + + Response typedRun(OperationContext* opCtx) { + uassert(ErrorCodes::IllegalOperation, + "_shardsvrDropDatabase can only be run on primary shard servers", + serverGlobalParams.clusterRole == ClusterRole::ShardServer); + + const StringData dbName = request().getDbName(); + + const auto configShard = Grid::get(opCtx)->shardRegistry()->getConfigShard(); + auto cmdResponse = uassertStatusOK(configShard->runCommandWithFixedRetryAttempts( + opCtx, + ReadPreferenceSetting(ReadPreference::PrimaryOnly), + "admin", + CommandHelpers::appendMajorityWriteConcern(BSON("_configsvrDropDatabase" << dbName), + opCtx->getWriteConcern()), + Shard::RetryPolicy::kIdempotent)); + + uassertStatusOK(cmdResponse.commandStatus); + + return Response::parse(IDLParserErrorContext("dropDatabase-reply"), + cmdResponse.response); + } + + bool supportsWriteConcern() const override { + return true; + } + + void doCheckAuthorization(OperationContext*) const override {} + + /** + * The ns() for when Request's IDL specifies "namespace: concatenate_with_db". + */ + NamespaceString ns() const override { + return {"", ""}; + } + }; +} shardsvrDropDatabaseCommand; + +} // namespace +} // namespace mongo \ No newline at end of file diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index bf4fc8cc3a6..29518c5d5ae 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -171,6 +171,7 @@ env.Library( 'request_types/reshard_collection.idl', 'request_types/set_shard_version_request.cpp', 'request_types/shard_collection.idl', + 'request_types/sharded_ddl_commands.idl', 'request_types/split_chunk_request_type.cpp', 'request_types/update_zone_key_range_request_type.cpp', 'request_types/wait_for_fail_point.idl', diff --git a/src/mongo/s/commands/cluster_drop_database_cmd.cpp b/src/mongo/s/commands/cluster_drop_database_cmd.cpp index f96a2cef9fc..3cb36fe8518 100644 --- a/src/mongo/s/commands/cluster_drop_database_cmd.cpp +++ b/src/mongo/s/commands/cluster_drop_database_cmd.cpp @@ -35,9 +35,12 @@ #include "mongo/db/commands.h" #include "mongo/db/drop_database_gen.h" #include "mongo/db/operation_context.h" +#include "mongo/rpc/get_status_from_command_result.h" #include "mongo/s/catalog_cache.h" #include "mongo/s/client/shard_registry.h" +#include "mongo/s/cluster_commands_helpers.h" #include "mongo/s/grid.h" +#include "mongo/s/request_types/sharded_ddl_commands_gen.h" #include "mongo/util/scopeguard.h" namespace mongo { @@ -78,7 +81,6 @@ public: uassert(ErrorCodes::IllegalOperation, "Cannot drop the config database", dbname != NamespaceString::kConfigDb); - uassert(ErrorCodes::IllegalOperation, "Cannot drop the admin database", dbname != NamespaceString::kAdminDb); @@ -88,28 +90,43 @@ public: "have to pass 1 as db parameter", request.getCommandParameter() == 1); - // Invalidate the database metadata so the next access kicks off a full reload, even if - // sending the command to the config server fails due to e.g. a NetworkError. - ON_BLOCK_EXIT([opCtx, dbname] { Grid::get(opCtx)->catalogCache()->purgeDatabase(dbname); }); - - // Send _configsvrDropDatabase to the config server. - auto configShard = Grid::get(opCtx)->shardRegistry()->getConfigShard(); - auto cmdResponse = uassertStatusOK(configShard->runCommandWithFixedRetryAttempts( - opCtx, - ReadPreferenceSetting(ReadPreference::PrimaryOnly), - "admin", - CommandHelpers::appendMajorityWriteConcern( - CommandHelpers::appendGenericCommandArgs(cmdObj, - BSON("_configsvrDropDatabase" << dbname)), - opCtx->getWriteConcern()), - Shard::RetryPolicy::kIdempotent)); - - // The cmdResponse status can be OK even if the config server replied ok: 0. - uassertStatusOK(cmdResponse.commandStatus); - auto reply = DropDatabaseReply::parse(IDLParserErrorContext("dropDatabase-reply"), - cmdResponse.response); - CommandHelpers::appendGenericReplyFields(cmdResponse.response, reply.toBSON(), &result); - return true; + try { + + const CachedDatabaseInfo dbInfo = + uassertStatusOK(Grid::get(opCtx)->catalogCache()->getDatabase(opCtx, dbname)); + + // Invalidate the database metadata so the next access kicks off a full reload, even if + // sending the command to the config server fails due to e.g. a NetworkError. + ON_BLOCK_EXIT( + [opCtx, dbname] { Grid::get(opCtx)->catalogCache()->purgeDatabase(dbname); }); + + // Send it to the primary shard + ShardsvrDropDatabase dropDatabaseCommand(1); + dropDatabaseCommand.setDbName(dbname); + + auto cmdResponse = executeCommandAgainstDatabasePrimary( + opCtx, + dbname, + dbInfo, + CommandHelpers::appendMajorityWriteConcern(dropDatabaseCommand.toBSON({}), + opCtx->getWriteConcern()), + ReadPreferenceSetting(ReadPreference::PrimaryOnly), + Shard::RetryPolicy::kIdempotent); + + const auto remoteResponse = uassertStatusOK(cmdResponse.swResponse); + uassertStatusOK(getStatusFromCommandResult(remoteResponse.data)); + + auto reply = DropDatabaseReply::parse(IDLParserErrorContext("dropDatabase-reply"), + remoteResponse.data); + CommandHelpers::appendGenericReplyFields(remoteResponse.data, reply.toBSON(), &result); + + return true; + } catch (const ExceptionFor&) { + // If the namespace isn't found, treat the drop as a success but inform about the + // failure. + result.append("info", "database does not exist"); + return true; + } } } clusterDropDatabaseCmd; diff --git a/src/mongo/s/request_types/sharded_ddl_commands.idl b/src/mongo/s/request_types/sharded_ddl_commands.idl new file mode 100644 index 00000000000..cf94288655b --- /dev/null +++ b/src/mongo/s/request_types/sharded_ddl_commands.idl @@ -0,0 +1,44 @@ +# Copyright (C) 2020-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. +# + +global: + cpp_namespace: "mongo" + +imports: + - "mongo/db/drop_database.idl" + - "mongo/s/database_version.idl" + +commands: + _shardsvrDropDatabase: + description: "Parser for the shardDropDatabase command" + command_name: _shardsvrDropDatabase + namespace: type + type: safeInt64 + cpp_name: ShardsvrDropDatabase + strict: true + reply_type: DropDatabaseReply \ No newline at end of file -- cgit v1.2.1