From cc088fe029f2da2deb439c4808a6a6eb280c5adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Jos=C3=A9=20Grillo=20Ram=C3=ADrez?= Date: Fri, 29 Jan 2021 13:45:06 +0100 Subject: SERVER-54015 Use catalog cache with a refresh to check if a collection was already created when sharding --- src/mongo/db/s/shard_collection_legacy.cpp | 54 ++++++++++++------------------ 1 file changed, 22 insertions(+), 32 deletions(-) (limited to 'src/mongo/db/s/shard_collection_legacy.cpp') diff --git a/src/mongo/db/s/shard_collection_legacy.cpp b/src/mongo/db/s/shard_collection_legacy.cpp index 82746f5200b..47e82cd0cc0 100644 --- a/src/mongo/db/s/shard_collection_legacy.cpp +++ b/src/mongo/db/s/shard_collection_legacy.cpp @@ -107,35 +107,32 @@ void uassertStatusOKWithWarning(const Status& status) { * If the collection is already sharded with the same options, returns the existing collection's * full spec, else returns boost::none. */ -boost::optional checkIfCollectionAlreadyShardedWithSameOptions( +boost::optional checkIfCollectionAlreadyShardedWithSameOptions( OperationContext* opCtx, const ShardsvrShardCollectionRequest& request) { - auto const catalogClient = Grid::get(opCtx)->catalogClient(); + const auto& nss = *request.get_shardsvrShardCollection(); + auto cm = uassertStatusOK( + Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh(opCtx, nss)); - CollectionType existingColl; - try { - existingColl = catalogClient->getCollection(opCtx, - *request.get_shardsvrShardCollection(), - repl::ReadConcernLevel::kMajorityReadConcern); - } catch (const ExceptionFor&) { - // Not currently sharded. + if (!cm.isSharded()) { return boost::none; } - CollectionType newColl( - *request.get_shardsvrShardCollection(), OID::gen(), Date_t::now(), UUID::gen()); - newColl.setKeyPattern(KeyPattern(request.getKey())); - newColl.setDefaultCollation(*request.getCollation()); - newColl.setUnique(request.getUnique()); + auto defaultCollator = + cm.getDefaultCollator() ? cm.getDefaultCollator()->getSpec().toBSON() : BSONObj(); // If the collection is already sharded, fail if the deduced options in this request do not // match the options the collection was originally sharded with. uassert(ErrorCodes::AlreadyInitialized, - str::stream() << "sharding already enabled for collection " - << *request.get_shardsvrShardCollection() << " with options " - << existingColl.toString(), - newColl.hasSameOptions(existingColl)); - - return existingColl; + str::stream() << "sharding already enabled for collection " << nss, + SimpleBSONObjComparator::kInstance.evaluate(cm.getShardKeyPattern().toBSON() == + request.getKey()) && + SimpleBSONObjComparator::kInstance.evaluate(defaultCollator == + *request.getCollation()) && + cm.isUnique() == request.getUnique()); + + CreateCollectionResponse response(cm.getVersion()); + response.setCollectionUUID(cm.getUUID()); + return response; } void checkForExistingChunks(OperationContext* opCtx, const NamespaceString& nss) { @@ -535,12 +532,9 @@ CreateCollectionResponse shardCollection(OperationContext* opCtx, bool mustTakeDistLock) { CreateCollectionResponse shardCollectionResponse; // Fast check for whether the collection is already sharded without taking any locks - if (auto collectionOptional = checkIfCollectionAlreadyShardedWithSameOptions(opCtx, request)) { - auto cri = - uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss)); - shardCollectionResponse.setCollectionUUID(collectionOptional->getUuid()); - shardCollectionResponse.setCollectionVersion(cri.getVersion()); - return shardCollectionResponse; + if (auto createCollectionResponseOpt = + checkIfCollectionAlreadyShardedWithSameOptions(opCtx, request)) { + return *createCollectionResponseOpt; } auto writeChunkDocumentsAndRefreshShards = @@ -603,13 +597,9 @@ CreateCollectionResponse shardCollection(OperationContext* opCtx, pauseShardCollectionReadOnlyCriticalSection.pauseWhileSet(); - if (auto collectionOptional = + if (auto createCollectionResponseOpt = checkIfCollectionAlreadyShardedWithSameOptions(opCtx, request)) { - auto cri = uassertStatusOK( - Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo(opCtx, nss)); - shardCollectionResponse.setCollectionUUID(collectionOptional->getUuid()); - shardCollectionResponse.setCollectionVersion(cri.getVersion()); - return shardCollectionResponse; + return *createCollectionResponseOpt; } // If DistLock must not be taken, then the request came from the config server, there is no -- cgit v1.2.1