summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2023-03-17 21:04:58 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-03-17 21:53:28 +0000
commit94a95de05bae3f835d64ce3447ad1684e6af08ed (patch)
treee525eb00d70d37fddce85388a426094e14ffc2a1 /src/mongo
parent1a7ef47ac1b71936d4f0e671aa1037e4467457cd (diff)
downloadmongo-94a95de05bae3f835d64ce3447ad1684e6af08ed.tar.gz
SERVER-74878 Restoring from query yield supports fetching point-in-time collections using UUIDs that are no longer in the latest CollectionCatalog
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/catalog/collection_catalog_test.cpp37
-rw-r--r--src/mongo/db/db_raii.cpp26
2 files changed, 59 insertions, 4 deletions
diff --git a/src/mongo/db/catalog/collection_catalog_test.cpp b/src/mongo/db/catalog/collection_catalog_test.cpp
index 343a10ae9f3..421e854969c 100644
--- a/src/mongo/db/catalog/collection_catalog_test.cpp
+++ b/src/mongo/db/catalog/collection_catalog_test.cpp
@@ -3669,5 +3669,42 @@ TEST_F(CollectionCatalogTimestampTest, OpenCollectionBetweenIndexBuildInProgress
coll);
}
}
+
+TEST_F(CollectionCatalogTimestampTest, ResolveNamespaceStringOrUUIDAtLatest) {
+ RAIIServerParameterControllerForTest featureFlagController(
+ "featureFlagPointInTimeCatalogLookups", true);
+
+ const NamespaceString nss = NamespaceString::createNamespaceString_forTest("a.b");
+ const Timestamp createCollectionTs = Timestamp(10, 10);
+ const UUID uuid = createCollection(opCtx.get(), nss, createCollectionTs);
+ const NamespaceStringOrUUID nssOrUUID = NamespaceStringOrUUID(nss.db(), uuid);
+
+ NamespaceString resolvedNss =
+ CollectionCatalog::get(opCtx.get())->resolveNamespaceStringOrUUID(opCtx.get(), nssOrUUID);
+ ASSERT_EQ(resolvedNss, nss);
+
+ const Timestamp dropCollectionTs = Timestamp(20, 20);
+ dropCollection(opCtx.get(), nss, dropCollectionTs);
+
+ // Resolving the UUID throws NamespaceNotFound as the collection is no longer in the latest
+ // collection catalog.
+ ASSERT_THROWS_CODE(
+ CollectionCatalog::get(opCtx.get())->resolveNamespaceStringOrUUID(opCtx.get(), nssOrUUID),
+ DBException,
+ ErrorCodes::NamespaceNotFound);
+
+ {
+ OneOffRead oor(opCtx.get(), createCollectionTs);
+ Lock::GlobalLock globalLock(opCtx.get(), MODE_IS);
+
+ CollectionCatalog::get(opCtx.get())
+ ->establishConsistentCollection(opCtx.get(), nss, createCollectionTs);
+
+ // Resolving the UUID looks in OpenedCollections to try to resolve the UUID.
+ resolvedNss = CollectionCatalog::get(opCtx.get())
+ ->resolveNamespaceStringOrUUID(opCtx.get(), nssOrUUID);
+ ASSERT_EQ(resolvedNss, nss);
+ }
+}
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/db_raii.cpp b/src/mongo/db/db_raii.cpp
index 4d65ddeba24..f9d8bb2e446 100644
--- a/src/mongo/db/db_raii.cpp
+++ b/src/mongo/db/db_raii.cpp
@@ -1084,10 +1084,28 @@ ConsistentCatalogAndSnapshot getConsistentCatalogAndSnapshot(
const auto catalogBeforeSnapshot = CollectionCatalog::get(opCtx);
- // It is incorrect to resolve the UUID here as we haven't established a consistent view of
- // this UUID yet. During a concurrent rename it can be wrong. This namespace is only used to
- // determine if it is an internal namespace.
- const auto nss = catalogBeforeSnapshot->resolveNamespaceStringOrUUID(opCtx, nsOrUUID);
+ // When a query yields it releases its snapshot, and any point-in-time instantiated
+ // collections stored on the snapshot decoration are destructed. At the start of a query,
+ // collections are fetched using a namespace. However, when a query is restoring from
+ // yield it attempts to fetch collections by UUID. It's possible for a UUID to no longer
+ // resolve to a namespace in the latest collection catalog if that collection was dropped
+ // while the query was yielding. This doesn't conclude that the collection is inaccessible
+ // at an earlier point-in-time as the data files may still be on disk. This namespace is
+ // used to determine if the read source needs to be changed and we only do this if the
+ // original read source is kNoTimestamp or kLastApplied. If it's neither of the two we can
+ // safely continue.
+ NamespaceString nss;
+ try {
+ nss = catalogBeforeSnapshot->resolveNamespaceStringOrUUID(opCtx, nsOrUUID);
+ } catch (const ExceptionFor<ErrorCodes::NamespaceNotFound>&) {
+ invariant(nsOrUUID.uuid());
+
+ const auto readSource = opCtx->recoveryUnit()->getTimestampReadSource();
+ if (readSource == RecoveryUnit::ReadSource::kNoTimestamp ||
+ readSource == RecoveryUnit::ReadSource::kLastApplied) {
+ throw;
+ }
+ }
// This may modify the read source on the recovery unit for opCtx if the current read source
// is either kNoTimestamp or kLastApplied.