summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorJack Mulrow <jack.mulrow@mongodb.com>2020-02-12 16:20:43 +0000
committerevergreen <evergreen@mongodb.com>2020-02-12 16:20:43 +0000
commit3e59bad319da75f2ad51a13ac3239bd21e74c41e (patch)
tree3c0f47597781502016ba5e0509d14cbbef29722b /src/mongo
parent436b0e57a57f8f5ae23d2a58c25ac488d5a8cef3 (diff)
downloadmongo-3e59bad319da75f2ad51a13ac3239bd21e74c41e.tar.gz
SERVER-45900 Check for unsharded collection when submitting range deletion task
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/s/migration_util.cpp21
-rw-r--r--src/mongo/db/s/migration_util_test.cpp73
2 files changed, 86 insertions, 8 deletions
diff --git a/src/mongo/db/s/migration_util.cpp b/src/mongo/db/s/migration_util.cpp
index ff3d10e6537..58f9198057c 100644
--- a/src/mongo/db/s/migration_util.cpp
+++ b/src/mongo/db/s/migration_util.cpp
@@ -144,15 +144,18 @@ ExecutorFuture<bool> submitRangeDeletionTask(OperationContext* opCtx,
autoColl.emplace(opCtx, deletionTask.getNss(), MODE_IS);
auto css = CollectionShardingRuntime::get(opCtx, deletionTask.getNss());
- if (!css->getCurrentMetadataIfKnown() ||
+ if (!css->getCurrentMetadataIfKnown() || !css->getCurrentMetadata()->isSharded() ||
!css->getCurrentMetadata()->uuidMatches(deletionTask.getCollectionUuid())) {
- // If the collection's filtering metadata is not known or its UUID does not match
- // the UUID of the deletion task, force a filtering metadata refresh once, because
- // this node may have just stepped up and therefore may have a stale cache.
+ // If the collection's filtering metadata is not known, is unsharded, or its UUID
+ // does not match the UUID of the deletion task, force a filtering metadata refresh
+ // once, because this node may have just stepped up and therefore may have a stale
+ // cache.
LOG(0) << "Filtering metadata for namespace in deletion task "
<< deletionTask.toBSON()
<< (css->getCurrentMetadataIfKnown()
- ? " has UUID that does not match UUID of the deletion task"
+ ? (css->getCurrentMetadata()->isSharded()
+ ? " has UUID that does not match UUID of the deletion task"
+ : " is unsharded")
: " is not known")
<< ", forcing a refresh of " << deletionTask.getNss();
@@ -173,14 +176,16 @@ ExecutorFuture<bool> submitRangeDeletionTask(OperationContext* opCtx,
}
autoColl.emplace(opCtx, deletionTask.getNss(), MODE_IS);
- if (!css->getCurrentMetadataIfKnown() ||
+ if (!css->getCurrentMetadataIfKnown() || !css->getCurrentMetadata()->isSharded() ||
!css->getCurrentMetadata()->uuidMatches(deletionTask.getCollectionUuid())) {
LOG(0) << "Even after forced refresh, filtering metadata for namespace in deletion "
"task "
<< deletionTask.toBSON()
<< (css->getCurrentMetadataIfKnown()
- ? "has UUID that does not match UUID of the deletion task"
- : "is not known")
+ ? (css->getCurrentMetadata()->isSharded()
+ ? " has UUID that does not match UUID of the deletion task"
+ : " is unsharded")
+ : " is not known")
<< ", deleting the task.";
autoColl.reset();
diff --git a/src/mongo/db/s/migration_util_test.cpp b/src/mongo/db/s/migration_util_test.cpp
index 14547873f36..fa8b6197552 100644
--- a/src/mongo/db/s/migration_util_test.cpp
+++ b/src/mongo/db/s/migration_util_test.cpp
@@ -534,6 +534,54 @@ TEST_F(SubmitRangeDeletionTaskTest,
ASSERT_EQ(store.count(opCtx), 0);
}
+TEST_F(SubmitRangeDeletionTaskTest, FailsAndDeletesTaskIfNamespaceIsUnshardedEvenAfterRefresh) {
+ auto opCtx = operationContext();
+
+ auto deletionTask = createDeletionTask(kNss, kDefaultUUID, 0, 10);
+
+ PersistentTaskStore<RangeDeletionTask> store(opCtx, NamespaceString::kRangeDeletionNamespace);
+ store.add(opCtx, deletionTask);
+ ASSERT_EQ(store.count(opCtx), 1);
+
+ // Make the refresh triggered by submitting the task return an empty result when loading the
+ // collection so it is considered unsharded.
+ _mockCatalogCacheLoader->setDatabaseRefreshReturnValue(kDefaultDatabaseType);
+ _mockCatalogCacheLoader->setCollectionRefreshReturnValue(
+ Status(ErrorCodes::NamespaceNotFound, "dummy errmsg"));
+
+ auto submitTaskFuture = migrationutil::submitRangeDeletionTask(opCtx, deletionTask);
+
+ // The task should not have been submitted, and the task's entry should have been removed from
+ // the persistent store.
+ ASSERT_FALSE(submitTaskFuture.get(opCtx));
+ ASSERT_EQ(store.count(opCtx), 0);
+}
+
+TEST_F(SubmitRangeDeletionTaskTest,
+ FailsAndDeletesTaskIfNamespaceIsUnshardedBeforeAndAfterRefresh) {
+ auto opCtx = operationContext();
+
+ auto deletionTask = createDeletionTask(kNss, kDefaultUUID, 0, 10);
+
+ PersistentTaskStore<RangeDeletionTask> store(opCtx, NamespaceString::kRangeDeletionNamespace);
+ store.add(opCtx, deletionTask);
+ ASSERT_EQ(store.count(opCtx), 1);
+
+ // Mock an empty result for the task's collection and force a refresh so the node believes the
+ // collection is unsharded.
+ _mockCatalogCacheLoader->setDatabaseRefreshReturnValue(kDefaultDatabaseType);
+ _mockCatalogCacheLoader->setCollectionRefreshReturnValue(
+ Status(ErrorCodes::NamespaceNotFound, "dummy errmsg"));
+ forceShardFilteringMetadataRefresh(opCtx, kNss, true);
+
+ auto submitTaskFuture = migrationutil::submitRangeDeletionTask(opCtx, deletionTask);
+
+ // The task should not have been submitted, and the task's entry should have been removed from
+ // the persistent store.
+ ASSERT_FALSE(submitTaskFuture.get(opCtx));
+ ASSERT_EQ(store.count(opCtx), 0);
+}
+
TEST_F(SubmitRangeDeletionTaskTest, SucceedsIfFilteringMetadataUUIDMatchesTaskUUID) {
auto opCtx = operationContext();
@@ -574,6 +622,31 @@ TEST_F(
}
TEST_F(SubmitRangeDeletionTaskTest,
+ SucceedsIfTaskNamespaceInitiallyUnshardedButUUIDMatchesAfterRefresh) {
+ auto opCtx = operationContext();
+
+ // Force a metadata refresh with no collection entry so the node believes the namespace is
+ // unsharded when the task is submitted.
+ _mockCatalogCacheLoader->setDatabaseRefreshReturnValue(kDefaultDatabaseType);
+ _mockCatalogCacheLoader->setCollectionRefreshReturnValue(
+ Status(ErrorCodes::NamespaceNotFound, "dummy errmsg"));
+ forceShardFilteringMetadataRefresh(opCtx, kNss, true);
+
+ auto deletionTask = createDeletionTask(kNss, kDefaultUUID, 0, 10);
+
+ // Make the refresh triggered by submitting the task return a UUID that matches the task's UUID.
+ auto matchingColl = makeCollectionType(kDefaultUUID, kEpoch);
+ _mockCatalogCacheLoader->setCollectionRefreshReturnValue(matchingColl);
+ _mockCatalogCacheLoader->setChunkRefreshReturnValue(
+ makeChangedChunks(ChunkVersion(10, 0, kEpoch)));
+ _mockCatalogClient->setCollections({matchingColl});
+
+ // The task should have been submitted successfully.
+ auto submitTaskFuture = migrationutil::submitRangeDeletionTask(opCtx, deletionTask);
+ ASSERT(submitTaskFuture.get(opCtx));
+}
+
+TEST_F(SubmitRangeDeletionTaskTest,
SucceedsIfFilteringMetadataUUIDInitiallyDifferentFromTaskUUIDButMatchesAfterRefresh) {
auto opCtx = operationContext();