diff options
author | Jason Zhang <jason.zhang@mongodb.com> | 2019-07-18 16:55:24 -0400 |
---|---|---|
committer | Jason Zhang <jason.zhang@mongodb.com> | 2019-07-25 13:01:38 -0400 |
commit | bbd8ad370bd4f32e58a9fdbed5e9ea7167f73704 (patch) | |
tree | cba484fe6c5185688de2de8aa477845810049479 /src/mongo | |
parent | 2a4d319f02427dbc88d42578a401a14cf1b7d1ac (diff) | |
download | mongo-bbd8ad370bd4f32e58a9fdbed5e9ea7167f73704.tar.gz |
SERVER-42119 Add shardsvrRenameCollection that wraps the existing mongod renameCollection command.
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/catalog/rename_collection.cpp | 47 | ||||
-rw-r--r-- | src/mongo/db/catalog/rename_collection.h | 9 | ||||
-rw-r--r-- | src/mongo/db/commands/rename_collection_cmd.cpp | 51 | ||||
-rw-r--r-- | src/mongo/db/s/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/db/s/config/configsvr_rename_collection_command.cpp | 23 | ||||
-rw-r--r-- | src/mongo/db/s/shardsvr_rename_collection.cpp | 92 | ||||
-rw-r--r-- | src/mongo/s/request_types/rename_collection.idl | 27 |
7 files changed, 203 insertions, 48 deletions
diff --git a/src/mongo/db/catalog/rename_collection.cpp b/src/mongo/db/catalog/rename_collection.cpp index 08047b91a31..5b41b3e3539 100644 --- a/src/mongo/db/catalog/rename_collection.cpp +++ b/src/mongo/db/catalog/rename_collection.cpp @@ -682,6 +682,53 @@ Status renameBetweenDBs(OperationContext* opCtx, } } // namespace +void validateAndRunRenameCollection(OperationContext* opCtx, + const NamespaceString& source, + const NamespaceString& target, + bool dropTarget, + bool stayTemp) { + uassert(ErrorCodes::InvalidNamespace, + str::stream() << "Invalid source namespace: " << source.ns(), + source.isValid()); + uassert(ErrorCodes::InvalidNamespace, + str::stream() << "Invalid target namespace: " << target.ns(), + target.isValid()); + + if ((repl::ReplicationCoordinator::get(opCtx)->getReplicationMode() != + repl::ReplicationCoordinator::modeNone)) { + uassert(ErrorCodes::IllegalOperation, + "can't rename live oplog while replicating", + !source.isOplog()); + uassert(ErrorCodes::IllegalOperation, + "can't rename to live oplog while replicating", + !target.isOplog()); + } + + uassert(ErrorCodes::IllegalOperation, + "If either the source or target of a rename is an oplog name, both must be", + source.isOplog() == target.isOplog()); + + Status sourceStatus = userAllowedWriteNS(source); + uassert(ErrorCodes::IllegalOperation, + "error with source namespace: " + sourceStatus.reason(), + sourceStatus.isOK()); + Status targetStatus = userAllowedWriteNS(target); + uassert(ErrorCodes::IllegalOperation, + "error with target namespace: " + targetStatus.reason(), + targetStatus.isOK()); + + if (source.isServerConfigurationCollection()) { + uasserted(ErrorCodes::IllegalOperation, + "renaming the server configuration " + "collection (admin.system.version) is not " + "allowed"); + } + + RenameCollectionOptions options; + options.dropTarget = dropTarget; + options.stayTemp = stayTemp; + uassertStatusOK(renameCollection(opCtx, source, target, options)); +} Status renameCollection(OperationContext* opCtx, const NamespaceString& source, diff --git a/src/mongo/db/catalog/rename_collection.h b/src/mongo/db/catalog/rename_collection.h index 90be31102c5..20756aaaedd 100644 --- a/src/mongo/db/catalog/rename_collection.h +++ b/src/mongo/db/catalog/rename_collection.h @@ -79,5 +79,14 @@ Status renameCollectionForApplyOps(OperationContext* opCtx, Status renameCollectionForRollback(OperationContext* opCtx, const NamespaceString& target, const UUID& uuid); +/** + * Runs renameCollection() with preliminary validation checks to ensure source + * and target namespaces are elligible for rename. + */ +void validateAndRunRenameCollection(OperationContext* opCtx, + const NamespaceString& source, + const NamespaceString& target, + bool dropTarget, + bool stayTemp); } // namespace mongo diff --git a/src/mongo/db/commands/rename_collection_cmd.cpp b/src/mongo/db/commands/rename_collection_cmd.cpp index e047376f281..4778255072e 100644 --- a/src/mongo/db/commands/rename_collection_cmd.cpp +++ b/src/mongo/db/commands/rename_collection_cmd.cpp @@ -96,54 +96,9 @@ public: const NamespaceString source(sourceNsElt.valueStringData()); const NamespaceString target(targetNsElt.valueStringData()); - - uassert(ErrorCodes::InvalidNamespace, - str::stream() << "Invalid source namespace: " << source.ns(), - source.isValid()); - uassert(ErrorCodes::InvalidNamespace, - str::stream() << "Invalid target namespace: " << target.ns(), - target.isValid()); - - if ((repl::ReplicationCoordinator::get(opCtx)->getReplicationMode() != - repl::ReplicationCoordinator::modeNone)) { - if (source.isOplog()) { - errmsg = "can't rename live oplog while replicating"; - return false; - } - if (target.isOplog()) { - errmsg = "can't rename to live oplog while replicating"; - return false; - } - } - - if (source.isOplog() != target.isOplog()) { - errmsg = "If either the source or target of a rename is an oplog name, both must be"; - return false; - } - - Status sourceStatus = userAllowedWriteNS(source); - if (!sourceStatus.isOK()) { - errmsg = "error with source namespace: " + sourceStatus.reason(); - return false; - } - - Status targetStatus = userAllowedWriteNS(target); - if (!targetStatus.isOK()) { - errmsg = "error with target namespace: " + targetStatus.reason(); - return false; - } - - if (source.isServerConfigurationCollection()) { - uasserted(ErrorCodes::IllegalOperation, - "renaming the server configuration " - "collection (admin.system.version) is not " - "allowed"); - } - - RenameCollectionOptions options; - options.dropTarget = cmdObj["dropTarget"].trueValue(); - options.stayTemp = cmdObj["stayTemp"].trueValue(); - uassertStatusOK(renameCollection(opCtx, source, target, options)); + bool dropTarget = cmdObj["dropTarget"].trueValue(); + bool stayTemp = cmdObj["stayTemp"].trueValue(); + validateAndRunRenameCollection(opCtx, source, target, dropTarget, stayTemp); return true; } diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript index 62583c09cf8..33e3f69d267 100644 --- a/src/mongo/db/s/SConscript +++ b/src/mongo/db/s/SConscript @@ -284,6 +284,7 @@ env.Library( 'set_shard_version_command.cpp', 'sharding_server_status.cpp', 'sharding_state_command.cpp', + 'shardsvr_rename_collection.cpp', 'shardsvr_shard_collection.cpp', 'split_chunk_command.cpp', 'split_vector_command.cpp', @@ -293,6 +294,7 @@ env.Library( ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/db/bson/dotted_path_support', + '$BUILD_DIR/mongo/db/catalog/catalog_helpers', '$BUILD_DIR/mongo/db/cloner', '$BUILD_DIR/mongo/db/commands/mongod_fcv', '$BUILD_DIR/mongo/db/commands/server_status', diff --git a/src/mongo/db/s/config/configsvr_rename_collection_command.cpp b/src/mongo/db/s/config/configsvr_rename_collection_command.cpp index 71f30139d4f..3e988f7c6c7 100644 --- a/src/mongo/db/s/config/configsvr_rename_collection_command.cpp +++ b/src/mongo/db/s/config/configsvr_rename_collection_command.cpp @@ -89,6 +89,29 @@ public: opCtx, nssSource.ns(), "renameCollection", DistLockManager::kDefaultLockTimeout)); auto collDistLockTarget = uassertStatusOK(catalogClient->getDistLockManager()->lock( opCtx, nssTarget.ns(), "renameCollection", DistLockManager::kDefaultLockTimeout)); + + ShardsvrRenameCollection shardsvrRenameCollectionRequest; + shardsvrRenameCollectionRequest.setRenameCollection(nssSource); + shardsvrRenameCollectionRequest.setTo(nssTarget); + shardsvrRenameCollectionRequest.setDropTarget(request().getDropTarget()); + shardsvrRenameCollectionRequest.setStayTemp(request().getStayTemp()); + + const auto dbType = uassertStatusOK(Grid::get(opCtx)->catalogClient()->getDatabase( + opCtx, + nssSource.db().toString(), + repl::ReadConcernArgs::get(opCtx).getLevel())) + .value; + const auto primaryShardId = dbType.getPrimary(); + const auto primaryShard = + uassertStatusOK(Grid::get(opCtx)->shardRegistry()->getShard(opCtx, primaryShardId)); + BSONObj unusedPassthroughObj; + auto cmdResponse = uassertStatusOK(primaryShard->runCommandWithFixedRetryAttempts( + opCtx, + ReadPreferenceSetting(ReadPreference::PrimaryOnly), + "admin", + shardsvrRenameCollectionRequest.toBSON(unusedPassthroughObj), + Shard::RetryPolicy::kIdempotent)); + uassertStatusOK(cmdResponse.commandStatus); } private: diff --git a/src/mongo/db/s/shardsvr_rename_collection.cpp b/src/mongo/db/s/shardsvr_rename_collection.cpp new file mode 100644 index 00000000000..fde6c08da1d --- /dev/null +++ b/src/mongo/db/s/shardsvr_rename_collection.cpp @@ -0,0 +1,92 @@ +/** + * Copyright (C) 2019-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_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kSharding + +#include "mongo/platform/basic.h" + +#include "mongo/db/auth/authorization_session.h" +#include "mongo/db/catalog/rename_collection.h" +#include "mongo/db/commands.h" +#include "mongo/db/namespace_string.h" +#include "mongo/s/grid.h" +#include "mongo/s/request_types/rename_collection_gen.h" + +namespace mongo { +namespace { +/** + * Internal sharding command run on a primary shard server to rename a collection. + */ +class ShardSvrRenameCollectionCommand final : public TypedCommand<ShardSvrRenameCollectionCommand> { +public: + using Request = ShardsvrRenameCollection; + + class Invocation final : public InvocationBase { + public: + using InvocationBase::InvocationBase; + + void typedRun(OperationContext* opCtx) { + validateAndRunRenameCollection( + opCtx, ns(), Request().getTo(), Request().getDropTarget(), Request().getStayTemp()); + } + + private: + NamespaceString ns() const override { + return request().getRenameCollection(); + } + + 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 shards." + "Renames a collection."; + } + + bool adminOnly() const override { + return true; + } + + AllowedOnSecondary secondaryAllowed(ServiceContext*) const override { + return AllowedOnSecondary::kNever; + } +} shardSvrRenameCollectionCmd; + +} // namespace +} // namespace mongo diff --git a/src/mongo/s/request_types/rename_collection.idl b/src/mongo/s/request_types/rename_collection.idl index d8a886934c0..228da644323 100644 --- a/src/mongo/s/request_types/rename_collection.idl +++ b/src/mongo/s/request_types/rename_collection.idl @@ -51,4 +51,31 @@ commands: type: bool description: "Whether or not mongod will drop the target of renameCollection prior to renaming the collection" + default: false + stayTemp: + type: bool + description: "Whether or not we want the source collection + to be a temporary collection after the rename" + default: false + _shardsvrRenameCollection: + cpp_name: ShardsvrRenameCollection + description: "The request format of the internal renameCollection + command on a shard server." + namespace: ignored + fields: + renameCollection: + type: namespacestring + description: "The namespace of the collection to be renamed." + to: + type: namespacestring + description: "The new namespace of the collection." + dropTarget: + type: bool + description: "Whether or not mongod will drop the target of + renameCollection prior to renaming the collection" + default: false + stayTemp: + type: bool + description: "Whether or not we want the source collection + to be a temporary collection after the rename" default: false
\ No newline at end of file |