diff options
author | Jamie Heppenstall <jamie.heppenstall@mongodb.com> | 2019-06-28 17:56:34 -0400 |
---|---|---|
committer | Jamie Heppenstall <jamie.heppenstall@mongodb.com> | 2019-07-03 14:06:23 -0400 |
commit | 558bc6285f0410c9d48fb491173212408bc6b48d (patch) | |
tree | 073afff8568c0a3a581e857199ab8970314ace74 /src/mongo | |
parent | f747b5477375197f4bef6e2e06899f7f974b9151 (diff) | |
download | mongo-558bc6285f0410c9d48fb491173212408bc6b48d.tar.gz |
SERVER-41943 Validate the given namespace for refineCollectionShardKey
Diffstat (limited to 'src/mongo')
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 |