diff options
author | Alex Taskov <alex.taskov@mongodb.com> | 2020-11-06 10:41:04 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-11-06 15:59:26 +0000 |
commit | 6508f5d6ad5d514f433b660f0da7f513625973be (patch) | |
tree | 4f535c406e51f33fad14641556f5b689bfcdc141 /src/mongo/db/s | |
parent | 5da1a52746a85a54b2809e8901da707a35d78e22 (diff) | |
download | mongo-6508f5d6ad5d514f433b660f0da7f513625973be.tar.gz |
SERVER-49825 Replicate updates changing value under new shard key pattern as delete + insert in a transaction
Diffstat (limited to 'src/mongo/db/s')
-rw-r--r-- | src/mongo/db/s/resharding_destined_recipient_test.cpp | 31 | ||||
-rw-r--r-- | src/mongo/db/s/resharding_util.cpp | 52 | ||||
-rw-r--r-- | src/mongo/db/s/resharding_util.h | 7 |
3 files changed, 66 insertions, 24 deletions
diff --git a/src/mongo/db/s/resharding_destined_recipient_test.cpp b/src/mongo/db/s/resharding_destined_recipient_test.cpp index ba3579501de..7e3a1c9f3bc 100644 --- a/src/mongo/db/s/resharding_destined_recipient_test.cpp +++ b/src/mongo/db/s/resharding_destined_recipient_test.cpp @@ -216,6 +216,7 @@ protected: _mockCatalogCacheLoader->setCollectionRefreshValues( env.tempNss, collType, createChunks(env.version.epoch(), "y"), boost::none); + forceDatabaseRefresh(opCtx, kNss.db()); forceShardFilteringMetadataRefresh(opCtx, kNss); if (refreshTempNss) @@ -474,5 +475,35 @@ TEST_F(DestinedRecipientTest, TestOpObserverSetsDestinedRecipientOnDeletesInTran ASSERT_EQ(*recipShard, env.destShard); } +TEST_F(DestinedRecipientTest, TestUpdateChangesOwningShardThrows) { + auto opCtx = operationContext(); + + DBDirectClient client(opCtx); + client.insert(kNss.toString(), BSON("_id" << 0 << "x" << 2 << "y" << 2 << "z" << 4)); + + auto env = setupReshardingEnv(opCtx, true); + + ASSERT_THROWS(runInTransaction( + opCtx, + [&]() { + updateDoc( + opCtx, kNss, BSON("_id" << 0), BSON("$set" << BSON("y" << 50)), env); + }), + ExceptionFor<ErrorCodes::WouldChangeOwningShard>); +} + +TEST_F(DestinedRecipientTest, TestUpdateSameOwningShard) { + auto opCtx = operationContext(); + + DBDirectClient client(opCtx); + client.insert(kNss.toString(), BSON("_id" << 0 << "x" << 2 << "y" << 2 << "z" << 4)); + + auto env = setupReshardingEnv(opCtx, true); + + runInTransaction(opCtx, [&]() { + updateDoc(opCtx, kNss, BSON("_id" << 0), BSON("$set" << BSON("y" << 3)), env); + }); +} + } // namespace } // namespace mongo diff --git a/src/mongo/db/s/resharding_util.cpp b/src/mongo/db/s/resharding_util.cpp index 31ba54feecb..3954023bd15 100644 --- a/src/mongo/db/s/resharding_util.cpp +++ b/src/mongo/db/s/resharding_util.cpp @@ -85,29 +85,6 @@ bool documentBelongsToMe(OperationContext* opCtx, return ownershipFilter.keyBelongsToMe(currentKeyPattern.extractShardKeyFromDoc(doc)); } -boost::optional<TypeCollectionDonorFields> getDonorFields(OperationContext* opCtx, - const NamespaceString& sourceNss, - const BSONObj& fullDocument) { - auto css = CollectionShardingState::get(opCtx, sourceNss); - auto collDesc = css->getCollectionDescription(opCtx); - - if (!collDesc.isSharded()) - return boost::none; - - const auto& reshardingFields = collDesc.getReshardingFields(); - if (!reshardingFields) - return boost::none; - - const auto& donorFields = reshardingFields->getDonorFields(); - if (!donorFields) - return boost::none; - - if (!documentBelongsToMe(opCtx, css, fullDocument)) - return boost::none; - - return donorFields; -} - } // namespace DonorShardEntry makeDonorShard(ShardId shardId, @@ -648,13 +625,40 @@ std::unique_ptr<Pipeline, PipelineDeleter> createAggForCollectionCloning( return Pipeline::create(std::move(stages), expCtx); } +namespace resharding { + +boost::optional<TypeCollectionDonorFields> getDonorFields(OperationContext* opCtx, + const NamespaceString& sourceNss, + const BSONObj& fullDocument) { + auto css = CollectionShardingState::get(opCtx, sourceNss); + auto collDesc = css->getCollectionDescription(opCtx); + + if (!collDesc.isSharded()) + return boost::none; + + const auto& reshardingFields = collDesc.getReshardingFields(); + if (!reshardingFields) + return boost::none; + + const auto& donorFields = reshardingFields->getDonorFields(); + if (!donorFields) + return boost::none; + + return donorFields; +} + +} // namespace resharding + boost::optional<ShardId> getDestinedRecipient(OperationContext* opCtx, const NamespaceString& sourceNss, const BSONObj& fullDocument) { - auto donorFields = getDonorFields(opCtx, sourceNss, fullDocument); + auto donorFields = resharding::getDonorFields(opCtx, sourceNss, fullDocument); if (!donorFields) return boost::none; + if (!documentBelongsToMe(opCtx, CollectionShardingState::get(opCtx, sourceNss), fullDocument)) + return boost::none; + bool allowLocks = true; auto tempNssRoutingInfo = Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfo( opCtx, diff --git a/src/mongo/db/s/resharding_util.h b/src/mongo/db/s/resharding_util.h index 071e9da6227..31ed606f1a8 100644 --- a/src/mongo/db/s/resharding_util.h +++ b/src/mongo/db/s/resharding_util.h @@ -177,6 +177,13 @@ std::unique_ptr<Pipeline, PipelineDeleter> createOplogFetchingPipelineForReshard const ShardId& recipientShard, bool doesDonorOwnMinKeyChunk); +namespace resharding { + +boost::optional<TypeCollectionDonorFields> getDonorFields(OperationContext* opCtx, + const NamespaceString& sourceNss, + const BSONObj& fullDocument); +} + /** * Returns the shard Id of the recipient shard that would own the document under the new shard * key pattern. |