summaryrefslogtreecommitdiff
path: root/src/mongo/db/s
diff options
context:
space:
mode:
authorAlex Taskov <alex.taskov@mongodb.com>2020-11-06 10:41:04 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-11-06 15:59:26 +0000
commit6508f5d6ad5d514f433b660f0da7f513625973be (patch)
tree4f535c406e51f33fad14641556f5b689bfcdc141 /src/mongo/db/s
parent5da1a52746a85a54b2809e8901da707a35d78e22 (diff)
downloadmongo-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.cpp31
-rw-r--r--src/mongo/db/s/resharding_util.cpp52
-rw-r--r--src/mongo/db/s/resharding_util.h7
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.