summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorJason Zhang <jason.zhang@mongodb.com>2019-07-18 16:55:24 -0400
committerJason Zhang <jason.zhang@mongodb.com>2019-07-25 13:01:38 -0400
commitbbd8ad370bd4f32e58a9fdbed5e9ea7167f73704 (patch)
treecba484fe6c5185688de2de8aa477845810049479 /src/mongo
parent2a4d319f02427dbc88d42578a401a14cf1b7d1ac (diff)
downloadmongo-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.cpp47
-rw-r--r--src/mongo/db/catalog/rename_collection.h9
-rw-r--r--src/mongo/db/commands/rename_collection_cmd.cpp51
-rw-r--r--src/mongo/db/s/SConscript2
-rw-r--r--src/mongo/db/s/config/configsvr_rename_collection_command.cpp23
-rw-r--r--src/mongo/db/s/shardsvr_rename_collection.cpp92
-rw-r--r--src/mongo/s/request_types/rename_collection.idl27
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