summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSophia Tan <sophia_tll@hotmail.com>2022-04-14 16:41:50 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-04-14 18:21:59 +0000
commitd568014e161d2386a47318ceed842c45c1006990 (patch)
treeec217db5573f4a35f75633b160b78996477ccc55
parent06625aa0a8fc826d9d5d80e8604b0456ffcd7d4a (diff)
downloadmongo-d568014e161d2386a47318ceed842c45c1006990.tar.gz
SERVER-63206 Change CollectionCatalog::_viewsForDatabase to be keyed by TenantDatabaseName
-rw-r--r--src/mongo/db/catalog/catalog_stats.cpp3
-rw-r--r--src/mongo/db/catalog/collection_catalog.cpp58
-rw-r--r--src/mongo/db/catalog/collection_catalog.h23
-rw-r--r--src/mongo/db/catalog/database_impl.cpp15
-rw-r--r--src/mongo/db/commands/list_collections.cpp2
-rw-r--r--src/mongo/db/commands/validate_db_metadata_cmd.cpp2
-rw-r--r--src/mongo/db/repl/tenant_file_importer_service.cpp2
-rw-r--r--src/mongo/db/views/SConscript1
-rw-r--r--src/mongo/db/views/durable_view_catalog.cpp7
-rw-r--r--src/mongo/db/views/view_catalog_test.cpp14
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());
}