summaryrefslogtreecommitdiff
path: root/src/mongo/db/catalog
diff options
context:
space:
mode:
authorXiangyu Yao <xiangyu.yao@mongodb.com>2019-04-26 10:30:18 -0400
committerXiangyu Yao <xiangyu.yao@mongodb.com>2019-04-26 14:45:54 -0400
commitfa23ce3476904d41f981a677aa4aba55deec4791 (patch)
treee53a0e8729364474931d1fdf3d56f8466c978ba6 /src/mongo/db/catalog
parent36fabef9e765033af90017a5ebc41e53ef46683e (diff)
downloadmongo-fa23ce3476904d41f981a677aa4aba55deec4791.tar.gz
SERVER-39520 Use database IX lock for dropCollection
Diffstat (limited to 'src/mongo/db/catalog')
-rw-r--r--src/mongo/db/catalog/SConscript13
-rw-r--r--src/mongo/db/catalog/catalog_control.cpp2
-rw-r--r--src/mongo/db/catalog/collection.h1
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp4
-rw-r--r--src/mongo/db/catalog/collection_impl.h1
-rw-r--r--src/mongo/db/catalog/collection_mock.h1
-rw-r--r--src/mongo/db/catalog/collection_test.cpp2
-rw-r--r--src/mongo/db/catalog/database_holder_impl.cpp5
-rw-r--r--src/mongo/db/catalog/database_impl.cpp51
-rw-r--r--src/mongo/db/catalog/drop_collection.cpp14
-rw-r--r--src/mongo/db/catalog/index_consistency.cpp2
-rw-r--r--src/mongo/db/catalog/index_consistency.h2
-rw-r--r--src/mongo/db/catalog/uuid_catalog.cpp34
-rw-r--r--src/mongo/db/catalog/uuid_catalog.h18
-rw-r--r--src/mongo/db/catalog/uuid_catalog_helper.cpp63
-rw-r--r--src/mongo/db/catalog/uuid_catalog_helper.h53
-rw-r--r--src/mongo/db/catalog/uuid_catalog_test.cpp2
17 files changed, 194 insertions, 74 deletions
diff --git a/src/mongo/db/catalog/SConscript b/src/mongo/db/catalog/SConscript
index e2eacc8d585..591691e1b13 100644
--- a/src/mongo/db/catalog/SConscript
+++ b/src/mongo/db/catalog/SConscript
@@ -325,6 +325,17 @@ env.Library(
]
)
+env.Library(
+ target='uuid_catalog_helper',
+ source=[
+ 'uuid_catalog_helper.cpp',
+ ],
+ LIBDEPS_PRIVATE=[
+ 'uuid_catalog',
+ '$BUILD_DIR/mongo/db/concurrency/lock_manager',
+ ]
+)
+
env.CppUnitTest(
target='namespace_uuid_cache_test',
source=[
@@ -342,7 +353,6 @@ env.CppUnitTest(
],
LIBDEPS=[
'uuid_catalog',
- '$BUILD_DIR/mongo/db/concurrency/lock_manager',
'$BUILD_DIR/mongo/db/service_context',
'$BUILD_DIR/mongo/db/storage/kv/kv_prefix',
],
@@ -417,6 +427,7 @@ env.Library(
'$BUILD_DIR/mongo/db/views/views_mongod',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/catalog/uuid_catalog_helper',
'$BUILD_DIR/mongo/db/commands/server_status_core',
'$BUILD_DIR/mongo/db/index/index_build_interceptor',
'$BUILD_DIR/mongo/db/logical_clock',
diff --git a/src/mongo/db/catalog/catalog_control.cpp b/src/mongo/db/catalog/catalog_control.cpp
index ffd4a5f60dc..a13ca2d2650 100644
--- a/src/mongo/db/catalog/catalog_control.cpp
+++ b/src/mongo/db/catalog/catalog_control.cpp
@@ -177,7 +177,7 @@ void openCatalog(OperationContext* opCtx, const MinVisibleTimestampMap& minVisib
LOG_FOR_RECOVERY(1) << "openCatalog: dbholder reopening database " << dbName;
auto db = databaseHolder->openDb(opCtx, dbName);
invariant(db, str::stream() << "failed to reopen database " << dbName);
- for (auto&& collNss : UUIDCatalog::get(opCtx).getAllCollectionNamesFromDb(dbName)) {
+ for (auto&& collNss : UUIDCatalog::get(opCtx).getAllCollectionNamesFromDb(opCtx, dbName)) {
// Note that the collection name already includes the database component.
auto collection = db->getCollection(opCtx, collNss.ns());
invariant(collection,
diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h
index 705cc5c6d44..39cb24a20d7 100644
--- a/src/mongo/db/catalog/collection.h
+++ b/src/mongo/db/catalog/collection.h
@@ -328,7 +328,6 @@ public:
virtual Status validate(OperationContext* const opCtx,
const ValidateCmdLevel level,
bool background,
- std::unique_ptr<Lock::CollectionLock> collLk,
ValidateResults* const results,
BSONObjBuilder* const output) = 0;
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index fcb62484ea6..aa662981b29 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -1273,7 +1273,6 @@ void _validateCatalogEntry(OperationContext* opCtx,
Status CollectionImpl::validate(OperationContext* opCtx,
ValidateCmdLevel level,
bool background,
- std::unique_ptr<Lock::CollectionLock> collLk,
ValidateResults* results,
BSONObjBuilder* output) {
dassert(opCtx->lockState()->isCollectionLockedForMode(ns(), MODE_IS));
@@ -1281,8 +1280,7 @@ Status CollectionImpl::validate(OperationContext* opCtx,
try {
ValidateResultsMap indexNsResultsMap;
BSONObjBuilder keysPerIndex; // not using subObjStart to be exception safe
- IndexConsistency indexConsistency(
- opCtx, this, ns(), _recordStore, std::move(collLk), background);
+ IndexConsistency indexConsistency(opCtx, this, ns(), _recordStore, background);
RecordStoreValidateAdaptor indexValidator = RecordStoreValidateAdaptor(
opCtx, &indexConsistency, level, _indexCatalog.get(), &indexNsResultsMap);
diff --git a/src/mongo/db/catalog/collection_impl.h b/src/mongo/db/catalog/collection_impl.h
index 615a2499c59..cc26c48ae73 100644
--- a/src/mongo/db/catalog/collection_impl.h
+++ b/src/mongo/db/catalog/collection_impl.h
@@ -237,7 +237,6 @@ public:
Status validate(OperationContext* opCtx,
ValidateCmdLevel level,
bool background,
- std::unique_ptr<Lock::CollectionLock> collLk,
ValidateResults* results,
BSONObjBuilder* output) final;
diff --git a/src/mongo/db/catalog/collection_mock.h b/src/mongo/db/catalog/collection_mock.h
index c7075786eda..14e9f8d1550 100644
--- a/src/mongo/db/catalog/collection_mock.h
+++ b/src/mongo/db/catalog/collection_mock.h
@@ -171,7 +171,6 @@ public:
Status validate(OperationContext* opCtx,
ValidateCmdLevel level,
bool background,
- std::unique_ptr<Lock::CollectionLock> collLk,
ValidateResults* results,
BSONObjBuilder* output) {
std::abort();
diff --git a/src/mongo/db/catalog/collection_test.cpp b/src/mongo/db/catalog/collection_test.cpp
index a6486ebc9b0..a36c4d71770 100644
--- a/src/mongo/db/catalog/collection_test.cpp
+++ b/src/mongo/db/catalog/collection_test.cpp
@@ -72,7 +72,7 @@ void CollectionTest::checkValidate(
for (auto level : levels) {
ValidateResults results;
BSONObjBuilder output;
- auto status = coll->validate(opCtx, level, false, std::move(collLock), &results, &output);
+ auto status = coll->validate(opCtx, level, false, &results, &output);
ASSERT_OK(status);
ASSERT_EQ(results.valid, valid);
ASSERT_EQ(results.errors.size(), (long unsigned int)errors);
diff --git a/src/mongo/db/catalog/database_holder_impl.cpp b/src/mongo/db/catalog/database_holder_impl.cpp
index 19143026e66..9560ec6f468 100644
--- a/src/mongo/db/catalog/database_holder_impl.cpp
+++ b/src/mongo/db/catalog/database_holder_impl.cpp
@@ -137,7 +137,7 @@ Database* DatabaseHolderImpl::openDb(OperationContext* opCtx, StringData ns, boo
// different databases for the same name.
lk.unlock();
- if (UUIDCatalog::get(opCtx).getAllCatalogEntriesFromDb(dbname).empty()) {
+ if (UUIDCatalog::get(opCtx).getAllCollectionUUIDsFromDb(dbname).empty()) {
audit::logCreateDatabase(opCtx->getClient(), dbname);
if (justCreated)
*justCreated = true;
@@ -202,6 +202,7 @@ void DatabaseHolderImpl::dropDb(OperationContext* opCtx, Database* db) {
namespace {
void evictDatabaseFromUUIDCatalog(OperationContext* opCtx, Database* db) {
+ invariant(opCtx->lockState()->isW());
for (auto collIt = db->begin(opCtx); collIt != db->end(opCtx); ++collIt) {
auto coll = *collIt;
if (!coll) {
@@ -210,7 +211,7 @@ void evictDatabaseFromUUIDCatalog(OperationContext* opCtx, Database* db) {
NamespaceUUIDCache::get(opCtx).evictNamespace(coll->ns());
}
- UUIDCatalog::get(opCtx).onCloseDatabase(db);
+ UUIDCatalog::get(opCtx).onCloseDatabase(opCtx, db);
}
} // namespace
diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp
index bee198a350d..b215bca2dd7 100644
--- a/src/mongo/db/catalog/database_impl.cpp
+++ b/src/mongo/db/catalog/database_impl.cpp
@@ -50,6 +50,7 @@
#include "mongo/db/catalog/index_catalog.h"
#include "mongo/db/catalog/namespace_uuid_cache.h"
#include "mongo/db/catalog/uuid_catalog.h"
+#include "mongo/db/catalog/uuid_catalog_helper.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/concurrency/write_conflict_exception.h"
@@ -169,7 +170,7 @@ void DatabaseImpl::init(OperationContext* const opCtx) const {
}
auto& uuidCatalog = UUIDCatalog::get(opCtx);
- for (const auto& nss : uuidCatalog.getAllCollectionNamesFromDb(_name)) {
+ for (const auto& nss : uuidCatalog.getAllCollectionNamesFromDb(opCtx, _name)) {
auto ownedCollection = _createCollectionInstance(opCtx, nss);
invariant(ownedCollection);
@@ -196,7 +197,7 @@ void DatabaseImpl::init(OperationContext* const opCtx) const {
void DatabaseImpl::clearTmpCollections(OperationContext* opCtx) const {
invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));
- for (const auto& nss : UUIDCatalog::get(opCtx).getAllCollectionNamesFromDb(_name)) {
+ for (const auto& nss : UUIDCatalog::get(opCtx).getAllCollectionNamesFromDb(opCtx, _name)) {
CollectionCatalogEntry* coll =
UUIDCatalog::get(opCtx).lookupCollectionCatalogEntryByNamespace(nss);
CollectionOptions options = coll->getCollectionOptions(opCtx);
@@ -278,24 +279,24 @@ void DatabaseImpl::getStats(OperationContext* opCtx, BSONObjBuilder* output, dou
invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_IS));
- for (const auto& nss : UUIDCatalog::get(opCtx).getAllCollectionNamesFromDb(_name)) {
- Lock::CollectionLock colLock(opCtx, nss, MODE_IS);
- Collection* collection = getCollection(opCtx, nss);
+ catalog::forEachCollectionFromDb(
+ opCtx,
+ name(),
+ MODE_IS,
+ [&](Collection* collection, CollectionCatalogEntry* catalogEntry) -> bool {
+ nCollections += 1;
+ objects += collection->numRecords(opCtx);
+ size += collection->dataSize(opCtx);
- if (!collection)
- continue;
-
- nCollections += 1;
- objects += collection->numRecords(opCtx);
- size += collection->dataSize(opCtx);
+ BSONObjBuilder temp;
+ storageSize += collection->getRecordStore()->storageSize(opCtx, &temp);
+ numExtents += temp.obj()["numExtents"].numberInt(); // XXX
- BSONObjBuilder temp;
- storageSize += collection->getRecordStore()->storageSize(opCtx, &temp);
- numExtents += temp.obj()["numExtents"].numberInt(); // XXX
+ indexes += collection->getIndexCatalog()->numIndexesTotal(opCtx);
+ indexSize += collection->getIndexSize(opCtx);
- indexes += collection->getIndexCatalog()->numIndexesTotal(opCtx);
- indexSize += collection->getIndexSize(opCtx);
- }
+ return true;
+ });
ViewCatalog::get(this)->iterate(opCtx, [&](const ViewDefinition& view) { nViews += 1; });
@@ -369,7 +370,7 @@ Status DatabaseImpl::dropCollection(OperationContext* opCtx,
Status DatabaseImpl::dropCollectionEvenIfSystem(OperationContext* opCtx,
const NamespaceString& fullns,
repl::OpTime dropOpTime) const {
- invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));
+ invariant(opCtx->lockState()->isCollectionLockedForMode(fullns, MODE_X));
LOG(1) << "dropCollection: " << fullns;
@@ -519,9 +520,10 @@ Collection* DatabaseImpl::getCollection(OperationContext* opCtx, const Namespace
}
NamespaceUUIDCache& cache = NamespaceUUIDCache::get(opCtx);
- auto uuid = coll->uuid();
- invariant(uuid);
- cache.ensureNamespaceInCache(nss, uuid.get());
+ auto uuid = UUIDCatalog::get(opCtx).lookupUUIDByNSS(nss);
+ if (uuid) {
+ cache.ensureNamespaceInCache(nss, uuid.get());
+ }
return coll;
}
@@ -530,7 +532,10 @@ Status DatabaseImpl::renameCollection(OperationContext* opCtx,
StringData toNS,
bool stayTemp) const {
audit::logRenameCollection(&cc(), fromNS, toNS);
- invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));
+ // TODO SERVER-39518 : Temporarily comment this out because dropCollection uses
+ // this function and now it only takes a database IX lock. We can change
+ // this invariant to IX once renameCollection only MODE_IX as well.
+ // invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));
const NamespaceString fromNSS(fromNS);
const NamespaceString toNSS(toNS);
@@ -821,7 +826,7 @@ void DatabaseImpl::checkForIdIndexesAndDropPendingCollections(OperationContext*
return;
}
- for (const auto& nss : UUIDCatalog::get(opCtx).getAllCollectionNamesFromDb(_name)) {
+ for (const auto& nss : UUIDCatalog::get(opCtx).getAllCollectionNamesFromDb(opCtx, _name)) {
if (nss.isDropPendingNamespace()) {
auto dropOpTime = fassert(40459, nss.getDropPendingNamespaceOpTime());
log() << "Found drop-pending namespace " << nss << " with drop optime " << dropOpTime;
diff --git a/src/mongo/db/catalog/drop_collection.cpp b/src/mongo/db/catalog/drop_collection.cpp
index 391a5a76048..b1d76ca11b4 100644
--- a/src/mongo/db/catalog/drop_collection.cpp
+++ b/src/mongo/db/catalog/drop_collection.cpp
@@ -55,9 +55,6 @@ Status _dropView(OperationContext* opCtx,
std::unique_ptr<AutoGetDb>& autoDb,
const NamespaceString& collectionName,
BSONObjBuilder& result) {
- // TODO(SERVER-39520): No need to relock once createCollection doesn't need X lock.
- autoDb.reset();
- autoDb = std::make_unique<AutoGetDb>(opCtx, collectionName.db(), MODE_IX);
Database* db = autoDb->getDb();
if (!db) {
return Status(ErrorCodes::NamespaceNotFound, "ns not found");
@@ -100,11 +97,16 @@ Status _dropView(OperationContext* opCtx,
Status _dropCollection(OperationContext* opCtx,
Database* db,
- Collection* coll,
const NamespaceString& collectionName,
const repl::OpTime& dropOpTime,
DropCollectionSystemCollectionMode systemCollectionMode,
BSONObjBuilder& result) {
+ Lock::CollectionLock collLock(opCtx, collectionName, MODE_X);
+ Collection* coll = db->getCollection(opCtx, collectionName);
+ if (!coll) {
+ return Status(ErrorCodes::NamespaceNotFound, "ns not found");
+ }
+
if (MONGO_FAIL_POINT(hangDuringDropCollection)) {
log() << "hangDuringDropCollection fail point enabled. Blocking until fail point is "
"disabled.";
@@ -155,7 +157,7 @@ Status dropCollection(OperationContext* opCtx,
return writeConflictRetry(opCtx, "drop", collectionName.ns(), [&] {
// TODO(SERVER-39520): Get rid of database MODE_X lock.
- auto autoDb = std::make_unique<AutoGetDb>(opCtx, collectionName.db(), MODE_X);
+ auto autoDb = std::make_unique<AutoGetDb>(opCtx, collectionName.db(), MODE_IX);
Database* db = autoDb->getDb();
if (!db) {
@@ -167,7 +169,7 @@ Status dropCollection(OperationContext* opCtx,
return _dropView(opCtx, autoDb, collectionName, result);
} else {
return _dropCollection(
- opCtx, db, coll, collectionName, dropOpTime, systemCollectionMode, result);
+ opCtx, db, collectionName, dropOpTime, systemCollectionMode, result);
}
});
}
diff --git a/src/mongo/db/catalog/index_consistency.cpp b/src/mongo/db/catalog/index_consistency.cpp
index 5195b2aebff..a10e63dee3a 100644
--- a/src/mongo/db/catalog/index_consistency.cpp
+++ b/src/mongo/db/catalog/index_consistency.cpp
@@ -61,13 +61,11 @@ IndexConsistency::IndexConsistency(OperationContext* opCtx,
Collection* collection,
NamespaceString nss,
RecordStore* recordStore,
- std::unique_ptr<Lock::CollectionLock> collLk,
const bool background)
: _opCtx(opCtx),
_collection(collection),
_nss(nss),
_recordStore(recordStore),
- _collLk(std::move(collLk)),
_tracker(opCtx->getServiceContext()->getFastClockSource(),
internalQueryExecYieldIterations.load(),
Milliseconds(internalQueryExecYieldPeriodMS.load())) {
diff --git a/src/mongo/db/catalog/index_consistency.h b/src/mongo/db/catalog/index_consistency.h
index ac90a4278a0..d22696c5b0c 100644
--- a/src/mongo/db/catalog/index_consistency.h
+++ b/src/mongo/db/catalog/index_consistency.h
@@ -90,7 +90,6 @@ public:
Collection* collection,
NamespaceString nss,
RecordStore* recordStore,
- std::unique_ptr<Lock::CollectionLock> collLk,
const bool background);
/**
@@ -169,7 +168,6 @@ private:
Collection* _collection;
const NamespaceString _nss;
const RecordStore* _recordStore;
- std::unique_ptr<Lock::CollectionLock> _collLk;
ElapsedTracker _tracker;
// We map the hashed KeyString values to a bucket which contain the count of how many
diff --git a/src/mongo/db/catalog/uuid_catalog.cpp b/src/mongo/db/catalog/uuid_catalog.cpp
index 6879e677df4..f45f505ecaa 100644
--- a/src/mongo/db/catalog/uuid_catalog.cpp
+++ b/src/mongo/db/catalog/uuid_catalog.cpp
@@ -266,14 +266,10 @@ void UUIDCatalog::setCollectionNamespace(OperationContext* opCtx,
});
}
-void UUIDCatalog::onCloseDatabase(Database* db) {
+void UUIDCatalog::onCloseDatabase(OperationContext* opCtx, Database* db) {
+ invariant(opCtx->lockState()->isW());
for (auto it = begin(db->name()); it != end(); ++it) {
- auto coll = *it;
- if (coll && coll->uuid()) {
- // While the collection does not actually get dropped, we're going to destroy the
- // Collection object, so for purposes of the UUIDCatalog it looks the same.
- deregisterCollectionObject(coll->uuid().get());
- }
+ deregisterCollectionObject(it.uuid().get());
}
auto rid = ResourceId(RESOURCE_DATABASE, db->name());
@@ -358,16 +354,6 @@ boost::optional<CollectionUUID> UUIDCatalog::lookupUUIDByNSS(const NamespaceStri
return boost::none;
}
-std::vector<CollectionCatalogEntry*> UUIDCatalog::getAllCatalogEntriesFromDb(
- StringData dbName) const {
- std::vector<UUID> uuids = getAllCollectionUUIDsFromDb(dbName);
- std::vector<CollectionCatalogEntry*> ret;
- for (auto& uuid : uuids) {
- ret.push_back(lookupCollectionCatalogEntryByUUID(uuid));
- }
- return ret;
-}
-
std::vector<CollectionUUID> UUIDCatalog::getAllCollectionUUIDsFromDb(StringData dbName) const {
stdx::lock_guard<stdx::mutex> lock(_catalogLock);
auto minUuid = UUID::parse("00000000-0000-0000-0000-000000000000").getValue();
@@ -381,10 +367,18 @@ std::vector<CollectionUUID> UUIDCatalog::getAllCollectionUUIDsFromDb(StringData
return ret;
}
-std::vector<NamespaceString> UUIDCatalog::getAllCollectionNamesFromDb(StringData dbName) const {
+std::vector<NamespaceString> UUIDCatalog::getAllCollectionNamesFromDb(OperationContext* opCtx,
+ StringData dbName) const {
+ invariant(opCtx->lockState()->isDbLockedForMode(dbName, MODE_S));
+
+ stdx::lock_guard<stdx::mutex> lock(_catalogLock);
+ auto minUuid = UUID::parse("00000000-0000-0000-0000-000000000000").getValue();
+
std::vector<NamespaceString> ret;
- for (auto catalogEntry : getAllCatalogEntriesFromDb(dbName)) {
- ret.push_back(catalogEntry->ns());
+ for (auto it = _orderedCollections.lower_bound(std::make_pair(dbName.toString(), minUuid));
+ it != _orderedCollections.end() && it->first.first == dbName;
+ ++it) {
+ ret.push_back(it->second->collectionCatalogEntry->ns());
}
return ret;
}
diff --git a/src/mongo/db/catalog/uuid_catalog.h b/src/mongo/db/catalog/uuid_catalog.h
index 7ddc0675301..ca0a7326e64 100644
--- a/src/mongo/db/catalog/uuid_catalog.h
+++ b/src/mongo/db/catalog/uuid_catalog.h
@@ -132,7 +132,7 @@ public:
/**
* Implies onDropCollection for all collections in db, but is not transactional.
*/
- void onCloseDatabase(Database* db);
+ void onCloseDatabase(OperationContext* opCtx, Database* db);
/**
* Register the collection catalog entry with `uuid`. The collection object with `uuid` must not
@@ -218,15 +218,11 @@ public:
boost::optional<CollectionUUID> lookupUUIDByNSS(const NamespaceString& nss) const;
/**
- * This function gets the pointers of all the CollectionCatalogEntries from `dbName`.
- *
- * Returns empty vector if the 'dbName' is not known.
- */
- std::vector<CollectionCatalogEntry*> getAllCatalogEntriesFromDb(StringData dbName) const;
-
- /**
* This function gets the UUIDs of all collections from `dbName`.
*
+ * If the caller does not take a strong database lock, some of UUIDs might no longer exist (due
+ * to collection drop) after this function returns.
+ *
* Returns empty vector if the 'dbName' is not known.
*/
std::vector<CollectionUUID> getAllCollectionUUIDsFromDb(StringData dbName) const;
@@ -234,9 +230,13 @@ public:
/**
* This function gets the ns of all collections from `dbName`. The result is not sorted.
*
+ * Caller must take a strong database lock; otherwise, collections returned could be dropped or
+ * renamed.
+ *
* Returns empty vector if the 'dbName' is not known.
*/
- std::vector<NamespaceString> getAllCollectionNamesFromDb(StringData dbName) const;
+ std::vector<NamespaceString> getAllCollectionNamesFromDb(OperationContext* opCtx,
+ StringData dbName) const;
/**
* This functions gets all the database names. The result is sorted in alphabetical ascending
diff --git a/src/mongo/db/catalog/uuid_catalog_helper.cpp b/src/mongo/db/catalog/uuid_catalog_helper.cpp
new file mode 100644
index 00000000000..1ba42ec7b04
--- /dev/null
+++ b/src/mongo/db/catalog/uuid_catalog_helper.cpp
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2019-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/db/catalog/uuid_catalog_helper.h"
+#include "mongo/db/catalog/collection.h"
+#include "mongo/db/catalog/collection_catalog_entry.h"
+#include "mongo/db/concurrency/d_concurrency.h"
+
+namespace mongo {
+namespace catalog {
+
+void forEachCollectionFromDb(
+ OperationContext* opCtx,
+ StringData dbName,
+ LockMode collLockMode,
+ std::function<bool(Collection* collection, CollectionCatalogEntry* catalogEntry)> callback) {
+
+ UUIDCatalog& uuidCatalog = UUIDCatalog::get(opCtx);
+ for (auto collectionIt = uuidCatalog.begin(dbName); collectionIt != uuidCatalog.end();
+ ++collectionIt) {
+ auto uuid = collectionIt.uuid().get();
+ auto nss = uuidCatalog.lookupNSSByUUID(uuid);
+
+ Lock::CollectionLock clk(opCtx, nss, collLockMode);
+
+ auto collection = uuidCatalog.lookupCollectionByUUID(uuid);
+ auto catalogEntry = uuidCatalog.lookupCollectionCatalogEntryByUUID(uuid);
+ if (!collection || !catalogEntry || catalogEntry->ns() != nss)
+ continue;
+
+ if (!callback(collection, catalogEntry))
+ break;
+ }
+}
+
+} // namespace catalog
+} // namespace mongo
diff --git a/src/mongo/db/catalog/uuid_catalog_helper.h b/src/mongo/db/catalog/uuid_catalog_helper.h
new file mode 100644
index 00000000000..0530618b102
--- /dev/null
+++ b/src/mongo/db/catalog/uuid_catalog_helper.h
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2019-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/db/catalog/uuid_catalog.h"
+#include "mongo/db/concurrency/lock_manager_defs.h"
+
+namespace mongo {
+
+class Collection;
+class CollectionCatalogEntry;
+
+namespace catalog {
+
+/**
+ * Looping through all the collections in the database and run callback function on each one of
+ * them. The return value of the callback decides whether we should continue the loop.
+ */
+void forEachCollectionFromDb(
+ OperationContext* opCtx,
+ StringData dbName,
+ LockMode collLockMode,
+ std::function<bool(Collection* collection, CollectionCatalogEntry* catalogEntry)> callback);
+
+} // namespace catalog
+} // namespace mongo
diff --git a/src/mongo/db/catalog/uuid_catalog_test.cpp b/src/mongo/db/catalog/uuid_catalog_test.cpp
index dd25f8de15b..dedb0582120 100644
--- a/src/mongo/db/catalog/uuid_catalog_test.cpp
+++ b/src/mongo/db/catalog/uuid_catalog_test.cpp
@@ -740,7 +740,7 @@ TEST_F(UUIDCatalogTest, GetAllCollectionNamesAndGetAllDbNames) {
}
std::vector<NamespaceString> dCollList = {d1Coll, d2Coll, d3Coll};
- auto res = catalog.getAllCollectionNamesFromDb("dbD");
+ auto res = catalog.getAllCollectionNamesFromDb(&opCtx, "dbD");
std::sort(res.begin(), res.end());
ASSERT(res == dCollList);