diff options
author | Pierlauro Sciarelli <pierlauro.sciarelli@mongodb.com> | 2021-09-10 13:18:07 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-09-10 13:59:35 +0000 |
commit | 35dd7411084701594e0912be7964c18d06886baf (patch) | |
tree | 81874b07ae2c262067b80a73c2c06882e1286d55 /src/mongo | |
parent | 8276455d9f89aac81ba8dda8f9364cde3872f1c8 (diff) | |
download | mongo-35dd7411084701594e0912be7964c18d06886baf.tar.gz |
SERVER-59756 ShardServerProcessInterface's rename must synchronize with DDL operations
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/commands/internal_rename_if_options_and_indexes_match_cmd.cpp | 54 | ||||
-rw-r--r-- | src/mongo/db/pipeline/process_interface/shardsvr_process_interface.cpp | 2 |
2 files changed, 45 insertions, 11 deletions
diff --git a/src/mongo/db/commands/internal_rename_if_options_and_indexes_match_cmd.cpp b/src/mongo/db/commands/internal_rename_if_options_and_indexes_match_cmd.cpp index 2bce9d0d65f..f9648db8105 100644 --- a/src/mongo/db/commands/internal_rename_if_options_and_indexes_match_cmd.cpp +++ b/src/mongo/db/commands/internal_rename_if_options_and_indexes_match_cmd.cpp @@ -36,8 +36,12 @@ #include "mongo/db/commands.h" #include "mongo/db/db_raii.h" #include "mongo/db/s/collection_sharding_state.h" +#include "mongo/db/s/database_sharding_state.h" +#include "mongo/db/s/dist_lock_manager.h" namespace mongo { +MONGO_FAIL_POINT_DEFINE(blockBeforeInternalRenameIfOptionsAndIndexesMatch); + namespace { bool isCollectionSharded(OperationContext* opCtx, const NamespaceString& nss) { @@ -62,26 +66,56 @@ public: void typedRun(OperationContext* opCtx) { auto thisRequest = request(); - auto toNss = thisRequest.getTo(); + const auto& fromNss = thisRequest.getFrom(); + const auto& toNss = thisRequest.getTo(); + const auto& originalIndexes = thisRequest.getIndexes(); + const auto indexList = + std::list<BSONObj>(originalIndexes.begin(), originalIndexes.end()); + const auto& collectionOptions = thisRequest.getCollectionOptions(); + + if (serverGlobalParams.clusterRole != ClusterRole::ShardServer) { + // No need to acquire additional locks in a non-sharded environment + _internalRun(opCtx, fromNss, toNss, indexList, collectionOptions); + return; + } + + // Check if the receiving shard is still the primary for the database + DatabaseShardingState::checkIsPrimaryShardForDb(opCtx, fromNss.db()); + + // Acquiring the local part of the distributed locks for involved namespaces allows: + // - Serialize with sharded DDLs, ensuring no concurrent modifications of the + // collections. + // - Check safely if the target collection is sharded or not. + auto distLockManager = DistLockManager::get(opCtx); + auto fromLocalDistlock = distLockManager->lockDirectLocally( + opCtx, fromNss.ns(), DistLockManager::kDefaultLockTimeout); + auto toLocalDistLock = distLockManager->lockDirectLocally( + opCtx, toNss.ns(), DistLockManager::kDefaultLockTimeout); uassert(ErrorCodes::IllegalOperation, str::stream() << "cannot rename to sharded collection '" << toNss << "'", !isCollectionSharded(opCtx, toNss)); - auto originalIndexes = thisRequest.getIndexes(); - auto indexList = std::list<BSONObj>(originalIndexes.begin(), originalIndexes.end()); + _internalRun(opCtx, fromNss, toNss, indexList, collectionOptions); + } + + private: + static void _internalRun(OperationContext* opCtx, + const NamespaceString& fromNss, + const NamespaceString& toNss, + const std::list<BSONObj>& indexList, + const BSONObj& collectionOptions) { + if (MONGO_unlikely(blockBeforeInternalRenameIfOptionsAndIndexesMatch.shouldFail())) { + blockBeforeInternalRenameIfOptionsAndIndexesMatch.pauseWhileSet(); + } + RenameCollectionOptions options; options.dropTarget = true; options.stayTemp = false; - doLocalRenameIfOptionsAndIndexesHaveNotChanged(opCtx, - thisRequest.getFrom(), - toNss, - options, - std::move(indexList), - thisRequest.getCollectionOptions()); + doLocalRenameIfOptionsAndIndexesHaveNotChanged( + opCtx, fromNss, toNss, options, std::move(indexList), collectionOptions); } - private: NamespaceString ns() const override { return request().getFrom(); } diff --git a/src/mongo/db/pipeline/process_interface/shardsvr_process_interface.cpp b/src/mongo/db/pipeline/process_interface/shardsvr_process_interface.cpp index d9ecc4ce655..104dcf3bc8a 100644 --- a/src/mongo/db/pipeline/process_interface/shardsvr_process_interface.cpp +++ b/src/mongo/db/pipeline/process_interface/shardsvr_process_interface.cpp @@ -225,7 +225,7 @@ void ShardServerProcessInterface::renameIfOptionsAndIndexesHaveNotChanged( // internalRenameIfOptionsAndIndexesMatch is adminOnly. NamespaceString::kAdminDb, cachedDbInfo, - // Only unsharded collections can be renamed. + // $out target collection must not exist or not be sharded. _versionCommandIfAppropriate(newCmdObj, cachedDbInfo, ChunkVersion::UNSHARDED()), ReadPreferenceSetting(ReadPreference::PrimaryOnly), Shard::RetryPolicy::kNoRetry); |