summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorJamie Heppenstall <jamie.heppenstall@mongodb.com>2019-06-28 17:56:34 -0400
committerJamie Heppenstall <jamie.heppenstall@mongodb.com>2019-07-03 14:06:23 -0400
commit558bc6285f0410c9d48fb491173212408bc6b48d (patch)
tree073afff8568c0a3a581e857199ab8970314ace74 /src/mongo
parentf747b5477375197f4bef6e2e06899f7f974b9151 (diff)
downloadmongo-558bc6285f0410c9d48fb491173212408bc6b48d.tar.gz
SERVER-41943 Validate the given namespace for refineCollectionShardKey
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp38
-rw-r--r--src/mongo/s/commands/cluster_refine_collection_shard_key_cmd.cpp19
-rw-r--r--src/mongo/s/request_types/refine_collection_shard_key.idl5
3 files changed, 57 insertions, 5 deletions
diff --git a/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp b/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp
index e31af7aa0de..37b8d03b4e7 100644
--- a/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp
+++ b/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp
@@ -33,6 +33,8 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/commands.h"
+#include "mongo/s/catalog/dist_lock_manager.h"
+#include "mongo/s/grid.h"
#include "mongo/s/request_types/refine_collection_shard_key_gen.h"
#include "mongo/util/log.h"
@@ -49,18 +51,50 @@ public:
using InvocationBase::InvocationBase;
void typedRun(OperationContext* opCtx) {
+ const NamespaceString& nss = ns();
+
uassert(ErrorCodes::IllegalOperation,
"_configsvrRefineCollectionShardKey can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
uassert(ErrorCodes::InvalidOptions,
- str::stream()
- << "refineCollectionShardKey must be called with majority writeConcern",
+ "refineCollectionShardKey must be called with majority writeConcern",
opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
// Set the operation context read concern level to local for reads into the config
// database.
repl::ReadConcernArgs::get(opCtx) =
repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern);
+
+ const auto catalogClient = Grid::get(opCtx)->catalogClient();
+
+ // Acquire distlocks on the namespace's database and collection.
+ DistLockManager::ScopedDistLock dbDistLock(uassertStatusOK(
+ catalogClient->getDistLockManager()->lock(opCtx,
+ nss.db(),
+ "refineCollectionShardKey",
+ DistLockManager::kDefaultLockTimeout)));
+ DistLockManager::ScopedDistLock collDistLock(uassertStatusOK(
+ catalogClient->getDistLockManager()->lock(opCtx,
+ nss.ns(),
+ "refineCollectionShardKey",
+ DistLockManager::kDefaultLockTimeout)));
+
+ const auto collStatus =
+ catalogClient->getCollection(opCtx, nss, repl::ReadConcernLevel::kLocalReadConcern);
+
+ uassert(ErrorCodes::NamespaceNotSharded,
+ str::stream() << "refineCollectionShardKey namespace " << nss.toString()
+ << " is not sharded",
+ collStatus != ErrorCodes::NamespaceNotFound);
+
+ const auto collType = uassertStatusOK(collStatus).value;
+
+ uassert(ErrorCodes::StaleEpoch,
+ str::stream()
+ << "refineCollectionShardKey namespace "
+ << nss.toString()
+ << " has a different epoch than mongos had in its routing table cache",
+ request().getEpoch() == collType.getEpoch());
}
private:
diff --git a/src/mongo/s/commands/cluster_refine_collection_shard_key_cmd.cpp b/src/mongo/s/commands/cluster_refine_collection_shard_key_cmd.cpp
index fa96a95b10f..23d8d1a3314 100644
--- a/src/mongo/s/commands/cluster_refine_collection_shard_key_cmd.cpp
+++ b/src/mongo/s/commands/cluster_refine_collection_shard_key_cmd.cpp
@@ -35,11 +35,14 @@
#include "mongo/db/commands.h"
#include "mongo/s/grid.h"
#include "mongo/s/request_types/refine_collection_shard_key_gen.h"
+#include "mongo/util/fail_point_service.h"
#include "mongo/util/log.h"
namespace mongo {
namespace {
+MONGO_FAIL_POINT_DEFINE(hangRefineCollectionShardKeyAfterRefresh);
+
class RefineCollectionShardKeyCommand final : public TypedCommand<RefineCollectionShardKeyCommand> {
public:
using Request = RefineCollectionShardKey;
@@ -49,13 +52,23 @@ public:
using InvocationBase::InvocationBase;
void typedRun(OperationContext* opCtx) {
- const NamespaceString nss = ns();
+ const NamespaceString& nss = ns();
+
+ const auto routingInfo = uassertStatusOK(
+ Grid::get(opCtx)->catalogCache()->getShardedCollectionRoutingInfoWithRefresh(opCtx,
+ nss));
- ConfigsvrRefineCollectionShardKey configsvrRefineCollShardKey(nss, request().getKey());
+ if (MONGO_FAIL_POINT(hangRefineCollectionShardKeyAfterRefresh)) {
+ log() << "Hit hangRefineCollectionShardKeyAfterRefresh failpoint";
+ MONGO_FAIL_POINT_PAUSE_WHILE_SET_OR_INTERRUPTED(
+ opCtx, hangRefineCollectionShardKeyAfterRefresh);
+ }
+
+ ConfigsvrRefineCollectionShardKey configsvrRefineCollShardKey(
+ nss, request().getKey(), routingInfo.cm()->getVersion().epoch());
configsvrRefineCollShardKey.setDbName(request().getDbName());
auto configShard = Grid::get(opCtx)->shardRegistry()->getConfigShard();
-
auto cmdResponse = uassertStatusOK(configShard->runCommandWithFixedRetryAttempts(
opCtx,
ReadPreferenceSetting(ReadPreference::PrimaryOnly),
diff --git a/src/mongo/s/request_types/refine_collection_shard_key.idl b/src/mongo/s/request_types/refine_collection_shard_key.idl
index bd6284b2709..5b03128620f 100644
--- a/src/mongo/s/request_types/refine_collection_shard_key.idl
+++ b/src/mongo/s/request_types/refine_collection_shard_key.idl
@@ -57,3 +57,8 @@ commands:
type: object
description: "The index specification document to use as the new shard key."
optional: false
+ epoch:
+ type: objectid
+ description: "The expected epoch of the namespace provided to
+ refineCollectionShardKey."
+ optional: false