diff options
author | Sophia Tan <sophia_tll@hotmail.com> | 2022-04-14 16:41:50 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-04-14 18:21:59 +0000 |
commit | d568014e161d2386a47318ceed842c45c1006990 (patch) | |
tree | ec217db5573f4a35f75633b160b78996477ccc55 | |
parent | 06625aa0a8fc826d9d5d80e8604b0456ffcd7d4a (diff) | |
download | mongo-d568014e161d2386a47318ceed842c45c1006990.tar.gz |
SERVER-63206 Change CollectionCatalog::_viewsForDatabase to be keyed by TenantDatabaseName
-rw-r--r-- | src/mongo/db/catalog/catalog_stats.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_catalog.cpp | 58 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_catalog.h | 23 | ||||
-rw-r--r-- | src/mongo/db/catalog/database_impl.cpp | 15 | ||||
-rw-r--r-- | src/mongo/db/commands/list_collections.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/commands/validate_db_metadata_cmd.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/tenant_file_importer_service.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/views/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/views/durable_view_catalog.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/views/view_catalog_test.cpp | 14 |
10 files changed, 69 insertions, 58 deletions
diff --git a/src/mongo/db/catalog/catalog_stats.cpp b/src/mongo/db/catalog/catalog_stats.cpp index ea7b4ee2276..3450f854171 100644 --- a/src/mongo/db/catalog/catalog_stats.cpp +++ b/src/mongo/db/catalog/catalog_stats.cpp @@ -84,8 +84,7 @@ public: const auto viewCatalogDbNames = catalog->getViewCatalogDbNames(opCtx); for (const auto& tenantDbName : viewCatalogDbNames) { try { - const auto viewStats = - catalog->getViewStatsForDatabase(opCtx, tenantDbName.dbName()); + const auto viewStats = catalog->getViewStatsForDatabase(opCtx, tenantDbName); invariant(viewStats); stats.timeseries += viewStats->userTimeseries; diff --git a/src/mongo/db/catalog/collection_catalog.cpp b/src/mongo/db/catalog/collection_catalog.cpp index e0c4f41afad..1c938446046 100644 --- a/src/mongo/db/catalog/collection_catalog.cpp +++ b/src/mongo/db/catalog/collection_catalog.cpp @@ -178,7 +178,7 @@ public: } case UncommittedCatalogUpdates::Entry::Action::kReplacedViewsForDatabase: { writeJobs.push_back( - [dbName = entry.nss.db(), + [dbName = TenantDatabaseName(boost::none, entry.nss.db()), &viewsForDb = entry.viewsForDb.get()](CollectionCatalog& catalog) { catalog._replaceViewsForDatabase(dbName, std::move(viewsForDb)); }); @@ -480,8 +480,9 @@ Status CollectionCatalog::createView( invariant(opCtx->lockState()->isCollectionLockedForMode( NamespaceString(viewName.db(), NamespaceString::kSystemDotViewsCollectionName), MODE_X)); - invariant(_viewsForDatabase.contains(viewName.db())); - const ViewsForDatabase& viewsForDb = *_getViewsForDatabase(opCtx, viewName.db()); + TenantDatabaseName tenantDbName(boost::none, viewName.db()); + invariant(_viewsForDatabase.contains(tenantDbName)); + const ViewsForDatabase& viewsForDb = *_getViewsForDatabase(opCtx, tenantDbName); if (viewName.db() != viewOn.db()) return Status(ErrorCodes::BadValue, @@ -524,8 +525,9 @@ Status CollectionCatalog::modifyView( invariant(opCtx->lockState()->isCollectionLockedForMode( NamespaceString(viewName.db(), NamespaceString::kSystemDotViewsCollectionName), MODE_X)); - invariant(_viewsForDatabase.contains(viewName.db())); - const ViewsForDatabase& viewsForDb = *_getViewsForDatabase(opCtx, viewName.db()); + TenantDatabaseName tenantDbName(boost::none, viewName.db()); + invariant(_viewsForDatabase.contains(tenantDbName)); + const ViewsForDatabase& viewsForDb = *_getViewsForDatabase(opCtx, tenantDbName); if (viewName.db() != viewOn.db()) return Status(ErrorCodes::BadValue, @@ -561,8 +563,9 @@ Status CollectionCatalog::dropView(OperationContext* opCtx, const NamespaceStrin invariant(opCtx->lockState()->isCollectionLockedForMode( NamespaceString(viewName.db(), NamespaceString::kSystemDotViewsCollectionName), MODE_X)); - invariant(_viewsForDatabase.contains(viewName.db())); - const ViewsForDatabase& viewsForDb = *_getViewsForDatabase(opCtx, viewName.db()); + TenantDatabaseName tenantDbName(boost::none, viewName.db()); + invariant(_viewsForDatabase.contains(tenantDbName)); + const ViewsForDatabase& viewsForDb = *_getViewsForDatabase(opCtx, tenantDbName); viewsForDb.requireValidCatalog(); // Make sure the view exists before proceeding. @@ -597,16 +600,17 @@ Status CollectionCatalog::dropView(OperationContext* opCtx, const NamespaceStrin return result; } -Status CollectionCatalog::reloadViews(OperationContext* opCtx, StringData dbName) const { +Status CollectionCatalog::reloadViews(OperationContext* opCtx, + const TenantDatabaseName& dbName) const { invariant(opCtx->lockState()->isCollectionLockedForMode( - NamespaceString(dbName, NamespaceString::kSystemDotViewsCollectionName), MODE_IS)); + NamespaceString(dbName.dbName(), NamespaceString::kSystemDotViewsCollectionName), MODE_IS)); auto& uncommittedCatalogUpdates = UncommittedCatalogUpdates::get(opCtx); - if (uncommittedCatalogUpdates.shouldIgnoreExternalViewChanges(dbName)) { + if (uncommittedCatalogUpdates.shouldIgnoreExternalViewChanges(dbName.dbName())) { return Status::OK(); } - LOGV2_DEBUG(22546, 1, "Reloading view catalog for database", "db"_attr = dbName); + LOGV2_DEBUG(22546, 1, "Reloading view catalog for database", "db"_attr = dbName.toString()); // Create a copy of the ViewsForDatabase instance to modify it. Reset the views for this // database, but preserve the DurableViewCatalog pointer. @@ -672,9 +676,9 @@ void CollectionCatalog::dropCollection(OperationContext* opCtx, Collection* coll } void CollectionCatalog::onOpenDatabase(OperationContext* opCtx, - StringData dbName, + const TenantDatabaseName& dbName, ViewsForDatabase&& viewsForDb) { - invariant(opCtx->lockState()->isDbLockedForMode(dbName, MODE_IS)); + invariant(opCtx->lockState()->isDbLockedForMode(dbName.dbName(), MODE_IS)); uassert(ErrorCodes::AlreadyInitialized, str::stream() << "Database " << dbName << " is already initialized", _viewsForDatabase.find(dbName) == _viewsForDatabase.end()); @@ -686,7 +690,7 @@ void CollectionCatalog::onCloseDatabase(OperationContext* opCtx, TenantDatabaseN invariant(opCtx->lockState()->isDbLockedForMode(tenantDbName.dbName(), MODE_X)); auto rid = ResourceId(RESOURCE_DATABASE, tenantDbName.dbName()); removeResource(rid, tenantDbName.dbName()); - _viewsForDatabase.erase(tenantDbName.dbName()); + _viewsForDatabase.erase(tenantDbName); } void CollectionCatalog::onCloseCatalog(OperationContext* opCtx) { @@ -947,7 +951,7 @@ boost::optional<UUID> CollectionCatalog::lookupUUIDByNSS(OperationContext* opCtx } void CollectionCatalog::iterateViews(OperationContext* opCtx, - StringData dbName, + const TenantDatabaseName& dbName, ViewIteratorCallback callback, ViewCatalogLookupBehavior lookupBehavior) const { auto viewsForDb = _getViewsForDatabase(opCtx, dbName); @@ -968,7 +972,7 @@ void CollectionCatalog::iterateViews(OperationContext* opCtx, std::shared_ptr<const ViewDefinition> CollectionCatalog::lookupView( OperationContext* opCtx, const NamespaceString& ns) const { - auto viewsForDb = _getViewsForDatabase(opCtx, ns.db()); + auto viewsForDb = _getViewsForDatabase(opCtx, TenantDatabaseName(boost::none, ns.db())); if (!viewsForDb) { return nullptr; } @@ -990,7 +994,7 @@ std::shared_ptr<const ViewDefinition> CollectionCatalog::lookupView( std::shared_ptr<const ViewDefinition> CollectionCatalog::lookupViewWithoutValidatingDurable( OperationContext* opCtx, const NamespaceString& ns) const { - auto viewsForDb = _getViewsForDatabase(opCtx, ns.db()); + auto viewsForDb = _getViewsForDatabase(opCtx, TenantDatabaseName(boost::none, ns.db())); if (!viewsForDb) { return nullptr; } @@ -1110,7 +1114,7 @@ CollectionCatalog::Stats CollectionCatalog::getStats() const { } boost::optional<ViewsForDatabase::Stats> CollectionCatalog::getViewStatsForDatabase( - OperationContext* opCtx, StringData dbName) const { + OperationContext* opCtx, const TenantDatabaseName& dbName) const { auto viewsForDb = _getViewsForDatabase(opCtx, dbName); if (!viewsForDb) { return boost::none; @@ -1122,8 +1126,7 @@ CollectionCatalog::ViewCatalogSet CollectionCatalog::getViewCatalogDbNames( OperationContext* opCtx) const { ViewCatalogSet results; for (const auto& dbNameViewSetPair : _viewsForDatabase) { - // TODO (SERVER-63206): Return stored TenantDatabaseName - results.insert(TenantDatabaseName{boost::none, dbNameViewSetPair.first}); + results.insert(dbNameViewSetPair.first); } return results; @@ -1253,7 +1256,8 @@ void CollectionCatalog::_ensureNamespaceDoesNotExist(OperationContext* opCtx, throw WriteConflictException(); } - if (auto viewsForDb = _getViewsForDatabase(opCtx, nss.db())) { + if (auto viewsForDb = + _getViewsForDatabase(opCtx, TenantDatabaseName(boost::none, nss.db()))) { if (viewsForDb->lookup(nss) != nullptr) { LOGV2( 5725003, @@ -1285,9 +1289,10 @@ void CollectionCatalog::deregisterAllCollectionsAndViews() { _resourceInformation.clear(); } -void CollectionCatalog::clearViews(OperationContext* opCtx, StringData dbName) const { +void CollectionCatalog::clearViews(OperationContext* opCtx, + const TenantDatabaseName& dbName) const { invariant(opCtx->lockState()->isCollectionLockedForMode( - NamespaceString(dbName, NamespaceString::kSystemDotViewsCollectionName), MODE_X)); + NamespaceString(dbName.dbName(), NamespaceString::kSystemDotViewsCollectionName), MODE_X)); auto it = _viewsForDatabase.find(dbName); invariant(it != _viewsForDatabase.end()); @@ -1376,9 +1381,9 @@ void CollectionCatalog::invariantHasExclusiveAccessToCollection(OperationContext } boost::optional<const ViewsForDatabase&> CollectionCatalog::_getViewsForDatabase( - OperationContext* opCtx, StringData dbName) const { + OperationContext* opCtx, const TenantDatabaseName& dbName) const { auto& uncommittedCatalogUpdates = UncommittedCatalogUpdates::get(opCtx); - auto uncommittedViews = uncommittedCatalogUpdates.getViewsForDatabase(dbName); + auto uncommittedViews = uncommittedCatalogUpdates.getViewsForDatabase(dbName.dbName()); if (uncommittedViews) { return uncommittedViews; } @@ -1390,7 +1395,8 @@ boost::optional<const ViewsForDatabase&> CollectionCatalog::_getViewsForDatabase return it->second; } -void CollectionCatalog::_replaceViewsForDatabase(StringData dbName, ViewsForDatabase&& views) { +void CollectionCatalog::_replaceViewsForDatabase(const TenantDatabaseName& dbName, + ViewsForDatabase&& views) { _viewsForDatabase[dbName] = std::move(views); } diff --git a/src/mongo/db/catalog/collection_catalog.h b/src/mongo/db/catalog/collection_catalog.h index f47f94397f9..042988be027 100644 --- a/src/mongo/db/catalog/collection_catalog.h +++ b/src/mongo/db/catalog/collection_catalog.h @@ -191,7 +191,7 @@ public: * * Requires an IS lock on the 'system.views' collection'. */ - Status reloadViews(OperationContext* opCtx, StringData dbName) const; + Status reloadViews(OperationContext* opCtx, const TenantDatabaseName& dbName) const; /** * Handles committing a collection to the catalog within a WriteUnitOfWork. @@ -223,7 +223,9 @@ public: * Initializes view records for database 'dbName'. Can throw a 'WriteConflictException' if this * database has already been initialized. */ - void onOpenDatabase(OperationContext* opCtx, StringData dbName, ViewsForDatabase&& viewsForDb); + void onOpenDatabase(OperationContext* opCtx, + const TenantDatabaseName& dbName, + ViewsForDatabase&& viewsForDb); /** * Removes the view records associated with 'tenantDbName', if any, from the in-memory @@ -265,7 +267,7 @@ public: * * Callers must re-fetch the catalog to observe changes. */ - void clearViews(OperationContext* opCtx, StringData dbName) const; + void clearViews(OperationContext* opCtx, const TenantDatabaseName& dbName) const; /** * This function gets the Collection pointer that corresponds to the UUID. @@ -340,7 +342,7 @@ public: */ void iterateViews( OperationContext* opCtx, - StringData dbName, + const TenantDatabaseName& dbName, ViewIteratorCallback callback, ViewCatalogLookupBehavior lookupBehavior = ViewCatalogLookupBehavior::kValidateViews) const; @@ -457,8 +459,8 @@ public: /** * Returns view statistics for the specified database. */ - boost::optional<ViewsForDatabase::Stats> getViewStatsForDatabase(OperationContext* opCtx, - StringData dbName) const; + boost::optional<ViewsForDatabase::Stats> getViewStatsForDatabase( + OperationContext* opCtx, const TenantDatabaseName& dbName) const; /** * Returns a set of databases, by name, that have view catalogs. @@ -530,14 +532,14 @@ private: * Retrieves the views for a given database, including any uncommitted changes for this * operation. */ - boost::optional<const ViewsForDatabase&> _getViewsForDatabase(OperationContext* opCtx, - StringData dbName) const; + boost::optional<const ViewsForDatabase&> _getViewsForDatabase( + OperationContext* opCtx, const TenantDatabaseName& dbName) const; /** * Sets all namespaces used by views for a database. Will uassert if there is a conflicting * collection name in the catalog. */ - void _replaceViewsForDatabase(StringData dbName, ViewsForDatabase&& views); + void _replaceViewsForDatabase(const TenantDatabaseName& dbName, ViewsForDatabase&& views); /** * Helper to take care of shared functionality for 'createView(...)' and 'modifyView(...)'. @@ -589,6 +591,7 @@ private: stdx::unordered_map<NamespaceString, std::shared_ptr<Collection>>; using UncommittedViewsSet = stdx::unordered_set<NamespaceString>; using DatabaseProfileSettingsMap = StringMap<ProfileSettings>; + using ViewsForDatabaseMap = stdx::unordered_map<TenantDatabaseName, ViewsForDatabase>; CollectionCatalogMap _catalog; OrderedCollectionMap _orderedCollections; // Ordered by <tenantDbName, collUUID> pair @@ -596,7 +599,7 @@ private: UncommittedViewsSet _uncommittedViews; // Map of database names to their corresponding views and other associated state. - StringMap<ViewsForDatabase> _viewsForDatabase; + ViewsForDatabaseMap _viewsForDatabase; // Incremented whenever the CollectionCatalog gets closed and reopened (onCloseCatalog and // onOpenCatalog). diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp index 077fc8d2313..b23f0f60046 100644 --- a/src/mongo/db/catalog/database_impl.cpp +++ b/src/mongo/db/catalog/database_impl.cpp @@ -207,7 +207,7 @@ Status DatabaseImpl::init(OperationContext* const opCtx) { } CollectionCatalog::write(opCtx, [&](CollectionCatalog& catalog) { - catalog.onOpenDatabase(opCtx, _name.dbName(), std::move(viewsForDb)); + catalog.onOpenDatabase(opCtx, _name, std::move(viewsForDb)); }); } catch (DBException& ex) { // Another operation may have tried to simultaneously open the database and register it @@ -233,7 +233,7 @@ Status DatabaseImpl::init(OperationContext* const opCtx) { NamespaceString resolvedNs; }; std::vector<ViewToDrop> viewsToDrop; - catalog->iterateViews(opCtx, _name.dbName(), [&](const ViewDefinition& view) { + catalog->iterateViews(opCtx, _name, [&](const ViewDefinition& view) { auto swResolvedView = view_catalog_helpers::resolveView(opCtx, catalog, view.name(), boost::none); if (!swResolvedView.isOK()) { @@ -375,11 +375,10 @@ void DatabaseImpl::getStats(OperationContext* opCtx, }); - CollectionCatalog::get(opCtx)->iterateViews( - opCtx, name().dbName(), [&](const ViewDefinition& view) { - nViews += 1; - return true; - }); + CollectionCatalog::get(opCtx)->iterateViews(opCtx, name(), [&](const ViewDefinition& view) { + nViews += 1; + return true; + }); // Make sure that the same fields are returned for non-existing dbs // in `DBStats::errmsgRun` @@ -458,7 +457,7 @@ Status DatabaseImpl::dropCollection(OperationContext* opCtx, "turn off profiling before dropping system.profile collection"); } else if (nss.isSystemDotViews()) { if (!MONGO_unlikely(allowSystemViewsDrop.shouldFail())) { - const auto viewStats = catalog->getViewStatsForDatabase(opCtx, _name.dbName()); + const auto viewStats = catalog->getViewStatsForDatabase(opCtx, _name); uassert(ErrorCodes::CommandFailed, str::stream() << "cannot drop collection " << nss << " when time-series collections are present.", diff --git a/src/mongo/db/commands/list_collections.cpp b/src/mongo/db/commands/list_collections.cpp index f78cfda6308..bc144913d4f 100644 --- a/src/mongo/db/commands/list_collections.cpp +++ b/src/mongo/db/commands/list_collections.cpp @@ -453,7 +453,7 @@ public: ListCollectionsFilter::makeTypeCollectionFilter()); if (!skipViews) { - catalog->iterateViews(opCtx, dbName, [&](const ViewDefinition& view) { + catalog->iterateViews(opCtx, tenantDbName, [&](const ViewDefinition& view) { if (authorizedCollections && !as->isAuthorizedForAnyActionOnResource( ResourcePattern::forExactNamespace(view.name()))) { diff --git a/src/mongo/db/commands/validate_db_metadata_cmd.cpp b/src/mongo/db/commands/validate_db_metadata_cmd.cpp index c3a00ff74e6..f635336802f 100644 --- a/src/mongo/db/commands/validate_db_metadata_cmd.cpp +++ b/src/mongo/db/commands/validate_db_metadata_cmd.cpp @@ -145,7 +145,7 @@ public: // If there is no collection name present in the input, run validation against all // the collections. collectionCatalog->iterateViews( - opCtx, tenantDbName.dbName(), [this, opCtx](const ViewDefinition& view) { + opCtx, tenantDbName, [this, opCtx](const ViewDefinition& view) { return _validateView(opCtx, view); }); diff --git a/src/mongo/db/repl/tenant_file_importer_service.cpp b/src/mongo/db/repl/tenant_file_importer_service.cpp index b315b7f43d3..4e16c773709 100644 --- a/src/mongo/db/repl/tenant_file_importer_service.cpp +++ b/src/mongo/db/repl/tenant_file_importer_service.cpp @@ -115,7 +115,7 @@ void importCopiedFiles(OperationContext* opCtx, opCtx, NamespaceString(m.ns.db(), NamespaceString::kSystemDotViewsCollectionName), MODE_X); - uassertStatusOK(catalog->reloadViews(opCtx, m.ns.db())); + uassertStatusOK(catalog->reloadViews(opCtx, TenantDatabaseName(boost::none, m.ns.db()))); } } } // namespace diff --git a/src/mongo/db/views/SConscript b/src/mongo/db/views/SConscript index a16bf79890a..bc24883a43b 100644 --- a/src/mongo/db/views/SConscript +++ b/src/mongo/db/views/SConscript @@ -70,6 +70,7 @@ env.CppUnitTest( LIBDEPS=[ '$BUILD_DIR/mongo/db/auth/authmocks', '$BUILD_DIR/mongo/db/catalog/catalog_test_fixture', + '$BUILD_DIR/mongo/db/multitenancy', '$BUILD_DIR/mongo/db/query/collation/collator_interface_mock', '$BUILD_DIR/mongo/db/query/query_test_service_context', '$BUILD_DIR/mongo/db/repl/replmocks', diff --git a/src/mongo/db/views/durable_view_catalog.cpp b/src/mongo/db/views/durable_view_catalog.cpp index bbc2d1f59ef..a3b6b814a04 100644 --- a/src/mongo/db/views/durable_view_catalog.cpp +++ b/src/mongo/db/views/durable_view_catalog.cpp @@ -65,7 +65,7 @@ void DurableViewCatalog::onExternalChange(OperationContext* opCtx, const Namespa // is reloaded. This will prevent any further usage of the views for this database until the // invalid view definitions are removed. auto catalog = CollectionCatalog::get(opCtx); - catalog->reloadViews(opCtx, name.db()).ignore(); + catalog->reloadViews(opCtx, TenantDatabaseName(boost::none, name.db())).ignore(); } void DurableViewCatalog::onSystemViewsCollectionDrop(OperationContext* opCtx, @@ -76,10 +76,11 @@ void DurableViewCatalog::onSystemViewsCollectionDrop(OperationContext* opCtx, dassert(name.coll() == NamespaceString::kSystemDotViewsCollectionName); auto catalog = CollectionCatalog::get(opCtx); + const TenantDatabaseName dbName(boost::none, name.db()); // First, iterate through the views on this database and audit them before they are dropped. catalog->iterateViews(opCtx, - name.db(), + dbName, [&](const ViewDefinition& view) -> bool { audit::logDropView(opCtx->getClient(), view.name(), @@ -92,7 +93,7 @@ void DurableViewCatalog::onSystemViewsCollectionDrop(OperationContext* opCtx, // If the 'system.views' collection is dropped, we need to clear the in-memory state of the // view catalog. - catalog->clearViews(opCtx, name.db()); + catalog->clearViews(opCtx, dbName); } // DurableViewCatalogImpl diff --git a/src/mongo/db/views/view_catalog_test.cpp b/src/mongo/db/views/view_catalog_test.cpp index 119b5b5456a..dd787101a80 100644 --- a/src/mongo/db/views/view_catalog_test.cpp +++ b/src/mongo/db/views/view_catalog_test.cpp @@ -649,12 +649,14 @@ TEST_F(ViewCatalogFixture, Iterate) { std::set<std::string> viewNames = {"db.view1", "db.view2", "db.view3"}; Lock::DBLock dbLock(operationContext(), "db", MODE_IX); - getCatalog()->iterateViews(operationContext(), "db", [&viewNames](const ViewDefinition& view) { - std::string name = view.name().toString(); - ASSERT(viewNames.end() != viewNames.find(name)); - viewNames.erase(name); - return true; - }); + getCatalog()->iterateViews(operationContext(), + TenantDatabaseName(boost::none, "db"), + [&viewNames](const ViewDefinition& view) { + std::string name = view.name().toString(); + ASSERT(viewNames.end() != viewNames.find(name)); + viewNames.erase(name); + return true; + }); ASSERT(viewNames.empty()); } |