summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/catalog/capped_utils.cpp3
-rw-r--r--src/mongo/db/catalog/capped_utils_test.cpp2
-rw-r--r--src/mongo/db/catalog/catalog_control.cpp15
-rw-r--r--src/mongo/db/catalog/catalog_control_test.cpp8
-rw-r--r--src/mongo/db/catalog/coll_mod.cpp8
-rw-r--r--src/mongo/db/catalog/collection.h3
-rw-r--r--src/mongo/db/catalog/collection_catalog_test.cpp4
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp22
-rw-r--r--src/mongo/db/catalog/collection_impl.h7
-rw-r--r--src/mongo/db/catalog/collection_mock.h15
-rw-r--r--src/mongo/db/catalog/collection_validation.cpp6
-rw-r--r--src/mongo/db/catalog/create_collection_test.cpp2
-rw-r--r--src/mongo/db/catalog/database_impl.cpp28
-rw-r--r--src/mongo/db/catalog/database_test.cpp2
-rw-r--r--src/mongo/db/catalog/index_build_block.cpp4
-rw-r--r--src/mongo/db/catalog/index_catalog_entry_impl.cpp24
-rw-r--r--src/mongo/db/catalog/index_catalog_impl.cpp40
-rw-r--r--src/mongo/db/catalog/multi_index_block.cpp2
-rw-r--r--src/mongo/db/catalog/rename_collection.cpp2
-rw-r--r--src/mongo/db/catalog/rename_collection_test.cpp2
-rw-r--r--src/mongo/db/catalog/validate_state.cpp5
-rw-r--r--src/mongo/db/catalog/validate_state_test.cpp14
-rw-r--r--src/mongo/db/cloner.cpp4
-rw-r--r--src/mongo/db/commands/drop_indexes.cpp6
-rw-r--r--src/mongo/db/commands/list_collections.cpp3
-rw-r--r--src/mongo/db/commands/list_indexes.cpp11
-rw-r--r--src/mongo/db/commands/mr.cpp4
-rw-r--r--src/mongo/db/commands/resize_oplog.cpp2
-rw-r--r--src/mongo/db/index_builds_coordinator.cpp4
-rw-r--r--src/mongo/db/op_observer_impl.cpp2
-rw-r--r--src/mongo/db/repair_database.cpp11
-rw-r--r--src/mongo/db/repair_database.h3
-rw-r--r--src/mongo/db/repair_database_and_check_version.cpp26
-rw-r--r--src/mongo/db/repl/dbcheck.cpp8
-rw-r--r--src/mongo/db/repl/idempotency_test_fixture.cpp8
-rw-r--r--src/mongo/db/repl/oplog.cpp2
-rw-r--r--src/mongo/db/repl/rollback_test_fixture.cpp3
-rw-r--r--src/mongo/db/repl/rs_rollback.cpp7
-rw-r--r--src/mongo/db/repl/rs_rollback_test.cpp7
-rw-r--r--src/mongo/db/repl/storage_interface_impl.cpp3
-rw-r--r--src/mongo/db/repl/storage_interface_impl_test.cpp8
-rw-r--r--src/mongo/db/storage/durable_catalog.h89
-rw-r--r--src/mongo/db/storage/durable_catalog_impl.cpp436
-rw-r--r--src/mongo/db/storage/durable_catalog_impl.h112
-rw-r--r--src/mongo/db/storage/durable_catalog_test_fixture.h58
-rw-r--r--src/mongo/db/storage/kv/durable_catalog_test.cpp204
-rw-r--r--src/mongo/db/storage/kv/kv_engine_test_harness.cpp238
-rw-r--r--src/mongo/db/storage/kv/storage_engine_test.cpp74
-rw-r--r--src/mongo/db/storage/storage_engine.h13
-rw-r--r--src/mongo/db/storage/storage_engine_impl.cpp103
-rw-r--r--src/mongo/db/storage/storage_engine_impl.h14
-rw-r--r--src/mongo/db/storage/storage_engine_test_fixture.h61
-rw-r--r--src/mongo/db/ttl.cpp10
53 files changed, 876 insertions, 876 deletions
diff --git a/src/mongo/db/catalog/capped_utils.cpp b/src/mongo/db/catalog/capped_utils.cpp
index 74bed97f6d5..05692e11536 100644
--- a/src/mongo/db/catalog/capped_utils.cpp
+++ b/src/mongo/db/catalog/capped_utils.cpp
@@ -140,7 +140,8 @@ void cloneCollectionAsCapped(OperationContext* opCtx,
// create new collection
{
- auto options = DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, fromNss);
+ auto options =
+ DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, fromCollection->getCatalogId());
// The capped collection will get its own new unique id, as the conversion isn't reversible,
// so it can't be rolled back.
options.uuid.reset();
diff --git a/src/mongo/db/catalog/capped_utils_test.cpp b/src/mongo/db/catalog/capped_utils_test.cpp
index d621beb280d..986552622c8 100644
--- a/src/mongo/db/catalog/capped_utils_test.cpp
+++ b/src/mongo/db/catalog/capped_utils_test.cpp
@@ -98,7 +98,7 @@ CollectionOptions getCollectionOptions(OperationContext* opCtx, const NamespaceS
auto collection = autoColl.getCollection();
ASSERT_TRUE(collection) << "Unable to get collections options for " << nss
<< " because collection does not exist.";
- return DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, nss);
+ return DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, collection->getCatalogId());
}
// Size of capped collection to be passed to convertToCapped() which accepts a double.
diff --git a/src/mongo/db/catalog/catalog_control.cpp b/src/mongo/db/catalog/catalog_control.cpp
index b7e4dfae103..916deb9f2c7 100644
--- a/src/mongo/db/catalog/catalog_control.cpp
+++ b/src/mongo/db/catalog/catalog_control.cpp
@@ -116,16 +116,17 @@ void openCatalog(OperationContext* opCtx, const MinVisibleTimestampMap& minVisib
// Determine which indexes need to be rebuilt. rebuildIndexesOnCollection() requires that all
// indexes on that collection are done at once, so we use a map to group them together.
StringMap<IndexNameObjs> nsToIndexNameObjMap;
- for (auto indexNamespace : indexesToRebuild.getValue()) {
- NamespaceString collNss(indexNamespace.first);
- auto indexName = indexNamespace.second;
- auto indexSpecs = getIndexNameObjs(
- opCtx, collNss, [&indexName](const std::string& name) { return name == indexName; });
+ for (StorageEngine::IndexIdentifier indexIdentifier : indexesToRebuild.getValue()) {
+ auto indexName = indexIdentifier.indexName;
+ auto indexSpecs =
+ getIndexNameObjs(opCtx,
+ indexIdentifier.catalogId,
+ [&indexName](const std::string& name) { return name == indexName; });
if (!indexSpecs.isOK() || indexSpecs.getValue().first.empty()) {
fassert(40689,
{ErrorCodes::InternalError,
str::stream() << "failed to get index spec for index " << indexName
- << " in collection " << collNss.toString()});
+ << " in collection " << indexIdentifier.nss});
}
auto indexesToRebuild = indexSpecs.getValue();
invariant(
@@ -137,7 +138,7 @@ void openCatalog(OperationContext* opCtx, const MinVisibleTimestampMap& minVisib
str::stream() << "expected to find a list containing exactly 1 index spec, but found "
<< indexesToRebuild.second.size());
- auto& ino = nsToIndexNameObjMap[collNss.ns()];
+ auto& ino = nsToIndexNameObjMap[indexIdentifier.nss.ns()];
ino.first.emplace_back(std::move(indexesToRebuild.first.back()));
ino.second.emplace_back(std::move(indexesToRebuild.second.back()));
}
diff --git a/src/mongo/db/catalog/catalog_control_test.cpp b/src/mongo/db/catalog/catalog_control_test.cpp
index a96fa812f82..21740aa1b12 100644
--- a/src/mongo/db/catalog/catalog_control_test.cpp
+++ b/src/mongo/db/catalog/catalog_control_test.cpp
@@ -96,7 +96,9 @@ public:
return Status(ErrorCodes::CommandNotSupported,
"The current storage engine does not support a concurrent mode.");
}
- Status repairRecordStore(OperationContext* opCtx, const NamespaceString& ns) final {
+ Status repairRecordStore(OperationContext* opCtx,
+ RecordId catalogId,
+ const NamespaceString& ns) final {
return Status::OK();
}
std::unique_ptr<TemporaryRecordStore> makeTemporaryRecordStore(OperationContext* opCtx) final {
@@ -146,9 +148,9 @@ public:
}
void setCachePressureForTest(int pressure) final {}
void triggerJournalFlush() const final {}
- StatusWith<std::vector<CollectionIndexNamePair>> reconcileCatalogAndIdents(
+ StatusWith<std::vector<IndexIdentifier>> reconcileCatalogAndIdents(
OperationContext* opCtx) final {
- return std::vector<CollectionIndexNamePair>();
+ return std::vector<IndexIdentifier>();
}
Timestamp getAllDurableTimestamp() const final {
return {};
diff --git a/src/mongo/db/catalog/coll_mod.cpp b/src/mongo/db/catalog/coll_mod.cpp
index 8ee9582bd1c..38c0a9b4aa3 100644
--- a/src/mongo/db/catalog/coll_mod.cpp
+++ b/src/mongo/db/catalog/coll_mod.cpp
@@ -350,7 +350,7 @@ Status _collModInternal(OperationContext* opCtx,
// options so we save the relevant TTL index data in a separate object.
CollectionOptions oldCollOptions =
- DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, nss);
+ DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, coll->getCatalogId());
boost::optional<TTLCollModInfo> ttlInfo;
@@ -363,8 +363,10 @@ Status _collModInternal(OperationContext* opCtx,
if (SimpleBSONElementComparator::kInstance.evaluate(oldExpireSecs != newExpireSecs)) {
// Change the value of "expireAfterSeconds" on disk.
- DurableCatalog::get(opCtx)->updateTTLSetting(
- opCtx, coll->ns(), cmrOld.idx->indexName(), newExpireSecs.safeNumberLong());
+ DurableCatalog::get(opCtx)->updateTTLSetting(opCtx,
+ coll->getCatalogId(),
+ cmrOld.idx->indexName(),
+ newExpireSecs.safeNumberLong());
// Notify the index catalog that the definition of this index changed. This will
// invalidate the idx pointer in cmrOld. On rollback of this WUOW, the idx pointer
diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h
index 2da11684f68..f4d22f31ee8 100644
--- a/src/mongo/db/catalog/collection.h
+++ b/src/mongo/db/catalog/collection.h
@@ -178,6 +178,7 @@ public:
*/
virtual std::unique_ptr<Collection> make(OperationContext* opCtx,
const NamespaceString& nss,
+ RecordId catalogId,
CollectionUUID uuid,
std::unique_ptr<RecordStore> rs) const = 0;
};
@@ -190,6 +191,8 @@ public:
Collection() = default;
virtual ~Collection() = default;
+ virtual RecordId getCatalogId() const = 0;
+
virtual const NamespaceString& ns() const = 0;
/**
diff --git a/src/mongo/db/catalog/collection_catalog_test.cpp b/src/mongo/db/catalog/collection_catalog_test.cpp
index 205a5647e75..e31e2c9af3e 100644
--- a/src/mongo/db/catalog/collection_catalog_test.cpp
+++ b/src/mongo/db/catalog/collection_catalog_test.cpp
@@ -683,7 +683,7 @@ TEST_F(ForEachCollectionFromDbTest, ForEachCollectionFromDbWithPredicate) {
ASSERT_TRUE(
opCtx->lockState()->isCollectionLockedForMode(collection->ns(), MODE_NONE));
return DurableCatalog::get(opCtx)
- ->getCollectionOptions(opCtx, collection->ns())
+ ->getCollectionOptions(opCtx, collection->getCatalogId())
.temp;
});
@@ -707,7 +707,7 @@ TEST_F(ForEachCollectionFromDbTest, ForEachCollectionFromDbWithPredicate) {
ASSERT_TRUE(
opCtx->lockState()->isCollectionLockedForMode(collection->ns(), MODE_NONE));
return !DurableCatalog::get(opCtx)
- ->getCollectionOptions(opCtx, collection->ns())
+ ->getCollectionOptions(opCtx, collection->getCatalogId())
.temp;
});
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index cadf71b6faf..c5c4912b584 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -190,9 +190,11 @@ StatusWith<CollectionImpl::ValidationAction> _parseValidationAction(StringData n
CollectionImpl::CollectionImpl(OperationContext* opCtx,
const NamespaceString& nss,
+ RecordId catalogId,
UUID uuid,
std::unique_ptr<RecordStore> recordStore)
: _ns(nss),
+ _catalogId(catalogId),
_uuid(uuid),
_recordStore(std::move(recordStore)),
_needCappedLock(supportsDocLocking() && _recordStore && _recordStore->isCapped() &&
@@ -219,13 +221,15 @@ CollectionImpl::~CollectionImpl() {
std::unique_ptr<Collection> CollectionImpl::FactoryImpl::make(
OperationContext* opCtx,
const NamespaceString& nss,
+ RecordId catalogId,
CollectionUUID uuid,
std::unique_ptr<RecordStore> rs) const {
- return std::make_unique<CollectionImpl>(opCtx, nss, uuid, std::move(rs));
+ return std::make_unique<CollectionImpl>(opCtx, nss, catalogId, uuid, std::move(rs));
}
void CollectionImpl::init(OperationContext* opCtx) {
- auto collectionOptions = DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, _ns);
+ auto collectionOptions =
+ DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, getCatalogId());
_collator = parseCollation(opCtx, _ns, collectionOptions.collation);
_validatorDoc = collectionOptions.validator.getOwned();
_validator = uassertStatusOK(
@@ -728,7 +732,7 @@ StatusWith<RecordData> CollectionImpl::updateDocumentWithDamages(
}
bool CollectionImpl::isTemporary(OperationContext* opCtx) const {
- return DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, _ns).temp;
+ return DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, getCatalogId()).temp;
}
bool CollectionImpl::isCapped() const {
@@ -840,7 +844,7 @@ Status CollectionImpl::setValidator(OperationContext* opCtx, BSONObj validatorDo
return statusWithMatcher.getStatus();
DurableCatalog::get(opCtx)->updateValidator(
- opCtx, ns(), validatorDoc, getValidationLevel(), getValidationAction());
+ opCtx, getCatalogId(), validatorDoc, getValidationLevel(), getValidationAction());
opCtx->recoveryUnit()->onRollback([this,
oldValidator = std::move(_validator),
@@ -887,7 +891,7 @@ Status CollectionImpl::setValidationLevel(OperationContext* opCtx, StringData ne
_validationLevel = levelSW.getValue();
DurableCatalog::get(opCtx)->updateValidator(
- opCtx, ns(), _validatorDoc, getValidationLevel(), getValidationAction());
+ opCtx, getCatalogId(), _validatorDoc, getValidationLevel(), getValidationAction());
opCtx->recoveryUnit()->onRollback(
[this, oldValidationLevel]() { this->_validationLevel = oldValidationLevel; });
@@ -907,7 +911,7 @@ Status CollectionImpl::setValidationAction(OperationContext* opCtx, StringData n
DurableCatalog::get(opCtx)->updateValidator(
- opCtx, ns(), _validatorDoc, getValidationLevel(), getValidationAction());
+ opCtx, getCatalogId(), _validatorDoc, getValidationLevel(), getValidationAction());
opCtx->recoveryUnit()->onRollback(
[this, oldValidationAction]() { this->_validationAction = oldValidationAction; });
@@ -931,7 +935,8 @@ Status CollectionImpl::updateValidator(OperationContext* opCtx,
this->_validationAction = oldValidationAction;
});
- DurableCatalog::get(opCtx)->updateValidator(opCtx, ns(), newValidator, newLevel, newAction);
+ DurableCatalog::get(opCtx)->updateValidator(
+ opCtx, getCatalogId(), newValidator, newLevel, newAction);
_validatorDoc = std::move(newValidator);
auto validatorSW =
@@ -1020,7 +1025,8 @@ void CollectionImpl::setNs(NamespaceString nss) {
}
void CollectionImpl::indexBuildSuccess(OperationContext* opCtx, IndexCatalogEntry* index) {
- DurableCatalog::get(opCtx)->indexBuildSuccess(opCtx, ns(), index->descriptor()->indexName());
+ DurableCatalog::get(opCtx)->indexBuildSuccess(
+ opCtx, getCatalogId(), index->descriptor()->indexName());
_indexCatalog->indexBuildSuccess(opCtx, index);
}
diff --git a/src/mongo/db/catalog/collection_impl.h b/src/mongo/db/catalog/collection_impl.h
index a33c507ecda..5e60d4b91db 100644
--- a/src/mongo/db/catalog/collection_impl.h
+++ b/src/mongo/db/catalog/collection_impl.h
@@ -44,6 +44,7 @@ public:
explicit CollectionImpl(OperationContext* opCtx,
const NamespaceString& nss,
+ RecordId catalogId,
UUID uuid,
std::unique_ptr<RecordStore> recordStore);
@@ -53,6 +54,7 @@ public:
public:
std::unique_ptr<Collection> make(OperationContext* opCtx,
const NamespaceString& nss,
+ RecordId catalogId,
CollectionUUID uuid,
std::unique_ptr<RecordStore> rs) const final;
};
@@ -63,6 +65,10 @@ public:
void setNs(NamespaceString nss) final;
+ RecordId getCatalogId() const {
+ return _catalogId;
+ }
+
UUID uuid() const {
return _uuid;
}
@@ -357,6 +363,7 @@ private:
OpDebug* opDebug);
NamespaceString _ns;
+ RecordId _catalogId;
UUID _uuid;
// The RecordStore may be null during a repair operation.
diff --git a/src/mongo/db/catalog/collection_mock.h b/src/mongo/db/catalog/collection_mock.h
index c851d8ceb51..e8a7e2aa2f5 100644
--- a/src/mongo/db/catalog/collection_mock.h
+++ b/src/mongo/db/catalog/collection_mock.h
@@ -31,6 +31,7 @@
#include "mongo/db/catalog/collection.h"
#include "mongo/db/catalog/index_catalog.h"
+#include "mongo/platform/atomic_word.h"
namespace mongo {
@@ -39,15 +40,26 @@ namespace mongo {
*/
class CollectionMock : public Collection {
public:
- CollectionMock(const NamespaceString& ns) : CollectionMock(ns, {}) {}
+ CollectionMock(const NamespaceString& ns)
+ : CollectionMock(ns, std::unique_ptr<IndexCatalog>()) {}
CollectionMock(const NamespaceString& ns, std::unique_ptr<IndexCatalog> indexCatalog)
: _ns(ns), _indexCatalog(std::move(indexCatalog)) {}
+ CollectionMock(const NamespaceString& ns, RecordId catalogId)
+ : _ns(ns), _catalogId(catalogId) {}
~CollectionMock() = default;
void init(OperationContext* opCtx) {
std::abort();
}
+ RecordId getCatalogId() const {
+ return _catalogId;
+ }
+
+ void setCatalogId(RecordId catalogId) {
+ _catalogId = catalogId;
+ }
+
const NamespaceString& ns() const {
return _ns;
}
@@ -263,6 +275,7 @@ public:
private:
UUID _uuid = UUID::gen();
NamespaceString _ns;
+ RecordId _catalogId{0};
std::unique_ptr<IndexCatalog> _indexCatalog;
};
diff --git a/src/mongo/db/catalog/collection_validation.cpp b/src/mongo/db/catalog/collection_validation.cpp
index cfb9fdf102d..83feee3965c 100644
--- a/src/mongo/db/catalog/collection_validation.cpp
+++ b/src/mongo/db/catalog/collection_validation.cpp
@@ -326,7 +326,7 @@ void _validateCatalogEntry(OperationContext* opCtx,
ValidateResults* results) {
Collection* collection = validateState->getCollection();
CollectionOptions options =
- DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, validateState->nss());
+ DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, collection->getCatalogId());
if (options.uuid) {
addErrorIfUnequal(*(options.uuid), validateState->uuid(), "UUID", results);
} else {
@@ -364,11 +364,11 @@ void _validateCatalogEntry(OperationContext* opCtx,
}
std::vector<std::string> indexes;
- DurableCatalog::get(opCtx)->getReadyIndexes(opCtx, validateState->nss(), &indexes);
+ DurableCatalog::get(opCtx)->getReadyIndexes(opCtx, collection->getCatalogId(), &indexes);
for (auto& index : indexes) {
MultikeyPaths multikeyPaths;
const bool isMultikey = DurableCatalog::get(opCtx)->isIndexMultikey(
- opCtx, validateState->nss(), index, &multikeyPaths);
+ opCtx, collection->getCatalogId(), index, &multikeyPaths);
const bool hasMultiKeyPaths = std::any_of(multikeyPaths.begin(),
multikeyPaths.end(),
[](auto& pathSet) { return pathSet.size() > 0; });
diff --git a/src/mongo/db/catalog/create_collection_test.cpp b/src/mongo/db/catalog/create_collection_test.cpp
index 8584212c03f..a75abe4e1f0 100644
--- a/src/mongo/db/catalog/create_collection_test.cpp
+++ b/src/mongo/db/catalog/create_collection_test.cpp
@@ -101,7 +101,7 @@ CollectionOptions getCollectionOptions(OperationContext* opCtx, const NamespaceS
auto collection = autoColl.getCollection();
ASSERT_TRUE(collection) << "Unable to get collections options for " << nss
<< " because collection does not exist.";
- return DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, nss);
+ return DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, collection->getCatalogId());
}
/**
diff --git a/src/mongo/db/catalog/database_impl.cpp b/src/mongo/db/catalog/database_impl.cpp
index 2d8b519bba0..bea3f169399 100644
--- a/src/mongo/db/catalog/database_impl.cpp
+++ b/src/mongo/db/catalog/database_impl.cpp
@@ -183,7 +183,9 @@ void DatabaseImpl::clearTmpCollections(OperationContext* opCtx) const {
};
CollectionCatalog::CollectionInfoFn predicate = [&](const Collection* collection) {
- return DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, collection->ns()).temp;
+ return DurableCatalog::get(opCtx)
+ ->getCollectionOptions(opCtx, collection->getCatalogId())
+ .temp;
};
catalog::forEachCollectionFromDb(opCtx, name(), MODE_X, callback, predicate);
@@ -448,7 +450,8 @@ void DatabaseImpl::_dropCollectionIndexes(OperationContext* opCtx,
LOG(1) << "dropCollection: " << nss << " - dropAllIndexes start";
collection->getIndexCatalog()->dropAllIndexes(opCtx, true);
- invariant(DurableCatalog::get(opCtx)->getTotalIndexCount(opCtx, nss) == 0);
+ invariant(DurableCatalog::get(opCtx)->getTotalIndexCount(opCtx, collection->getCatalogId()) ==
+ 0);
LOG(1) << "dropCollection: " << nss << " - dropAllIndexes done";
}
@@ -458,7 +461,7 @@ Status DatabaseImpl::_finishDropCollection(OperationContext* opCtx,
UUID uuid = collection->uuid();
log() << "Finishing collection drop for " << nss << " (" << uuid << ").";
- auto status = DurableCatalog::get(opCtx)->dropCollection(opCtx, nss);
+ auto status = DurableCatalog::get(opCtx)->dropCollection(opCtx, collection->getCatalogId());
if (!status.isOK())
return status;
@@ -509,7 +512,8 @@ Status DatabaseImpl::renameCollection(OperationContext* opCtx,
Top::get(opCtx->getServiceContext()).collectionDropped(fromNss);
- Status status = DurableCatalog::get(opCtx)->renameCollection(opCtx, fromNss, toNss, stayTemp);
+ Status status = DurableCatalog::get(opCtx)->renameCollection(
+ opCtx, collToRename->getCatalogId(), toNss, stayTemp);
// Set the namespace of 'collToRename' from within the CollectionCatalog. This is necessary
// because
@@ -631,12 +635,16 @@ Collection* DatabaseImpl::createCollection(OperationContext* opCtx,
// Create Collection object
auto storageEngine = opCtx->getServiceContext()->getStorageEngine();
- auto statusWithRecordStore = storageEngine->getCatalog()->createCollection(
- opCtx, nss, optionsWithUUID, true /*allocateDefaultSpace*/);
- massertStatusOK(statusWithRecordStore.getStatus());
- std::unique_ptr<RecordStore> rs = std::move(statusWithRecordStore.getValue());
- std::unique_ptr<Collection> ownedCollection = Collection::Factory::get(opCtx)->make(
- opCtx, nss, optionsWithUUID.uuid.get(), std::move(rs));
+ std::pair<RecordId, std::unique_ptr<RecordStore>> catalogIdRecordStorePair =
+ uassertStatusOK(storageEngine->getCatalog()->createCollection(
+ opCtx, nss, optionsWithUUID, true /*allocateDefaultSpace*/));
+ auto catalogId = catalogIdRecordStorePair.first;
+ std::unique_ptr<Collection> ownedCollection =
+ Collection::Factory::get(opCtx)->make(opCtx,
+ nss,
+ catalogId,
+ optionsWithUUID.uuid.get(),
+ std::move(catalogIdRecordStorePair.second));
auto collection = ownedCollection.get();
ownedCollection->init(opCtx);
diff --git a/src/mongo/db/catalog/database_test.cpp b/src/mongo/db/catalog/database_test.cpp
index aec6f8d42fb..47f2acd3d97 100644
--- a/src/mongo/db/catalog/database_test.cpp
+++ b/src/mongo/db/catalog/database_test.cpp
@@ -369,7 +369,7 @@ TEST_F(DatabaseTest, RenameCollectionPreservesUuidOfSourceCollectionAndUpdatesUu
ASSERT_TRUE(toCollection);
auto toCollectionOptions =
- DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, toCollection->ns());
+ DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, toCollection->getCatalogId());
auto toUuid = toCollectionOptions.uuid;
ASSERT_TRUE(toUuid);
diff --git a/src/mongo/db/catalog/index_build_block.cpp b/src/mongo/db/catalog/index_build_block.cpp
index c7a1578f83e..77c7f04fb60 100644
--- a/src/mongo/db/catalog/index_build_block.cpp
+++ b/src/mongo/db/catalog/index_build_block.cpp
@@ -95,7 +95,7 @@ Status IndexBuildBlock::init(OperationContext* opCtx, Collection* collection) {
// Setup on-disk structures.
const auto protocol = IndexBuildProtocol::kSinglePhase;
Status status = DurableCatalog::get(opCtx)->prepareForIndexBuild(
- opCtx, _nss, descriptor.get(), protocol, isBackgroundSecondaryBuild);
+ opCtx, collection->getCatalogId(), descriptor.get(), protocol, isBackgroundSecondaryBuild);
if (!status.isOK())
return status;
@@ -118,7 +118,7 @@ Status IndexBuildBlock::init(OperationContext* opCtx, Collection* collection) {
DurableCatalog::get(opCtx)->setIndexBuildScanning(
opCtx,
- _nss,
+ collection->getCatalogId(),
_indexCatalogEntry->descriptor()->indexName(),
sideWritesIdent,
constraintsIdent);
diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.cpp b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
index 6e8538bce53..72102857cf3 100644
--- a/src/mongo/db/catalog/index_catalog_entry_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_entry_impl.cpp
@@ -70,7 +70,7 @@ IndexCatalogEntryImpl::IndexCatalogEntryImpl(OperationContext* const opCtx,
_isReady(false),
_isDropped(false),
_prefix(DurableCatalog::get(opCtx)->getIndexPrefix(
- opCtx, _descriptor->parentNS(), _descriptor->indexName())) {
+ opCtx, _descriptor->getCollection()->getCatalogId(), _descriptor->indexName())) {
_descriptor->_cachedEntry = this;
_isReady = _catalogIsReady(opCtx);
@@ -287,7 +287,10 @@ void IndexCatalogEntryImpl::setMultikey(OperationContext* opCtx,
}
fassert(31164, status);
indexMetadataHasChanged = DurableCatalog::get(opCtx)->setIndexIsMultikey(
- opCtx, ns(), _descriptor->indexName(), paths);
+ opCtx,
+ _descriptor->getCollection()->getCatalogId(),
+ _descriptor->indexName(),
+ paths);
opCtx->recoveryUnit()->onCommit(
[onMultikeyCommitFn, indexMetadataHasChanged](boost::optional<Timestamp>) {
onMultikeyCommitFn(indexMetadataHasChanged);
@@ -296,7 +299,7 @@ void IndexCatalogEntryImpl::setMultikey(OperationContext* opCtx,
});
} else {
indexMetadataHasChanged = DurableCatalog::get(opCtx)->setIndexIsMultikey(
- opCtx, ns(), _descriptor->indexName(), paths);
+ opCtx, _descriptor->getCollection()->getCatalogId(), _descriptor->indexName(), paths);
}
opCtx->recoveryUnit()->onCommit(
@@ -308,21 +311,26 @@ void IndexCatalogEntryImpl::setMultikey(OperationContext* opCtx,
// ----
bool IndexCatalogEntryImpl::_catalogIsReady(OperationContext* opCtx) const {
- return DurableCatalog::get(opCtx)->isIndexReady(opCtx, ns(), _descriptor->indexName());
+ return DurableCatalog::get(opCtx)->isIndexReady(
+ opCtx, _descriptor->getCollection()->getCatalogId(), _descriptor->indexName());
}
bool IndexCatalogEntryImpl::_catalogIsPresent(OperationContext* opCtx) const {
- return DurableCatalog::get(opCtx)->isIndexPresent(opCtx, ns(), _descriptor->indexName());
+ return DurableCatalog::get(opCtx)->isIndexPresent(
+ opCtx, _descriptor->getCollection()->getCatalogId(), _descriptor->indexName());
}
bool IndexCatalogEntryImpl::_catalogIsMultikey(OperationContext* opCtx,
MultikeyPaths* multikeyPaths) const {
- return DurableCatalog::get(opCtx)->isIndexMultikey(
- opCtx, ns(), _descriptor->indexName(), multikeyPaths);
+ return DurableCatalog::get(opCtx)->isIndexMultikey(opCtx,
+ _descriptor->getCollection()->getCatalogId(),
+ _descriptor->indexName(),
+ multikeyPaths);
}
KVPrefix IndexCatalogEntryImpl::_catalogGetPrefix(OperationContext* opCtx) const {
- return DurableCatalog::get(opCtx)->getIndexPrefix(opCtx, ns(), _descriptor->indexName());
+ return DurableCatalog::get(opCtx)->getIndexPrefix(
+ opCtx, _descriptor->getCollection()->getCatalogId(), _descriptor->indexName());
}
} // namespace mongo
diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp
index e8f444bcb0f..88ca5640675 100644
--- a/src/mongo/db/catalog/index_catalog_impl.cpp
+++ b/src/mongo/db/catalog/index_catalog_impl.cpp
@@ -93,12 +93,13 @@ IndexCatalogImpl::IndexCatalogImpl(Collection* collection) : _collection(collect
Status IndexCatalogImpl::init(OperationContext* opCtx) {
vector<string> indexNames;
auto durableCatalog = DurableCatalog::get(opCtx);
- durableCatalog->getAllIndexes(opCtx, _collection->ns(), &indexNames);
+ durableCatalog->getAllIndexes(opCtx, _collection->getCatalogId(), &indexNames);
for (size_t i = 0; i < indexNames.size(); i++) {
const string& indexName = indexNames[i];
- BSONObj spec = durableCatalog->getIndexSpec(opCtx, _collection->ns(), indexName).getOwned();
- invariant(durableCatalog->isIndexReady(opCtx, _collection->ns(), indexName));
+ BSONObj spec =
+ durableCatalog->getIndexSpec(opCtx, _collection->getCatalogId(), indexName).getOwned();
+ invariant(durableCatalog->isIndexReady(opCtx, _collection->getCatalogId(), indexName));
BSONObj keyPattern = spec.getObjectField("key");
auto descriptor =
@@ -236,25 +237,26 @@ void IndexCatalogImpl::_logInternalState(OperationContext* opCtx,
std::vector<std::string> readyIndexes;
auto durableCatalog = DurableCatalog::get(opCtx);
- durableCatalog->getAllIndexes(opCtx, _collection->ns(), &allIndexes);
- durableCatalog->getReadyIndexes(opCtx, _collection->ns(), &readyIndexes);
+ durableCatalog->getAllIndexes(opCtx, _collection->getCatalogId(), &allIndexes);
+ durableCatalog->getReadyIndexes(opCtx, _collection->getCatalogId(), &readyIndexes);
error() << "All indexes:";
for (const auto& index : allIndexes) {
error() << "Index '" << index << "' with specification: "
- << redact(durableCatalog->getIndexSpec(opCtx, _collection->ns(), index));
+ << redact(durableCatalog->getIndexSpec(opCtx, _collection->getCatalogId(), index));
}
error() << "Ready indexes:";
for (const auto& index : readyIndexes) {
error() << "Index '" << index << "' with specification: "
- << redact(durableCatalog->getIndexSpec(opCtx, _collection->ns(), index));
+ << redact(durableCatalog->getIndexSpec(opCtx, _collection->getCatalogId(), index));
}
error() << "Index names to drop:";
for (const auto& indexNameToDrop : indexNamesToDrop) {
error() << "Index '" << indexNameToDrop << "' with specification: "
- << redact(durableCatalog->getIndexSpec(opCtx, _collection->ns(), indexNameToDrop));
+ << redact(durableCatalog->getIndexSpec(
+ opCtx, _collection->getCatalogId(), indexNameToDrop));
}
}
@@ -349,8 +351,8 @@ IndexCatalogEntry* IndexCatalogImpl::createIndexEntry(OperationContext* opCtx,
}
auto engine = opCtx->getServiceContext()->getStorageEngine();
- std::string ident =
- engine->getCatalog()->getIndexIdent(opCtx, _collection->ns(), descriptor->indexName());
+ std::string ident = engine->getCatalog()->getIndexIdent(
+ opCtx, _collection->getCatalogId(), descriptor->indexName());
auto* const descriptorPtr = descriptor.get();
auto entry = std::make_shared<IndexCatalogEntryImpl>(
@@ -423,7 +425,7 @@ StatusWith<BSONObj> IndexCatalogImpl::createIndexOnEmptyCollection(OperationCont
// sanity check
invariant(DurableCatalog::get(opCtx)->isIndexReady(
- opCtx, _collection->ns(), descriptor->indexName()));
+ opCtx, _collection->getCatalogId(), descriptor->indexName()));
return spec;
}
@@ -826,7 +828,7 @@ void IndexCatalogImpl::dropAllIndexes(OperationContext* opCtx,
// verify state is sane post cleaning
long long numIndexesInCollectionCatalogEntry =
- DurableCatalog::get(opCtx)->getTotalIndexCount(opCtx, _collection->ns());
+ DurableCatalog::get(opCtx)->getTotalIndexCount(opCtx, _collection->getCatalogId());
if (haveIdIndex) {
fassert(17324, numIndexesTotal(opCtx) == 1);
@@ -934,7 +936,8 @@ Status IndexCatalogImpl::dropIndexEntry(OperationContext* opCtx, IndexCatalogEnt
void IndexCatalogImpl::deleteIndexFromDisk(OperationContext* opCtx, const string& indexName) {
invariant(opCtx->lockState()->isCollectionLockedForMode(_collection->ns(), MODE_X));
- Status status = DurableCatalog::get(opCtx)->removeIndex(opCtx, _collection->ns(), indexName);
+ Status status =
+ DurableCatalog::get(opCtx)->removeIndex(opCtx, _collection->getCatalogId(), indexName);
if (status.code() == ErrorCodes::NamespaceNotFound) {
/*
* This is ok, as we may be partially through index creation.
@@ -988,8 +991,8 @@ int IndexCatalogImpl::numIndexesTotal(OperationContext* opCtx) const {
// This can throw a WriteConflictException when retries on write conflicts are disabled
// during testing. The DurableCatalog fetches the metadata off of the disk using a
// findRecord() call.
- dassert(DurableCatalog::get(opCtx)->getTotalIndexCount(opCtx, _collection->ns()) ==
- count);
+ dassert(DurableCatalog::get(opCtx)->getTotalIndexCount(
+ opCtx, _collection->getCatalogId()) == count);
} catch (const WriteConflictException& ex) {
log() << " Skipping dassert check due to: " << ex;
}
@@ -1007,7 +1010,7 @@ int IndexCatalogImpl::numIndexesReady(OperationContext* opCtx) const {
}
if (kDebugBuild) {
std::vector<std::string> completedIndexes;
- durableCatalog->getReadyIndexes(opCtx, _collection->ns(), &completedIndexes);
+ durableCatalog->getReadyIndexes(opCtx, _collection->getCatalogId(), &completedIndexes);
// There is a potential inconistency where the index information in the collection catalog
// entry and the index catalog differ. Log as much information as possible here.
@@ -1159,7 +1162,7 @@ const IndexDescriptor* IndexCatalogImpl::refreshEntry(OperationContext* opCtx,
const std::string indexName = oldDesc->indexName();
auto durableCatalog = DurableCatalog::get(opCtx);
- invariant(durableCatalog->isIndexReady(opCtx, _collection->ns(), indexName));
+ invariant(durableCatalog->isIndexReady(opCtx, _collection->getCatalogId(), indexName));
// Delete the IndexCatalogEntry that owns this descriptor. After deletion, 'oldDesc' is
// invalid and should not be dereferenced. Also, invalidate the index from the
@@ -1171,7 +1174,8 @@ const IndexDescriptor* IndexCatalogImpl::refreshEntry(OperationContext* opCtx,
CollectionQueryInfo::get(_collection).droppedIndex(opCtx, indexName);
// Ask the CollectionCatalogEntry for the new index spec.
- BSONObj spec = durableCatalog->getIndexSpec(opCtx, _collection->ns(), indexName).getOwned();
+ BSONObj spec =
+ durableCatalog->getIndexSpec(opCtx, _collection->getCatalogId(), indexName).getOwned();
BSONObj keyPattern = spec.getObjectField("key");
// Re-register this index in the index catalog with the new spec. Also, add the new index
diff --git a/src/mongo/db/catalog/multi_index_block.cpp b/src/mongo/db/catalog/multi_index_block.cpp
index 324c64aff8d..15ac455da05 100644
--- a/src/mongo/db/catalog/multi_index_block.cpp
+++ b/src/mongo/db/catalog/multi_index_block.cpp
@@ -841,7 +841,7 @@ Status MultiIndexBlock::commit(OperationContext* opCtx,
opCtx->getServiceContext()->getStorageEngine()->getCheckpointLock(opCtx);
auto indexIdent =
opCtx->getServiceContext()->getStorageEngine()->getCatalog()->getIndexIdent(
- opCtx, collection->ns(), _indexes[i].block->getIndexName());
+ opCtx, collection->getCatalogId(), _indexes[i].block->getIndexName());
opCtx->getServiceContext()->getStorageEngine()->addIndividuallyCheckpointedIndexToList(
indexIdent);
}
diff --git a/src/mongo/db/catalog/rename_collection.cpp b/src/mongo/db/catalog/rename_collection.cpp
index af0a0cce8e2..c70792a1d3a 100644
--- a/src/mongo/db/catalog/rename_collection.cpp
+++ b/src/mongo/db/catalog/rename_collection.cpp
@@ -548,7 +548,7 @@ Status renameBetweenDBs(OperationContext* opCtx,
Collection* tmpColl = nullptr;
{
auto collectionOptions =
- DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, sourceColl->ns());
+ DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, sourceColl->getCatalogId());
// Renaming across databases will result in a new UUID.
collectionOptions.uuid = UUID::gen();
diff --git a/src/mongo/db/catalog/rename_collection_test.cpp b/src/mongo/db/catalog/rename_collection_test.cpp
index 8ef720a9c0c..ebef7bd241e 100644
--- a/src/mongo/db/catalog/rename_collection_test.cpp
+++ b/src/mongo/db/catalog/rename_collection_test.cpp
@@ -430,7 +430,7 @@ CollectionOptions _getCollectionOptions(OperationContext* opCtx, const Namespace
auto collection = autoColl.getCollection();
ASSERT_TRUE(collection) << "Unable to get collections options for " << nss
<< " because collection does not exist.";
- return DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, nss);
+ return DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, collection->getCatalogId());
}
/**
diff --git a/src/mongo/db/catalog/validate_state.cpp b/src/mongo/db/catalog/validate_state.cpp
index f9e0b93c8ac..19a20a178b5 100644
--- a/src/mongo/db/catalog/validate_state.cpp
+++ b/src/mongo/db/catalog/validate_state.cpp
@@ -179,7 +179,8 @@ void ValidateState::initializeCursors(OperationContext* opCtx) {
std::vector<std::string> readyDurableIndexes;
try {
- DurableCatalog::get(opCtx)->getReadyIndexes(opCtx, _nss, &readyDurableIndexes);
+ DurableCatalog::get(opCtx)->getReadyIndexes(
+ opCtx, _collection->getCatalogId(), &readyDurableIndexes);
} catch (const ExceptionFor<ErrorCodes::CursorNotFound>& ex) {
invariant(_background);
log() << "Skipping background validation on collection '" << _nss
@@ -213,7 +214,7 @@ void ValidateState::initializeCursors(OperationContext* opCtx) {
// because its in-memory representation is gone).
auto diskIndexIdent =
opCtx->getServiceContext()->getStorageEngine()->getCatalog()->getIndexIdent(
- opCtx, _nss, desc->indexName());
+ opCtx, _collection->getCatalogId(), desc->indexName());
if (entry->getIdent() != diskIndexIdent) {
log() << "Skipping validation on index '" << desc->indexName() << "' in collection '"
<< _nss << "' because the index was recreated and is not yet in a checkpoint.";
diff --git a/src/mongo/db/catalog/validate_state_test.cpp b/src/mongo/db/catalog/validate_state_test.cpp
index d4d0f65a56e..f4397374908 100644
--- a/src/mongo/db/catalog/validate_state_test.cpp
+++ b/src/mongo/db/catalog/validate_state_test.cpp
@@ -54,11 +54,11 @@ public:
/**
* Create collection 'nss' and insert some documents. It will possess a default _id index.
*/
- void createCollectionAndPopulateIt(OperationContext* opCtx, const NamespaceString& nss);
+ Collection* createCollectionAndPopulateIt(OperationContext* opCtx, const NamespaceString& nss);
};
-void ValidateStateTest::createCollectionAndPopulateIt(OperationContext* opCtx,
- const NamespaceString& nss) {
+Collection* ValidateStateTest::createCollectionAndPopulateIt(OperationContext* opCtx,
+ const NamespaceString& nss) {
// Create collection.
CollectionOptions defaultCollectionOptions;
ASSERT_OK(storageInterface()->createCollection(opCtx, nss, defaultCollectionOptions));
@@ -75,6 +75,8 @@ void ValidateStateTest::createCollectionAndPopulateIt(OperationContext* opCtx,
collection->insertDocument(opCtx, InsertStatement(BSON("_id" << i)), nullOpDebug));
wuow.commit();
}
+
+ return collection;
}
/**
@@ -199,7 +201,7 @@ TEST_F(ValidateStateTest, OpenCursorsOnCheckpointedIndexes) {
// Only open cursors against indexes that are consistent with the rest of the checkpoint'ed data.
TEST_F(ValidateStateTest, OpenCursorsOnConsistentlyCheckpointedIndexes) {
auto opCtx = operationContext();
- createCollectionAndPopulateIt(opCtx, kNss);
+ Collection* coll = createCollectionAndPopulateIt(opCtx, kNss);
// Disable periodic checkpoint'ing thread so we can control when checkpoints occur.
FailPointEnableBlock failPoint("pauseCheckpointThread");
@@ -220,10 +222,10 @@ TEST_F(ValidateStateTest, OpenCursorsOnConsistentlyCheckpointedIndexes) {
opCtx->getServiceContext()->getStorageEngine()->getCheckpointLock(opCtx);
auto indexIdentA =
opCtx->getServiceContext()->getStorageEngine()->getCatalog()->getIndexIdent(
- opCtx, kNss, "a_1");
+ opCtx, coll->getCatalogId(), "a_1");
auto indexIdentB =
opCtx->getServiceContext()->getStorageEngine()->getCatalog()->getIndexIdent(
- opCtx, kNss, "b_1");
+ opCtx, coll->getCatalogId(), "b_1");
opCtx->getServiceContext()->getStorageEngine()->addIndividuallyCheckpointedIndexToList(
indexIdentA);
opCtx->getServiceContext()->getStorageEngine()->addIndividuallyCheckpointedIndexToList(
diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp
index 9c547811e69..c6475cbe0e9 100644
--- a/src/mongo/db/cloner.cpp
+++ b/src/mongo/db/cloner.cpp
@@ -600,8 +600,8 @@ Status Cloner::createCollectionsForDb(
// exists on the target, we check if the existing collection's UUID matches
// that of the one we're trying to create. If it does, we treat the create
// as a no-op; if it doesn't match, we return an error.
- auto existingOpts =
- DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, collection->ns());
+ auto existingOpts = DurableCatalog::get(opCtx)->getCollectionOptions(
+ opCtx, collection->getCatalogId());
const UUID clonedUUID =
uassertStatusOK(UUID::parse(params.collectionInfo["info"]["uuid"]));
diff --git a/src/mongo/db/commands/drop_indexes.cpp b/src/mongo/db/commands/drop_indexes.cpp
index 9c6e5394797..033023ec710 100644
--- a/src/mongo/db/commands/drop_indexes.cpp
+++ b/src/mongo/db/commands/drop_indexes.cpp
@@ -151,7 +151,8 @@ public:
vector<string> indexNames;
writeConflictRetry(opCtx, "listIndexes", toReIndexNss.ns(), [&] {
indexNames.clear();
- DurableCatalog::get(opCtx)->getAllIndexes(opCtx, collection->ns(), &indexNames);
+ DurableCatalog::get(opCtx)->getAllIndexes(
+ opCtx, collection->getCatalogId(), &indexNames);
});
all.reserve(indexNames.size());
@@ -159,7 +160,8 @@ public:
for (size_t i = 0; i < indexNames.size(); i++) {
const string& name = indexNames[i];
BSONObj spec = writeConflictRetry(opCtx, "getIndexSpec", toReIndexNss.ns(), [&] {
- return DurableCatalog::get(opCtx)->getIndexSpec(opCtx, collection->ns(), name);
+ return DurableCatalog::get(opCtx)->getIndexSpec(
+ opCtx, collection->getCatalogId(), name);
});
{
diff --git a/src/mongo/db/commands/list_collections.cpp b/src/mongo/db/commands/list_collections.cpp
index 398c4f4fb36..ca0dab0d375 100644
--- a/src/mongo/db/commands/list_collections.cpp
+++ b/src/mongo/db/commands/list_collections.cpp
@@ -186,7 +186,8 @@ BSONObj buildCollectionBson(OperationContext* opCtx,
return b.obj();
}
- CollectionOptions options = DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, nss);
+ CollectionOptions options =
+ DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, collection->getCatalogId());
// While the UUID is stored as a collection option, from the user's perspective it is an
// unsettable read-only property, so put it in the 'info' section.
diff --git a/src/mongo/db/commands/list_indexes.cpp b/src/mongo/db/commands/list_indexes.cpp
index b7c26eb3309..858b22daba0 100644
--- a/src/mongo/db/commands/list_indexes.cpp
+++ b/src/mongo/db/commands/list_indexes.cpp
@@ -164,7 +164,7 @@ public:
vector<string> indexNames;
writeConflictRetry(opCtx, "listIndexes", nss.ns(), [&] {
indexNames.clear();
- durableCatalog->getAllIndexes(opCtx, nss, &indexNames);
+ durableCatalog->getAllIndexes(opCtx, collection->getCatalogId(), &indexNames);
});
auto ws = std::make_unique<WorkingSet>();
@@ -173,17 +173,20 @@ public:
for (size_t i = 0; i < indexNames.size(); i++) {
auto indexSpec = writeConflictRetry(opCtx, "listIndexes", nss.ns(), [&] {
if (includeBuildUUIDs &&
- !durableCatalog->isIndexReady(opCtx, nss, indexNames[i])) {
+ !durableCatalog->isIndexReady(
+ opCtx, collection->getCatalogId(), indexNames[i])) {
BSONObjBuilder builder;
builder.append("spec"_sd,
- durableCatalog->getIndexSpec(opCtx, nss, indexNames[i]));
+ durableCatalog->getIndexSpec(
+ opCtx, collection->getCatalogId(), indexNames[i]));
// TODO(SERVER-37980): Replace with index build UUID.
auto indexBuildUUID = UUID::gen();
indexBuildUUID.appendToBuilder(&builder, "buildUUID"_sd);
return builder.obj();
}
- return durableCatalog->getIndexSpec(opCtx, nss, indexNames[i]);
+ return durableCatalog->getIndexSpec(
+ opCtx, collection->getCatalogId(), indexNames[i]);
});
WorkingSetID id = ws->allocate();
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index f9f1ced56da..f7bc154dfb8 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -560,8 +560,8 @@ void State::prepTempCollection() {
auto const finalColl = autoGetFinalColl.getCollection();
if (finalColl) {
- finalOptions =
- DurableCatalog::get(_opCtx)->getCollectionOptions(_opCtx, finalColl->ns());
+ finalOptions = DurableCatalog::get(_opCtx)->getCollectionOptions(
+ _opCtx, finalColl->getCatalogId());
std::unique_ptr<IndexCatalog::IndexIterator> ii =
finalColl->getIndexCatalog()->getIndexIterator(_opCtx, true);
diff --git a/src/mongo/db/commands/resize_oplog.cpp b/src/mongo/db/commands/resize_oplog.cpp
index 2cd5f851cb4..31c2153a8da 100644
--- a/src/mongo/db/commands/resize_oplog.cpp
+++ b/src/mongo/db/commands/resize_oplog.cpp
@@ -105,7 +105,7 @@ public:
WriteUnitOfWork wunit(opCtx);
Status status = coll->getRecordStore()->updateCappedSize(opCtx, size);
uassertStatusOK(status);
- DurableCatalog::get(opCtx)->updateCappedSize(opCtx, coll->ns(), size);
+ DurableCatalog::get(opCtx)->updateCappedSize(opCtx, coll->getCatalogId(), size);
wunit.commit();
LOG(0) << "replSetResizeOplog success, currentSize:" << size;
return true;
diff --git a/src/mongo/db/index_builds_coordinator.cpp b/src/mongo/db/index_builds_coordinator.cpp
index 493eecd9aa6..0eaa5962d85 100644
--- a/src/mongo/db/index_builds_coordinator.cpp
+++ b/src/mongo/db/index_builds_coordinator.cpp
@@ -353,8 +353,8 @@ StatusWith<std::pair<long long, long long>> IndexBuildsCoordinator::startIndexRe
auto descriptor = indexCatalog->findIndexByName(opCtx, indexNames[i], false);
if (!descriptor) {
// If it's unfinished index, drop it directly via removeIndex.
- Status status =
- DurableCatalog::get(opCtx)->removeIndex(opCtx, nss, indexNames[i]);
+ Status status = DurableCatalog::get(opCtx)->removeIndex(
+ opCtx, collection->getCatalogId(), indexNames[i]);
continue;
}
Status s = indexCatalog->dropIndex(opCtx, descriptor);
diff --git a/src/mongo/db/op_observer_impl.cpp b/src/mongo/db/op_observer_impl.cpp
index 73d31fd799d..28696a8a95f 100644
--- a/src/mongo/db/op_observer_impl.cpp
+++ b/src/mongo/db/op_observer_impl.cpp
@@ -614,7 +614,7 @@ void OpObserverImpl::onCollMod(OperationContext* opCtx,
Collection* coll = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(nss);
invariant(coll->uuid() == uuid);
- invariant(DurableCatalog::get(opCtx)->isEqualToMetadataUUID(opCtx, nss, uuid));
+ invariant(DurableCatalog::get(opCtx)->isEqualToMetadataUUID(opCtx, coll->getCatalogId(), uuid));
}
void OpObserverImpl::onDropDatabase(OperationContext* opCtx, const std::string& dbName) {
diff --git a/src/mongo/db/repair_database.cpp b/src/mongo/db/repair_database.cpp
index 092857b8a81..19e5a8fe114 100644
--- a/src/mongo/db/repair_database.cpp
+++ b/src/mongo/db/repair_database.cpp
@@ -61,7 +61,7 @@
namespace mongo {
StatusWith<IndexNameObjs> getIndexNameObjs(OperationContext* opCtx,
- const NamespaceString& nss,
+ RecordId catalogId,
std::function<bool(const std::string&)> filter) {
IndexNameObjs ret;
std::vector<std::string>& indexNames = ret.first;
@@ -69,7 +69,7 @@ StatusWith<IndexNameObjs> getIndexNameObjs(OperationContext* opCtx,
auto durableCatalog = DurableCatalog::get(opCtx);
{
// Fetch all indexes
- durableCatalog->getAllIndexes(opCtx, nss, &indexNames);
+ durableCatalog->getAllIndexes(opCtx, catalogId, &indexNames);
auto newEnd =
std::remove_if(indexNames.begin(),
indexNames.end(),
@@ -80,7 +80,7 @@ StatusWith<IndexNameObjs> getIndexNameObjs(OperationContext* opCtx,
for (const auto& name : indexNames) {
- BSONObj spec = durableCatalog->getIndexSpec(opCtx, nss, name);
+ BSONObj spec = durableCatalog->getIndexSpec(opCtx, catalogId, name);
using IndexVersion = IndexDescriptor::IndexVersion;
IndexVersion indexVersion = IndexVersion::kV1;
if (auto indexVersionElem = spec[IndexDescriptor::kIndexVersionFieldName]) {
@@ -147,7 +147,8 @@ Status repairCollections(OperationContext* opCtx,
log() << "Repairing collection " << nss;
- Status status = engine->repairRecordStore(opCtx, nss);
+ auto collection = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(nss);
+ Status status = engine->repairRecordStore(opCtx, collection->getCatalogId(), nss);
if (!status.isOK())
return status;
}
@@ -155,7 +156,7 @@ Status repairCollections(OperationContext* opCtx,
for (const auto& nss : colls) {
opCtx->checkForInterrupt();
auto collection = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(nss);
- auto swIndexNameObjs = getIndexNameObjs(opCtx, nss);
+ auto swIndexNameObjs = getIndexNameObjs(opCtx, collection->getCatalogId());
if (!swIndexNameObjs.isOK())
return swIndexNameObjs.getStatus();
diff --git a/src/mongo/db/repair_database.h b/src/mongo/db/repair_database.h
index 50fed16a86c..6989515b7c6 100644
--- a/src/mongo/db/repair_database.h
+++ b/src/mongo/db/repair_database.h
@@ -33,6 +33,7 @@
#include <string>
#include "mongo/bson/bsonobj.h"
+#include "mongo/db/record_id.h"
namespace mongo {
class Collection;
@@ -52,7 +53,7 @@ typedef std::pair<std::vector<std::string>, std::vector<BSONObj>> IndexNameObjs;
* should be included in the result.
*/
StatusWith<IndexNameObjs> getIndexNameObjs(OperationContext* opCtx,
- const NamespaceString& nss,
+ RecordId catalogId,
std::function<bool(const std::string&)> filter =
[](const std::string& indexName) { return true; });
diff --git a/src/mongo/db/repair_database_and_check_version.cpp b/src/mongo/db/repair_database_and_check_version.cpp
index ab1fedc9cd2..1995e67e60a 100644
--- a/src/mongo/db/repair_database_and_check_version.cpp
+++ b/src/mongo/db/repair_database_and_check_version.cpp
@@ -140,11 +140,11 @@ Status restoreMissingFeatureCompatibilityVersionDocument(OperationContext* opCtx
* Returns true if the collection associated with the given CollectionCatalogEntry has an index on
* the _id field
*/
-bool checkIdIndexExists(OperationContext* opCtx, const NamespaceString& nss) {
+bool checkIdIndexExists(OperationContext* opCtx, RecordId catalogId) {
auto durableCatalog = DurableCatalog::get(opCtx);
- auto indexCount = durableCatalog->getTotalIndexCount(opCtx, nss);
+ auto indexCount = durableCatalog->getTotalIndexCount(opCtx, catalogId);
auto indexNames = std::vector<std::string>(indexCount);
- durableCatalog->getAllIndexes(opCtx, nss, &indexNames);
+ durableCatalog->getAllIndexes(opCtx, catalogId, &indexNames);
for (auto name : indexNames) {
if (name == "_id_") {
@@ -213,13 +213,15 @@ Status ensureCollectionProperties(OperationContext* opCtx,
// All user-created replicated collections created since MongoDB 4.0 have _id indexes.
auto requiresIndex = coll->requiresIdIndex() && coll->ns().isReplicated();
- auto collOptions = DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, coll->ns());
+ auto collOptions =
+ DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, coll->getCatalogId());
auto hasAutoIndexIdField = collOptions.autoIndexId == CollectionOptions::YES;
// Even if the autoIndexId field is not YES, the collection may still have an _id index
// that was created manually by the user. Check the list of indexes to confirm index
// does not exist before attempting to build it or returning an error.
- if (requiresIndex && !hasAutoIndexIdField && !checkIdIndexExists(opCtx, coll->ns())) {
+ if (requiresIndex && !hasAutoIndexIdField &&
+ !checkIdIndexExists(opCtx, coll->getCatalogId())) {
log() << "collection " << coll->ns() << " is missing an _id index; building it now";
auto status = buildMissingIdIndex(opCtx, coll);
if (!status.isOK()) {
@@ -262,7 +264,7 @@ void checkForCappedOplog(OperationContext* opCtx, Database* db) {
}
void rebuildIndexes(OperationContext* opCtx, StorageEngine* storageEngine) {
- std::vector<StorageEngine::CollectionIndexNamePair> indexesToRebuild =
+ std::vector<StorageEngine::IndexIdentifier> indexesToRebuild =
fassert(40593, storageEngine->reconcileCatalogAndIdents(opCtx));
if (!indexesToRebuild.empty() && serverGlobalParams.indexBuildRetry) {
@@ -278,11 +280,13 @@ void rebuildIndexes(OperationContext* opCtx, StorageEngine* storageEngine) {
// Determine which indexes need to be rebuilt. rebuildIndexesOnCollection() requires that all
// indexes on that collection are done at once, so we use a map to group them together.
StringMap<IndexNameObjs> nsToIndexNameObjMap;
- for (auto&& indexNamespace : indexesToRebuild) {
- NamespaceString collNss(indexNamespace.first);
- const std::string& indexName = indexNamespace.second;
- auto swIndexSpecs = getIndexNameObjs(
- opCtx, collNss, [&indexName](const std::string& name) { return name == indexName; });
+ for (auto&& idxIdentifier : indexesToRebuild) {
+ NamespaceString collNss = idxIdentifier.nss;
+ const std::string& indexName = idxIdentifier.indexName;
+ auto swIndexSpecs =
+ getIndexNameObjs(opCtx, idxIdentifier.catalogId, [&indexName](const std::string& name) {
+ return name == indexName;
+ });
if (!swIndexSpecs.isOK() || swIndexSpecs.getValue().first.empty()) {
fassert(40590,
{ErrorCodes::InternalError,
diff --git a/src/mongo/db/repl/dbcheck.cpp b/src/mongo/db/repl/dbcheck.cpp
index 16011047f43..c9e822b0cc3 100644
--- a/src/mongo/db/repl/dbcheck.cpp
+++ b/src/mongo/db/repl/dbcheck.cpp
@@ -359,11 +359,11 @@ std::vector<BSONObj> collectionIndexInfo(OperationContext* opCtx, Collection* co
// List the indices,
auto durableCatalog = DurableCatalog::get(opCtx);
- durableCatalog->getAllIndexes(opCtx, collection->ns(), &names);
+ durableCatalog->getAllIndexes(opCtx, collection->getCatalogId(), &names);
// and get the info for each one.
for (const auto& name : names) {
- result.push_back(durableCatalog->getIndexSpec(opCtx, collection->ns(), name));
+ result.push_back(durableCatalog->getIndexSpec(opCtx, collection->getCatalogId(), name));
}
auto comp = std::make_unique<SimpleBSONObjComparator>();
@@ -374,7 +374,9 @@ std::vector<BSONObj> collectionIndexInfo(OperationContext* opCtx, Collection* co
}
BSONObj collectionOptions(OperationContext* opCtx, Collection* collection) {
- return DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, collection->ns()).toBSON();
+ return DurableCatalog::get(opCtx)
+ ->getCollectionOptions(opCtx, collection->getCatalogId())
+ .toBSON();
}
AutoGetDbForDbCheck::AutoGetDbForDbCheck(OperationContext* opCtx, const NamespaceString& nss)
diff --git a/src/mongo/db/repl/idempotency_test_fixture.cpp b/src/mongo/db/repl/idempotency_test_fixture.cpp
index b06bb4e5f1b..2d398f1a817 100644
--- a/src/mongo/db/repl/idempotency_test_fixture.cpp
+++ b/src/mongo/db/repl/idempotency_test_fixture.cpp
@@ -609,12 +609,14 @@ CollectionState IdempotencyTest::validate(const NamespaceString& nss) {
std::string dataHash = computeDataHash(collection);
auto durableCatalog = DurableCatalog::get(_opCtx.get());
- auto collectionOptions = durableCatalog->getCollectionOptions(_opCtx.get(), collection->ns());
+ auto collectionOptions =
+ durableCatalog->getCollectionOptions(_opCtx.get(), collection->getCatalogId());
std::vector<std::string> allIndexes;
BSONObjSet indexSpecs = SimpleBSONObjComparator::kInstance.makeBSONObjSet();
- durableCatalog->getAllIndexes(_opCtx.get(), collection->ns(), &allIndexes);
+ durableCatalog->getAllIndexes(_opCtx.get(), collection->getCatalogId(), &allIndexes);
for (auto const& index : allIndexes) {
- indexSpecs.insert(durableCatalog->getIndexSpec(_opCtx.get(), collection->ns(), index));
+ indexSpecs.insert(
+ durableCatalog->getIndexSpec(_opCtx.get(), collection->getCatalogId(), index));
}
ASSERT_EQUALS(indexSpecs.size(), allIndexes.size());
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 5f0548d92cb..027b9d80cac 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -594,7 +594,7 @@ void createOplog(OperationContext* opCtx,
if (collection) {
if (replSettings.getOplogSizeBytes() != 0) {
const CollectionOptions oplogOpts =
- DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, oplogCollectionName);
+ DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, collection->getCatalogId());
int o = (int)(oplogOpts.cappedSize / (1024 * 1024));
int n = (int)(replSettings.getOplogSizeBytes() / (1024 * 1024));
diff --git a/src/mongo/db/repl/rollback_test_fixture.cpp b/src/mongo/db/repl/rollback_test_fixture.cpp
index 881a0b2c612..d0b0463fe07 100644
--- a/src/mongo/db/repl/rollback_test_fixture.cpp
+++ b/src/mongo/db/repl/rollback_test_fixture.cpp
@@ -320,7 +320,8 @@ void RollbackResyncsCollectionOptionsTest::resyncCollectionOptionsTest(
// Make sure the collection options are correct.
AutoGetCollectionForReadCommand autoColl(_opCtx.get(), NamespaceString(nss.toString()));
auto collAfterRollbackOptions =
- DurableCatalog::get(_opCtx.get())->getCollectionOptions(_opCtx.get(), nss);
+ DurableCatalog::get(_opCtx.get())
+ ->getCollectionOptions(_opCtx.get(), autoColl.getCollection()->getCatalogId());
BSONObjBuilder expectedOptionsBob;
if (localCollOptions.uuid) {
diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp
index 255dedd9995..87f3448c504 100644
--- a/src/mongo/db/repl/rs_rollback.cpp
+++ b/src/mongo/db/repl/rs_rollback.cpp
@@ -1278,7 +1278,7 @@ void rollback_internal::syncFixUp(OperationContext* opCtx,
WriteUnitOfWork wuow(opCtx);
// Set collection to whatever temp status is on the sync source.
- DurableCatalog::get(opCtx)->setIsTemp(opCtx, *nss, options.temp);
+ DurableCatalog::get(opCtx)->setIsTemp(opCtx, collection->getCatalogId(), options.temp);
// Set any document validation options. We update the validator fields without
// parsing/validation, since we fetched the options object directly from the sync
@@ -1296,8 +1296,9 @@ void rollback_internal::syncFixUp(OperationContext* opCtx,
LOG(1) << "Resynced collection metadata for collection: " << *nss << ", UUID: " << uuid
<< ", with: " << redact(info) << ", to: "
- << redact(
- DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, *nss).toBSON());
+ << redact(DurableCatalog::get(opCtx)
+ ->getCollectionOptions(opCtx, collection->getCatalogId())
+ .toBSON());
}
// Since we read from the sync source to retrieve the metadata of the
diff --git a/src/mongo/db/repl/rs_rollback_test.cpp b/src/mongo/db/repl/rs_rollback_test.cpp
index 337144013b0..9380cbe51ad 100644
--- a/src/mongo/db/repl/rs_rollback_test.cpp
+++ b/src/mongo/db/repl/rs_rollback_test.cpp
@@ -1061,7 +1061,7 @@ TEST_F(RSRollbackTest, RollbackRenameCollectionInSameDatabaseCommand) {
// Remote collection options should have been empty.
auto collAfterRollbackOptions =
DurableCatalog::get(_opCtx.get())
- ->getCollectionOptions(_opCtx.get(), oldCollName.getCollection()->ns());
+ ->getCollectionOptions(_opCtx.get(), oldCollName.getCollection()->getCatalogId());
ASSERT_BSONOBJ_EQ(BSON("uuid" << *options.uuid), collAfterRollbackOptions.toBSON());
}
}
@@ -1117,7 +1117,8 @@ TEST_F(RSRollbackTest,
AutoGetCollectionForReadCommand autoColl(_opCtx.get(), NamespaceString(renameFromNss));
auto collAfterRollbackOptions =
- DurableCatalog::get(_opCtx.get())->getCollectionOptions(_opCtx.get(), renameFromNss);
+ DurableCatalog::get(_opCtx.get())
+ ->getCollectionOptions(_opCtx.get(), autoColl.getCollection()->getCatalogId());
ASSERT_TRUE(collAfterRollbackOptions.temp);
ASSERT_BSONOBJ_EQ(BSON("uuid" << *options.uuid << "temp" << true),
collAfterRollbackOptions.toBSON());
@@ -1712,7 +1713,7 @@ TEST_F(RSRollbackTest, RollbackCollectionModificationCommand) {
AutoGetCollectionForReadCommand autoColl(_opCtx.get(), NamespaceString("test.t"));
auto collAfterRollbackOptions =
DurableCatalog::get(_opCtx.get())
- ->getCollectionOptions(_opCtx.get(), NamespaceString("test.t"));
+ ->getCollectionOptions(_opCtx.get(), autoColl.getCollection()->getCatalogId());
ASSERT_BSONOBJ_EQ(BSON("uuid" << *options.uuid), collAfterRollbackOptions.toBSON());
}
diff --git a/src/mongo/db/repl/storage_interface_impl.cpp b/src/mongo/db/repl/storage_interface_impl.cpp
index 0770b586e37..ef77a529a56 100644
--- a/src/mongo/db/repl/storage_interface_impl.cpp
+++ b/src/mongo/db/repl/storage_interface_impl.cpp
@@ -426,7 +426,8 @@ StatusWith<size_t> StorageInterfaceImpl::getOplogMaxSize(OperationContext* opCtx
return collectionResult.getStatus();
}
- const auto options = DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, nss);
+ const auto options = DurableCatalog::get(opCtx)->getCollectionOptions(
+ opCtx, collectionResult.getValue()->getCatalogId());
if (!options.capped)
return {ErrorCodes::BadValue, str::stream() << nss.ns() << " isn't capped"};
diff --git a/src/mongo/db/repl/storage_interface_impl_test.cpp b/src/mongo/db/repl/storage_interface_impl_test.cpp
index aa3a3fa0b46..6c91cc5e090 100644
--- a/src/mongo/db/repl/storage_interface_impl_test.cpp
+++ b/src/mongo/db/repl/storage_interface_impl_test.cpp
@@ -791,7 +791,9 @@ TEST_F(StorageInterfaceImplTest, RenameCollectionWithStayTempFalseMakesItNotTemp
AutoGetCollectionForReadCommand autoColl2(opCtx, toNss);
ASSERT_TRUE(autoColl2.getCollection());
- ASSERT_FALSE(DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, toNss).temp);
+ ASSERT_FALSE(DurableCatalog::get(opCtx)
+ ->getCollectionOptions(opCtx, autoColl2.getCollection()->getCatalogId())
+ .temp);
}
TEST_F(StorageInterfaceImplTest, RenameCollectionWithStayTempTrueMakesItTemp) {
@@ -810,7 +812,9 @@ TEST_F(StorageInterfaceImplTest, RenameCollectionWithStayTempTrueMakesItTemp) {
AutoGetCollectionForReadCommand autoColl2(opCtx, toNss);
ASSERT_TRUE(autoColl2.getCollection());
- ASSERT_TRUE(DurableCatalog::get(opCtx)->getCollectionOptions(opCtx, toNss).temp);
+ ASSERT_TRUE(DurableCatalog::get(opCtx)
+ ->getCollectionOptions(opCtx, autoColl2.getCollection()->getCatalogId())
+ .temp);
}
TEST_F(StorageInterfaceImplTest, RenameCollectionFailsBetweenDatabases) {
diff --git a/src/mongo/db/storage/durable_catalog.h b/src/mongo/db/storage/durable_catalog.h
index 8a87d2ae37b..a13527268d7 100644
--- a/src/mongo/db/storage/durable_catalog.h
+++ b/src/mongo/db/storage/durable_catalog.h
@@ -54,6 +54,18 @@ protected:
DurableCatalog() = default;
public:
+ /**
+ * `Entry` ties together the common identifiers of a single `_mdb_catalog` document.
+ */
+ struct Entry {
+ Entry() {}
+ Entry(RecordId catalogId, std::string ident, NamespaceString nss)
+ : catalogId(catalogId), ident(std::move(ident)), nss(std::move(nss)) {}
+ RecordId catalogId;
+ std::string ident;
+ NamespaceString nss;
+ };
+
virtual ~DurableCatalog() {}
static DurableCatalog* get(OperationContext* opCtx) {
@@ -62,16 +74,16 @@ public:
virtual void init(OperationContext* opCtx) = 0;
- virtual std::vector<NamespaceString> getAllCollections() const = 0;
+ virtual std::vector<Entry> getAllCatalogEntries(OperationContext* opCtx) const = 0;
- virtual std::string getCollectionIdent(const NamespaceString& nss) const = 0;
+ virtual Entry getEntry(RecordId catalogId) const = 0;
virtual std::string getIndexIdent(OperationContext* opCtx,
- const NamespaceString& nss,
- StringData idName) const = 0;
+ RecordId id,
+ StringData idxName) const = 0;
virtual BSONCollectionCatalogEntry::MetaData getMetaData(OperationContext* opCtx,
- const NamespaceString& nss) const = 0;
+ RecordId id) const = 0;
/**
* Updates the catalog entry for the collection 'nss' with the fields specified in 'md'. If
@@ -79,10 +91,9 @@ public:
* adds it to the catalog entry.
*/
virtual void putMetaData(OperationContext* opCtx,
- const NamespaceString& nss,
+ RecordId id,
BSONCollectionCatalogEntry::MetaData& md) = 0;
- virtual std::vector<std::string> getAllIdentsForDB(StringData db) const = 0;
virtual std::vector<std::string> getAllIdents(OperationContext* opCtx) const = 0;
virtual bool isUserDataIdent(StringData ident) const = 0;
@@ -109,23 +120,27 @@ public:
*/
virtual std::string newInternalIdent() = 0;
- virtual StatusWith<std::unique_ptr<RecordStore>> createCollection(
+ /**
+ * On success, returns the RecordId which identifies the new record store in the durable catalog
+ * in addition to ownership of the new RecordStore.
+ */
+ virtual StatusWith<std::pair<RecordId, std::unique_ptr<RecordStore>>> createCollection(
OperationContext* opCtx,
const NamespaceString& nss,
const CollectionOptions& options,
bool allocateDefaultSpace) = 0;
virtual Status renameCollection(OperationContext* opCtx,
- const NamespaceString& fromNss,
+ RecordId catalogId,
const NamespaceString& toNss,
bool stayTemp) = 0;
- virtual Status dropCollection(OperationContext* opCtx, const NamespaceString& nss) = 0;
+ virtual Status dropCollection(OperationContext* opCtx, RecordId catalogId) = 0;
/**
* Updates size of a capped Collection.
*/
- virtual void updateCappedSize(OperationContext* opCtx, NamespaceString ns, long long size) = 0;
+ virtual void updateCappedSize(OperationContext* opCtx, RecordId catalogId, long long size) = 0;
/*
* Updates the expireAfterSeconds field of the given index to the value in newExpireSecs.
@@ -133,7 +148,7 @@ public:
* that field and newExpireSecs must both be numeric.
*/
virtual void updateTTLSetting(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData idxName,
long long newExpireSeconds) = 0;
@@ -141,16 +156,16 @@ public:
* equal, false otherwise.
*/
virtual bool isEqualToMetadataUUID(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
OptionalCollectionUUID uuid) = 0;
/**
* Updates the 'temp' setting for this collection.
*/
- virtual void setIsTemp(OperationContext* opCtx, NamespaceString ns, bool isTemp) = 0;
+ virtual void setIsTemp(OperationContext* opCtx, RecordId catalogId, bool isTemp) = 0;
virtual boost::optional<std::string> getSideWritesIdent(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const = 0;
/**
@@ -159,13 +174,13 @@ public:
* An empty validator removes all validation.
*/
virtual void updateValidator(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
const BSONObj& validator,
StringData validationLevel,
StringData validationAction) = 0;
virtual Status removeIndex(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) = 0;
/**
@@ -173,7 +188,7 @@ public:
* disk.
*/
virtual Status prepareForIndexBuild(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
const IndexDescriptor* spec,
IndexBuildProtocol indexBuildProtocol,
bool isBackgroundSecondaryBuild) = 0;
@@ -182,7 +197,7 @@ public:
* Returns whether or not the index is being built with the two-phase index build procedure.
*/
virtual bool isTwoPhaseIndexBuild(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const = 0;
/**
@@ -192,7 +207,7 @@ public:
* It is only valid to call this when the index is using the kTwoPhase IndexBuildProtocol.
*/
virtual void setIndexBuildScanning(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName,
std::string sideWritesIdent,
boost::optional<std::string> constraintViolationsIdent) = 0;
@@ -202,7 +217,7 @@ public:
* Returns whether or not this index is building in the "scanning" phase.
*/
virtual bool isIndexBuildScanning(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const = 0;
/**
@@ -211,21 +226,21 @@ public:
* It is only valid to call this when the index is using the kTwoPhase IndexBuildProtocol.
*/
virtual void setIndexBuildDraining(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) = 0;
/**
* Returns whether or not this index is building in the "draining" phase.
*/
virtual bool isIndexBuildDraining(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const = 0;
/**
* Indicate that an index build is completed and the index is ready to use.
*/
virtual void indexBuildSuccess(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) = 0;
/**
@@ -240,7 +255,7 @@ public:
* number of elements in the index key pattern of empty sets.
*/
virtual bool isIndexMultikey(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName,
MultikeyPaths* multikeyPaths) const = 0;
@@ -254,49 +269,49 @@ public:
* This function returns true if the index metadata has changed, and returns false otherwise.
*/
virtual bool setIndexIsMultikey(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName,
const MultikeyPaths& multikeyPaths) = 0;
virtual boost::optional<std::string> getConstraintViolationsIdent(
- OperationContext* opCtx, NamespaceString ns, StringData indexName) const = 0;
+ OperationContext* opCtx, RecordId catalogId, StringData indexName) const = 0;
/**
* Returns the server-compatibility version of the index build procedure.
*/
virtual long getIndexBuildVersion(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const = 0;
virtual CollectionOptions getCollectionOptions(OperationContext* opCtx,
- NamespaceString ns) const = 0;
+ RecordId catalogId) const = 0;
- virtual int getTotalIndexCount(OperationContext* opCtx, NamespaceString ns) const = 0;
+ virtual int getTotalIndexCount(OperationContext* opCtx, RecordId catalogId) const = 0;
- virtual int getCompletedIndexCount(OperationContext* opCtx, NamespaceString ns) const = 0;
+ virtual int getCompletedIndexCount(OperationContext* opCtx, RecordId catalogId) const = 0;
virtual BSONObj getIndexSpec(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const = 0;
virtual void getAllIndexes(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
std::vector<std::string>* names) const = 0;
virtual void getReadyIndexes(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
std::vector<std::string>* names) const = 0;
virtual bool isIndexPresent(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const = 0;
virtual bool isIndexReady(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const = 0;
virtual KVPrefix getIndexPrefix(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const = 0;
};
} // namespace mongo
diff --git a/src/mongo/db/storage/durable_catalog_impl.cpp b/src/mongo/db/storage/durable_catalog_impl.cpp
index 0189a8d22b1..f6511da8264 100644
--- a/src/mongo/db/storage/durable_catalog_impl.cpp
+++ b/src/mongo/db/storage/durable_catalog_impl.cpp
@@ -146,32 +146,32 @@ using std::unique_ptr;
class DurableCatalogImpl::AddIdentChange : public RecoveryUnit::Change {
public:
- AddIdentChange(DurableCatalogImpl* catalog, StringData ident)
- : _catalog(catalog), _ident(ident.toString()) {}
+ AddIdentChange(DurableCatalogImpl* catalog, RecordId catalogId)
+ : _catalog(catalog), _catalogId(catalogId) {}
virtual void commit(boost::optional<Timestamp>) {}
virtual void rollback() {
- stdx::lock_guard<Latch> lk(_catalog->_identsLock);
- _catalog->_idents.erase(_ident);
+ stdx::lock_guard<Latch> lk(_catalog->_catalogIdToEntryMapLock);
+ _catalog->_catalogIdToEntryMap.erase(_catalogId);
}
DurableCatalogImpl* const _catalog;
- const std::string _ident;
+ const RecordId _catalogId;
};
class DurableCatalogImpl::RemoveIdentChange : public RecoveryUnit::Change {
public:
- RemoveIdentChange(DurableCatalogImpl* catalog, StringData ident, const Entry& entry)
- : _catalog(catalog), _ident(ident.toString()), _entry(entry) {}
+ RemoveIdentChange(DurableCatalogImpl* catalog, RecordId catalogId, const Entry& entry)
+ : _catalog(catalog), _catalogId(catalogId), _entry(entry) {}
virtual void commit(boost::optional<Timestamp>) {}
virtual void rollback() {
- stdx::lock_guard<Latch> lk(_catalog->_identsLock);
- _catalog->_idents[_ident] = _entry;
+ stdx::lock_guard<Latch> lk(_catalog->_catalogIdToEntryMapLock);
+ _catalog->_catalogIdToEntryMap[_catalogId] = _entry;
}
DurableCatalogImpl* const _catalog;
- const std::string _ident;
+ const RecordId _catalogId;
const Entry _entry;
};
@@ -402,8 +402,8 @@ std::string DurableCatalogImpl::_newRand() {
bool DurableCatalogImpl::_hasEntryCollidingWithRand() const {
// Only called from init() so don't need to lock.
- for (NSToIdentMap::const_iterator it = _idents.begin(); it != _idents.end(); ++it) {
- if (StringData(it->first).endsWith(_rand))
+ for (auto it = _catalogIdToEntryMap.begin(); it != _catalogIdToEntryMap.end(); ++it) {
+ if (StringData(it->second.ident).endsWith(_rand))
return true;
}
return false;
@@ -424,7 +424,7 @@ std::string DurableCatalogImpl::getFilesystemPathForDb(const std::string& dbName
}
}
-std::string DurableCatalogImpl::_newUniqueIdent(const NamespaceString& nss, const char* kind) {
+std::string DurableCatalogImpl::_newUniqueIdent(NamespaceString nss, const char* kind) {
// If this changes to not put _rand at the end, _hasEntryCollidingWithRand will need fixing.
StringBuilder buf;
if (_directoryPerDb) {
@@ -453,9 +453,9 @@ void DurableCatalogImpl::init(OperationContext* opCtx) {
}
// No rollback since this is just loading already committed data.
- string ns = obj["ns"].String();
string ident = obj["ident"].String();
- _idents[ns] = Entry(ident, record->id);
+ string ns = obj["ns"].String();
+ _catalogIdToEntryMap[record->id] = Entry(record->id, ident, NamespaceString(ns));
}
if (!_featureTracker) {
@@ -470,31 +470,41 @@ void DurableCatalogImpl::init(OperationContext* opCtx) {
}
}
-std::vector<NamespaceString> DurableCatalogImpl::getAllCollections() const {
- stdx::lock_guard<Latch> lk(_identsLock);
- std::vector<NamespaceString> result;
- for (NSToIdentMap::const_iterator it = _idents.begin(); it != _idents.end(); ++it) {
- result.push_back(NamespaceString(it->first));
+std::vector<DurableCatalog::Entry> DurableCatalogImpl::getAllCatalogEntries(
+ OperationContext* opCtx) const {
+ std::vector<DurableCatalog::Entry> ret;
+
+ auto cursor = _rs->getCursor(opCtx);
+ while (auto record = cursor->next()) {
+ BSONObj obj = record->data.releaseToBson();
+ if (FeatureTracker::isFeatureDocument(obj)) {
+ // Skip over the version document because it doesn't correspond to a collection.
+ continue;
+ }
+ string ident = obj["ident"].String();
+ string collName = obj["ns"].String();
+
+ ret.emplace_back(record->id, ident, NamespaceString(collName));
}
- return result;
+
+ return ret;
+}
+
+DurableCatalog::Entry DurableCatalogImpl::getEntry(RecordId catalogId) const {
+ stdx::lock_guard<Latch> lk(_catalogIdToEntryMapLock);
+ auto it = _catalogIdToEntryMap.find(catalogId);
+ invariant(it != _catalogIdToEntryMap.end());
+ return it->second;
}
-Status DurableCatalogImpl::_addEntry(OperationContext* opCtx,
- const NamespaceString& nss,
- const CollectionOptions& options,
- KVPrefix prefix) {
+StatusWith<DurableCatalog::Entry> DurableCatalogImpl::_addEntry(OperationContext* opCtx,
+ NamespaceString nss,
+ const CollectionOptions& options,
+ KVPrefix prefix) {
invariant(opCtx->lockState()->isDbLockedForMode(nss.db(), MODE_IX));
const string ident = _newUniqueIdent(nss, "collection");
- stdx::lock_guard<Latch> lk(_identsLock);
- Entry& old = _idents[nss.toString()];
- if (!old.ident.empty()) {
- return Status(ErrorCodes::NamespaceExists, "collection already exists");
- }
-
- opCtx->recoveryUnit()->registerChange(std::make_unique<AddIdentChange>(this, nss.ns()));
-
BSONObj obj;
{
BSONObjBuilder b;
@@ -511,55 +521,39 @@ Status DurableCatalogImpl::_addEntry(OperationContext* opCtx,
if (!res.isOK())
return res.getStatus();
- old = Entry(ident, res.getValue());
- LOG(1) << "stored meta data for " << nss.ns() << " @ " << res.getValue();
- return Status::OK();
-}
+ stdx::lock_guard<Latch> lk(_catalogIdToEntryMapLock);
+ invariant(_catalogIdToEntryMap.find(res.getValue()) == _catalogIdToEntryMap.end());
+ _catalogIdToEntryMap[res.getValue()] = {res.getValue(), ident, nss};
+ opCtx->recoveryUnit()->registerChange(std::make_unique<AddIdentChange>(this, res.getValue()));
-std::string DurableCatalogImpl::getCollectionIdent(const NamespaceString& nss) const {
- stdx::lock_guard<Latch> lk(_identsLock);
- NSToIdentMap::const_iterator it = _idents.find(nss.toString());
- invariant(it != _idents.end());
- return it->second.ident;
+ LOG(1) << "stored meta data for " << nss.ns() << " @ " << res.getValue();
+ return {{res.getValue(), ident, nss}};
}
std::string DurableCatalogImpl::getIndexIdent(OperationContext* opCtx,
- const NamespaceString& nss,
+ RecordId catalogId,
StringData idxName) const {
- BSONObj obj = _findEntry(opCtx, nss);
+ BSONObj obj = _findEntry(opCtx, catalogId);
BSONObj idxIdent = obj["idxIdent"].Obj();
return idxIdent[idxName].String();
}
-BSONObj DurableCatalogImpl::_findEntry(OperationContext* opCtx,
- const NamespaceString& nss,
- RecordId* out) const {
- RecordId dl;
- {
- stdx::lock_guard<Latch> lk(_identsLock);
- NSToIdentMap::const_iterator it = _idents.find(nss.toString());
- invariant(it != _idents.end(), str::stream() << "Did not find collection. Ns: " << nss);
- dl = it->second.storedLoc;
- }
-
- LOG(3) << "looking up metadata for: " << nss << " @ " << dl;
+BSONObj DurableCatalogImpl::_findEntry(OperationContext* opCtx, RecordId catalogId) const {
+ LOG(3) << "looking up metadata for: " << catalogId;
RecordData data;
- if (!_rs->findRecord(opCtx, dl, &data)) {
+ if (!_rs->findRecord(opCtx, catalogId, &data)) {
// since the in memory meta data isn't managed with mvcc
// its possible for different transactions to see slightly
// different things, which is ok via the locking above.
return BSONObj();
}
- if (out)
- *out = dl;
-
return data.releaseToBson().getOwned();
}
-BSONCollectionCatalogEntry::MetaData DurableCatalogImpl::getMetaData(
- OperationContext* opCtx, const NamespaceString& nss) const {
- BSONObj obj = _findEntry(opCtx, nss);
+BSONCollectionCatalogEntry::MetaData DurableCatalogImpl::getMetaData(OperationContext* opCtx,
+ RecordId catalogId) const {
+ BSONObj obj = _findEntry(opCtx, catalogId);
LOG(3) << " fetched CCE metadata: " << obj;
BSONCollectionCatalogEntry::MetaData md;
const BSONElement mdElement = obj["md"];
@@ -571,10 +565,10 @@ BSONCollectionCatalogEntry::MetaData DurableCatalogImpl::getMetaData(
}
void DurableCatalogImpl::putMetaData(OperationContext* opCtx,
- const NamespaceString& nss,
+ RecordId catalogId,
BSONCollectionCatalogEntry::MetaData& md) {
- RecordId loc;
- BSONObj obj = _findEntry(opCtx, nss, &loc);
+ NamespaceString nss(md.ns);
+ BSONObj obj = _findEntry(opCtx, catalogId);
{
// Remove the index spec 'ns' field if FCV is set to 4.4.
@@ -623,16 +617,15 @@ void DurableCatalogImpl::putMetaData(OperationContext* opCtx,
}
LOG(3) << "recording new metadata: " << obj;
- Status status = _rs->updateRecord(opCtx, loc, obj.objdata(), obj.objsize());
+ Status status = _rs->updateRecord(opCtx, catalogId, obj.objdata(), obj.objsize());
fassert(28521, status);
}
Status DurableCatalogImpl::_replaceEntry(OperationContext* opCtx,
- const NamespaceString& fromNss,
+ RecordId catalogId,
const NamespaceString& toNss,
bool stayTemp) {
- RecordId loc;
- BSONObj old = _findEntry(opCtx, fromNss, &loc).getOwned();
+ BSONObj old = _findEntry(opCtx, catalogId).getOwned();
{
BSONObjBuilder b;
@@ -648,21 +641,24 @@ Status DurableCatalogImpl::_replaceEntry(OperationContext* opCtx,
b.appendElementsUnique(old);
BSONObj obj = b.obj();
- Status status = _rs->updateRecord(opCtx, loc, obj.objdata(), obj.objsize());
+ Status status = _rs->updateRecord(opCtx, catalogId, obj.objdata(), obj.objsize());
fassert(28522, status);
}
- stdx::lock_guard<Latch> lk(_identsLock);
- const NSToIdentMap::iterator fromIt = _idents.find(fromNss.toString());
- invariant(fromIt != _idents.end());
-
- opCtx->recoveryUnit()->registerChange(
- std::make_unique<RemoveIdentChange>(this, fromNss.ns(), fromIt->second));
- opCtx->recoveryUnit()->registerChange(std::make_unique<AddIdentChange>(this, toNss.ns()));
-
- _idents.erase(fromIt);
- _idents[toNss.toString()] = Entry(old["ident"].String(), loc);
+ stdx::lock_guard<Latch> lk(_catalogIdToEntryMapLock);
+ const auto it = _catalogIdToEntryMap.find(catalogId);
+ invariant(it != _catalogIdToEntryMap.end());
+
+ NamespaceString fromName = it->second.nss;
+ it->second.nss = toNss;
+ opCtx->recoveryUnit()->onRollback([this, catalogId, fromName]() {
+ stdx::lock_guard<Latch> lk(_catalogIdToEntryMapLock);
+ const auto it = _catalogIdToEntryMap.find(catalogId);
+ invariant(it != _catalogIdToEntryMap.end());
+ it->second.nss = fromName;
+ });
+ NamespaceString fromNss(fromName);
if (IndexTimestampHelper::requiresGhostCommitTimestampForCatalogWrite(opCtx, fromNss) &&
!fromNss.isDropPendingNamespace()) {
opCtx->recoveryUnit()->setMustBeTimestamped();
@@ -671,40 +667,23 @@ Status DurableCatalogImpl::_replaceEntry(OperationContext* opCtx,
return Status::OK();
}
-Status DurableCatalogImpl::_removeEntry(OperationContext* opCtx, const NamespaceString& nss) {
- invariant(opCtx->lockState()->isCollectionLockedForMode(nss, MODE_X));
- stdx::lock_guard<Latch> lk(_identsLock);
- const NSToIdentMap::iterator it = _idents.find(nss.toString());
- if (it == _idents.end()) {
+Status DurableCatalogImpl::_removeEntry(OperationContext* opCtx, RecordId catalogId) {
+ stdx::lock_guard<Latch> lk(_catalogIdToEntryMapLock);
+ const auto it = _catalogIdToEntryMap.find(catalogId);
+ if (it == _catalogIdToEntryMap.end()) {
return Status(ErrorCodes::NamespaceNotFound, "collection not found");
}
opCtx->recoveryUnit()->registerChange(
- std::make_unique<RemoveIdentChange>(this, nss.ns(), it->second));
+ std::make_unique<RemoveIdentChange>(this, catalogId, it->second));
- LOG(1) << "deleting metadata for " << nss << " @ " << it->second.storedLoc;
- _rs->deleteRecord(opCtx, it->second.storedLoc);
- _idents.erase(it);
+ LOG(1) << "deleting metadata for " << it->second.nss << " @ " << catalogId;
+ _rs->deleteRecord(opCtx, catalogId);
+ _catalogIdToEntryMap.erase(it);
return Status::OK();
}
-std::vector<std::string> DurableCatalogImpl::getAllIdentsForDB(StringData db) const {
- std::vector<std::string> v;
-
- {
- stdx::lock_guard<Latch> lk(_identsLock);
- for (NSToIdentMap::const_iterator it = _idents.begin(); it != _idents.end(); ++it) {
- NamespaceString ns(it->first);
- if (ns.db() != db)
- continue;
- v.push_back(it->second.ident);
- }
- }
-
- return v;
-}
-
std::vector<std::string> DurableCatalogImpl::getAllIdents(OperationContext* opCtx) const {
std::vector<std::string> v;
@@ -757,17 +736,8 @@ StatusWith<std::string> DurableCatalogImpl::newOrphanedIdent(OperationContext* o
// The collection will be named local.orphan.xxxxx.
std::string identNs = ident;
std::replace(identNs.begin(), identNs.end(), '-', '_');
- std::string ns = NamespaceString(NamespaceString::kOrphanCollectionDb,
- NamespaceString::kOrphanCollectionPrefix + identNs)
- .ns();
-
- stdx::lock_guard<Latch> lk(_identsLock);
- Entry& old = _idents[ns];
- if (!old.ident.empty()) {
- return Status(ErrorCodes::NamespaceExists,
- str::stream() << ns << " already exists in the catalog");
- }
- opCtx->recoveryUnit()->registerChange(std::make_unique<AddIdentChange>(this, ns));
+ NamespaceString ns = NamespaceString(NamespaceString::kOrphanCollectionDb,
+ NamespaceString::kOrphanCollectionPrefix + identNs);
// Generate a new UUID for the orphaned collection.
CollectionOptions optionsWithUUID;
@@ -775,10 +745,10 @@ StatusWith<std::string> DurableCatalogImpl::newOrphanedIdent(OperationContext* o
BSONObj obj;
{
BSONObjBuilder b;
- b.append("ns", ns);
+ b.append("ns", ns.ns());
b.append("ident", ident);
BSONCollectionCatalogEntry::MetaData md;
- md.ns = ns;
+ md.ns = ns.ns();
// Default options with newly generated UUID.
md.options = optionsWithUUID;
// Not Prefixed.
@@ -790,12 +760,16 @@ StatusWith<std::string> DurableCatalogImpl::newOrphanedIdent(OperationContext* o
if (!res.isOK())
return res.getStatus();
- old = Entry(ident, res.getValue());
+ stdx::lock_guard<Latch> lk(_catalogIdToEntryMapLock);
+ invariant(_catalogIdToEntryMap.find(res.getValue()) == _catalogIdToEntryMap.end());
+ _catalogIdToEntryMap[res.getValue()] = Entry(res.getValue(), ident, ns);
+ opCtx->recoveryUnit()->registerChange(std::make_unique<AddIdentChange>(this, res.getValue()));
+
LOG(1) << "stored meta data for orphaned collection " << ns << " @ " << res.getValue();
- return StatusWith<std::string>(std::move(ns));
+ return {ns.ns()};
}
-StatusWith<std::unique_ptr<RecordStore>> DurableCatalogImpl::createCollection(
+StatusWith<std::pair<RecordId, std::unique_ptr<RecordStore>>> DurableCatalogImpl::createCollection(
OperationContext* opCtx,
const NamespaceString& nss,
const CollectionOptions& options,
@@ -810,14 +784,13 @@ StatusWith<std::unique_ptr<RecordStore>> DurableCatalogImpl::createCollection(
KVPrefix prefix = KVPrefix::getNextPrefix(nss);
- Status status = _addEntry(opCtx, nss, options, prefix);
- if (!status.isOK())
- return status;
-
- std::string ident = getCollectionIdent(nss);
+ StatusWith<Entry> swEntry = _addEntry(opCtx, nss, options, prefix);
+ if (!swEntry.isOK())
+ return swEntry.getStatus();
+ Entry& entry = swEntry.getValue();
- status =
- _engine->getEngine()->createGroupedRecordStore(opCtx, nss.ns(), ident, options, prefix);
+ Status status = _engine->getEngine()->createGroupedRecordStore(
+ opCtx, nss.ns(), entry.ident, options, prefix);
if (!status.isOK())
return status;
@@ -830,85 +803,64 @@ StatusWith<std::unique_ptr<RecordStore>> DurableCatalogImpl::createCollection(
}
CollectionUUID uuid = options.uuid.get();
- opCtx->recoveryUnit()->onRollback([opCtx, catalog = this, nss, ident, uuid]() {
+ opCtx->recoveryUnit()->onRollback([opCtx, catalog = this, nss, ident = entry.ident, uuid]() {
// Intentionally ignoring failure
catalog->_engine->getEngine()->dropIdent(opCtx, ident).ignore();
});
- auto rs = _engine->getEngine()->getGroupedRecordStore(opCtx, nss.ns(), ident, options, prefix);
+ auto rs =
+ _engine->getEngine()->getGroupedRecordStore(opCtx, nss.ns(), entry.ident, options, prefix);
invariant(rs);
- return std::move(rs);
+ return std::pair<RecordId, std::unique_ptr<RecordStore>>(entry.catalogId, std::move(rs));
}
Status DurableCatalogImpl::renameCollection(OperationContext* opCtx,
- const NamespaceString& fromNss,
+ RecordId catalogId,
const NamespaceString& toNss,
bool stayTemp) {
- invariant(opCtx->lockState()->isCollectionLockedForMode(fromNss, MODE_X));
- invariant(opCtx->lockState()->isCollectionLockedForMode(toNss, MODE_X));
-
- const std::string identFrom = _engine->getCatalog()->getCollectionIdent(fromNss);
-
- Status status =
- _engine->getEngine()->okToRename(opCtx, fromNss.ns(), toNss.ns(), identFrom, nullptr);
- if (!status.isOK())
- return status;
-
- status = _replaceEntry(opCtx, fromNss, toNss, stayTemp);
- if (!status.isOK())
- return status;
-
- const std::string identTo = getCollectionIdent(toNss);
- invariant(identFrom == identTo);
-
- return Status::OK();
+ return _replaceEntry(opCtx, catalogId, toNss, stayTemp);
}
-Status DurableCatalogImpl::dropCollection(OperationContext* opCtx, const NamespaceString& nss) {
- invariant(opCtx->lockState()->isCollectionLockedForMode(nss, MODE_X));
-
- if (!CollectionCatalog::get(opCtx).lookupCollectionByNamespace(nss)) {
- return Status(ErrorCodes::NamespaceNotFound, "cannnot find collection to drop");
+Status DurableCatalogImpl::dropCollection(OperationContext* opCtx, RecordId catalogId) {
+ Entry entry;
+ {
+ stdx::lock_guard<Latch> lk(_catalogIdToEntryMapLock);
+ entry = _catalogIdToEntryMap[catalogId];
}
- auto& catalog = CollectionCatalog::get(opCtx);
- auto uuid = catalog.lookupUUIDByNSS(nss);
-
- invariant(getTotalIndexCount(opCtx, nss) == getCompletedIndexCount(opCtx, nss));
-
+ invariant(opCtx->lockState()->isCollectionLockedForMode(entry.nss, MODE_X));
+ invariant(getTotalIndexCount(opCtx, catalogId) == getCompletedIndexCount(opCtx, catalogId));
{
std::vector<std::string> indexNames;
- getAllIndexes(opCtx, nss, &indexNames);
+ getAllIndexes(opCtx, catalogId, &indexNames);
for (size_t i = 0; i < indexNames.size(); i++) {
- Status status = removeIndex(opCtx, nss, indexNames[i]);
+ Status status = removeIndex(opCtx, catalogId, indexNames[i]);
}
}
- invariant(getTotalIndexCount(opCtx, nss) == 0);
-
- const std::string ident = getCollectionIdent(nss);
+ invariant(getTotalIndexCount(opCtx, catalogId) == 0);
// Remove metadata from mdb_catalog
- Status status = _removeEntry(opCtx, nss);
+ Status status = _removeEntry(opCtx, catalogId);
if (!status.isOK()) {
return status;
}
// This will notify the storageEngine to drop the collection only on WUOW::commit().
opCtx->recoveryUnit()->onCommit(
- [opCtx, catalog = this, nss, uuid, ident](boost::optional<Timestamp> commitTimestamp) {
+ [opCtx, catalog = this, entry](boost::optional<Timestamp> commitTimestamp) {
StorageEngineInterface* engine = catalog->_engine;
auto storageEngine = engine->getStorageEngine();
if (storageEngine->supportsPendingDrops() && commitTimestamp) {
- log() << "Deferring table drop for collection '" << nss << "' (" << uuid << ")"
- << ". Ident: " << ident << ", commit timestamp: " << commitTimestamp;
- engine->addDropPendingIdent(*commitTimestamp, nss, ident);
+ log() << "Deferring table drop for collection '" << entry.nss
+ << "'. Ident: " << entry.ident << ", commit timestamp: " << commitTimestamp;
+ engine->addDropPendingIdent(*commitTimestamp, entry.nss, entry.ident);
} else {
// Intentionally ignoring failure here. Since we've removed the metadata pointing to
// the collection, we should never see it again anyway.
auto kvEngine = engine->getEngine();
- kvEngine->dropIdent(opCtx, ident).ignore();
+ kvEngine->dropIdent(opCtx, entry.ident).ignore();
}
});
@@ -916,85 +868,85 @@ Status DurableCatalogImpl::dropCollection(OperationContext* opCtx, const Namespa
}
void DurableCatalogImpl::updateCappedSize(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
long long size) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
md.options.cappedSize = size;
- putMetaData(opCtx, ns, md);
+ putMetaData(opCtx, catalogId, md);
}
void DurableCatalogImpl::updateTTLSetting(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData idxName,
long long newExpireSeconds) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(idxName);
invariant(offset >= 0);
md.indexes[offset].updateTTLSetting(newExpireSeconds);
- putMetaData(opCtx, ns, md);
+ putMetaData(opCtx, catalogId, md);
}
bool DurableCatalogImpl::isEqualToMetadataUUID(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
OptionalCollectionUUID uuid) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
return md.options.uuid && md.options.uuid == uuid;
}
-void DurableCatalogImpl::setIsTemp(OperationContext* opCtx, NamespaceString ns, bool isTemp) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+void DurableCatalogImpl::setIsTemp(OperationContext* opCtx, RecordId catalogId, bool isTemp) {
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
md.options.temp = isTemp;
- putMetaData(opCtx, ns, md);
+ putMetaData(opCtx, catalogId, md);
}
boost::optional<std::string> DurableCatalogImpl::getSideWritesIdent(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
return md.indexes[offset].sideWritesIdent;
}
void DurableCatalogImpl::updateValidator(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
const BSONObj& validator,
StringData validationLevel,
StringData validationAction) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
md.options.validator = validator;
md.options.validationLevel = validationLevel.toString();
md.options.validationAction = validationAction.toString();
- putMetaData(opCtx, ns, md);
+ putMetaData(opCtx, catalogId, md);
}
Status DurableCatalogImpl::removeIndex(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
if (md.findIndexOffset(indexName) < 0)
return Status::OK(); // never had the index so nothing to do.
- const string ident = getIndexIdent(opCtx, ns, indexName);
+ const string ident = getIndexIdent(opCtx, catalogId, indexName);
md.eraseIndex(indexName);
- putMetaData(opCtx, ns, md);
+ putMetaData(opCtx, catalogId, md);
// Lazily remove to isolate underlying engine from rollback.
- opCtx->recoveryUnit()->registerChange(
- std::make_unique<RemoveIndexChange>(opCtx, _engine, md.options.uuid, ns, indexName, ident));
+ opCtx->recoveryUnit()->registerChange(std::make_unique<RemoveIndexChange>(
+ opCtx, _engine, md.options.uuid, NamespaceString(md.ns), indexName, ident));
return Status::OK();
}
Status DurableCatalogImpl::prepareForIndexBuild(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
const IndexDescriptor* spec,
IndexBuildProtocol indexBuildProtocol,
bool isBackgroundSecondaryBuild) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
- KVPrefix prefix = KVPrefix::getNextPrefix(ns);
+ KVPrefix prefix = KVPrefix::getNextPrefix(NamespaceString(md.ns));
BSONCollectionCatalogEntry::IndexMetaData imd;
imd.spec = spec->infoObj();
imd.ready = false;
@@ -1020,13 +972,13 @@ Status DurableCatalogImpl::prepareForIndexBuild(OperationContext* opCtx,
}
md.indexes.push_back(imd);
- putMetaData(opCtx, ns, md);
+ putMetaData(opCtx, catalogId, md);
- string ident = getIndexIdent(opCtx, ns, spec->indexName());
+ string ident = getIndexIdent(opCtx, catalogId, spec->indexName());
auto kvEngine = _engine->getEngine();
const Status status = kvEngine->createGroupedSortedDataInterface(
- opCtx, getCollectionOptions(opCtx, ns), ident, spec, prefix);
+ opCtx, getCollectionOptions(opCtx, catalogId), ident, spec, prefix);
if (status.isOK()) {
opCtx->recoveryUnit()->registerChange(
std::make_unique<AddIndexChange>(opCtx, _engine, ident));
@@ -1036,9 +988,9 @@ Status DurableCatalogImpl::prepareForIndexBuild(OperationContext* opCtx,
}
bool DurableCatalogImpl::isTwoPhaseIndexBuild(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
return md.indexes[offset].runTwoPhaseBuild;
@@ -1046,11 +998,11 @@ bool DurableCatalogImpl::isTwoPhaseIndexBuild(OperationContext* opCtx,
void DurableCatalogImpl::setIndexBuildScanning(
OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName,
std::string sideWritesIdent,
boost::optional<std::string> constraintViolationsIdent) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
invariant(!md.indexes[offset].ready);
@@ -1060,13 +1012,13 @@ void DurableCatalogImpl::setIndexBuildScanning(
md.indexes[offset].buildPhase = BSONCollectionCatalogEntry::kIndexBuildScanning.toString();
md.indexes[offset].sideWritesIdent = sideWritesIdent;
md.indexes[offset].constraintViolationsIdent = constraintViolationsIdent;
- putMetaData(opCtx, ns, md);
+ putMetaData(opCtx, catalogId, md);
}
bool DurableCatalogImpl::isIndexBuildScanning(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
return md.indexes[offset].buildPhase ==
@@ -1074,9 +1026,9 @@ bool DurableCatalogImpl::isIndexBuildScanning(OperationContext* opCtx,
}
void DurableCatalogImpl::setIndexBuildDraining(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
invariant(!md.indexes[offset].ready);
@@ -1085,13 +1037,13 @@ void DurableCatalogImpl::setIndexBuildDraining(OperationContext* opCtx,
BSONCollectionCatalogEntry::kIndexBuildScanning.toString());
md.indexes[offset].buildPhase = BSONCollectionCatalogEntry::kIndexBuildDraining.toString();
- putMetaData(opCtx, ns, md);
+ putMetaData(opCtx, catalogId, md);
}
bool DurableCatalogImpl::isIndexBuildDraining(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
return md.indexes[offset].buildPhase ==
@@ -1099,9 +1051,9 @@ bool DurableCatalogImpl::isIndexBuildDraining(OperationContext* opCtx,
}
void DurableCatalogImpl::indexBuildSuccess(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
md.indexes[offset].ready = true;
@@ -1109,14 +1061,14 @@ void DurableCatalogImpl::indexBuildSuccess(OperationContext* opCtx,
md.indexes[offset].buildPhase = boost::none;
md.indexes[offset].sideWritesIdent = boost::none;
md.indexes[offset].constraintViolationsIdent = boost::none;
- putMetaData(opCtx, ns, md);
+ putMetaData(opCtx, catalogId, md);
}
bool DurableCatalogImpl::isIndexMultikey(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName,
MultikeyPaths* multikeyPaths) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
@@ -1129,10 +1081,10 @@ bool DurableCatalogImpl::isIndexMultikey(OperationContext* opCtx,
}
bool DurableCatalogImpl::setIndexIsMultikey(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName,
const MultikeyPaths& multikeyPaths) {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
@@ -1179,41 +1131,41 @@ bool DurableCatalogImpl::setIndexIsMultikey(OperationContext* opCtx,
}
}
- putMetaData(opCtx, ns, md);
+ putMetaData(opCtx, catalogId, md);
return true;
}
boost::optional<std::string> DurableCatalogImpl::getConstraintViolationsIdent(
- OperationContext* opCtx, NamespaceString ns, StringData indexName) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ OperationContext* opCtx, RecordId catalogId, StringData indexName) const {
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
return md.indexes[offset].constraintViolationsIdent;
}
long DurableCatalogImpl::getIndexBuildVersion(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
return md.indexes[offset].versionOfBuild;
}
CollectionOptions DurableCatalogImpl::getCollectionOptions(OperationContext* opCtx,
- NamespaceString ns) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ RecordId catalogId) const {
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
return md.options;
}
-int DurableCatalogImpl::getTotalIndexCount(OperationContext* opCtx, NamespaceString ns) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+int DurableCatalogImpl::getTotalIndexCount(OperationContext* opCtx, RecordId catalogId) const {
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
return static_cast<int>(md.indexes.size());
}
-int DurableCatalogImpl::getCompletedIndexCount(OperationContext* opCtx, NamespaceString ns) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+int DurableCatalogImpl::getCompletedIndexCount(OperationContext* opCtx, RecordId catalogId) const {
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int num = 0;
for (unsigned i = 0; i < md.indexes.size(); i++) {
@@ -1224,9 +1176,9 @@ int DurableCatalogImpl::getCompletedIndexCount(OperationContext* opCtx, Namespac
}
BSONObj DurableCatalogImpl::getIndexSpec(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
@@ -1236,9 +1188,9 @@ BSONObj DurableCatalogImpl::getIndexSpec(OperationContext* opCtx,
}
void DurableCatalogImpl::getAllIndexes(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
std::vector<std::string>* names) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
for (unsigned i = 0; i < md.indexes.size(); i++) {
names->push_back(md.indexes[i].spec["name"].String());
@@ -1246,9 +1198,9 @@ void DurableCatalogImpl::getAllIndexes(OperationContext* opCtx,
}
void DurableCatalogImpl::getReadyIndexes(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
std::vector<std::string>* names) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
for (unsigned i = 0; i < md.indexes.size(); i++) {
if (md.indexes[i].ready)
@@ -1257,17 +1209,17 @@ void DurableCatalogImpl::getReadyIndexes(OperationContext* opCtx,
}
bool DurableCatalogImpl::isIndexPresent(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
return offset >= 0;
}
bool DurableCatalogImpl::isIndexReady(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
@@ -1275,9 +1227,9 @@ bool DurableCatalogImpl::isIndexReady(OperationContext* opCtx,
}
KVPrefix DurableCatalogImpl::getIndexPrefix(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const {
- BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns);
+ BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, catalogId);
int offset = md.findIndexOffset(indexName);
invariant(offset >= 0);
return md.indexes[offset].prefix;
diff --git a/src/mongo/db/storage/durable_catalog_impl.h b/src/mongo/db/storage/durable_catalog_impl.h
index f99ff41da5b..9767f1bb637 100644
--- a/src/mongo/db/storage/durable_catalog_impl.h
+++ b/src/mongo/db/storage/durable_catalog_impl.h
@@ -65,21 +65,22 @@ public:
void init(OperationContext* opCtx);
- std::vector<NamespaceString> getAllCollections() const;
+ std::vector<Entry> getAllCatalogEntries(OperationContext* opCtx) const;
- std::string getCollectionIdent(const NamespaceString& nss) const;
+ Entry getEntry(RecordId catalogId) const;
+
+ std::string getCollectionIdent(RecordId catalogId) const;
std::string getIndexIdent(OperationContext* opCtx,
- const NamespaceString& nss,
- StringData idName) const;
+ RecordId catalogId,
+ StringData idxName) const;
BSONCollectionCatalogEntry::MetaData getMetaData(OperationContext* opCtx,
- const NamespaceString& nss) const;
+ RecordId catalogId) const;
void putMetaData(OperationContext* opCtx,
- const NamespaceString& nss,
+ RecordId catalogId,
BSONCollectionCatalogEntry::MetaData& md);
- std::vector<std::string> getAllIdentsForDB(StringData db) const;
std::vector<std::string> getAllIdents(OperationContext* opCtx) const;
bool isUserDataIdent(StringData ident) const;
@@ -103,112 +104,113 @@ public:
std::string newInternalIdent();
- StatusWith<std::unique_ptr<RecordStore>> createCollection(OperationContext* opCtx,
- const NamespaceString& nss,
- const CollectionOptions& options,
- bool allocateDefaultSpace);
+ StatusWith<std::pair<RecordId, std::unique_ptr<RecordStore>>> createCollection(
+ OperationContext* opCtx,
+ const NamespaceString& nss,
+ const CollectionOptions& options,
+ bool allocateDefaultSpace);
Status renameCollection(OperationContext* opCtx,
- const NamespaceString& fromNss,
+ RecordId catalogId,
const NamespaceString& toNss,
bool stayTemp);
- Status dropCollection(OperationContext* opCtx, const NamespaceString& nss);
+ Status dropCollection(OperationContext* opCtx, RecordId catalogId);
- void updateCappedSize(OperationContext* opCtx, NamespaceString ns, long long size);
+ void updateCappedSize(OperationContext* opCtx, RecordId catalogId, long long size);
void updateTTLSetting(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData idxName,
long long newExpireSeconds);
bool isEqualToMetadataUUID(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
OptionalCollectionUUID uuid);
- void setIsTemp(OperationContext* opCtx, NamespaceString ns, bool isTemp);
+ void setIsTemp(OperationContext* opCtx, RecordId catalogId, bool isTemp);
boost::optional<std::string> getSideWritesIdent(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const;
void updateValidator(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
const BSONObj& validator,
StringData validationLevel,
StringData validationAction);
- Status removeIndex(OperationContext* opCtx, NamespaceString ns, StringData indexName);
+ Status removeIndex(OperationContext* opCtx, RecordId catalogId, StringData indexName);
Status prepareForIndexBuild(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
const IndexDescriptor* spec,
IndexBuildProtocol indexBuildProtocol,
bool isBackgroundSecondaryBuild);
bool isTwoPhaseIndexBuild(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const;
void setIndexBuildScanning(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName,
std::string sideWritesIdent,
boost::optional<std::string> constraintViolationsIdent);
bool isIndexBuildScanning(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const;
- void setIndexBuildDraining(OperationContext* opCtx, NamespaceString ns, StringData indexName);
+ void setIndexBuildDraining(OperationContext* opCtx, RecordId catalogId, StringData indexName);
bool isIndexBuildDraining(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const;
- void indexBuildSuccess(OperationContext* opCtx, NamespaceString ns, StringData indexName);
+ void indexBuildSuccess(OperationContext* opCtx, RecordId catalogId, StringData indexName);
bool isIndexMultikey(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName,
MultikeyPaths* multikeyPaths) const;
bool setIndexIsMultikey(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName,
const MultikeyPaths& multikeyPaths);
boost::optional<std::string> getConstraintViolationsIdent(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const;
long getIndexBuildVersion(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const;
- CollectionOptions getCollectionOptions(OperationContext* opCtx, NamespaceString ns) const;
+ CollectionOptions getCollectionOptions(OperationContext* opCtx, RecordId catalogId) const;
- int getTotalIndexCount(OperationContext* opCtx, NamespaceString ns) const;
+ int getTotalIndexCount(OperationContext* opCtx, RecordId catalogId) const;
- int getCompletedIndexCount(OperationContext* opCtx, NamespaceString ns) const;
+ int getCompletedIndexCount(OperationContext* opCtx, RecordId catalogId) const;
- BSONObj getIndexSpec(OperationContext* opCtx, NamespaceString ns, StringData indexName) const;
+ BSONObj getIndexSpec(OperationContext* opCtx, RecordId catalogId, StringData indexName) const;
void getAllIndexes(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
std::vector<std::string>* names) const;
void getReadyIndexes(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
std::vector<std::string>* names) const;
- bool isIndexPresent(OperationContext* opCtx, NamespaceString ns, StringData indexName) const;
+ bool isIndexPresent(OperationContext* opCtx, RecordId catalogId, StringData indexName) const;
- bool isIndexReady(OperationContext* opCtx, NamespaceString ns, StringData indexName) const;
+ bool isIndexReady(OperationContext* opCtx, RecordId catalogId, StringData indexName) const;
KVPrefix getIndexPrefix(OperationContext* opCtx,
- NamespaceString ns,
+ RecordId catalogId,
StringData indexName) const;
private:
@@ -221,25 +223,23 @@ private:
friend class DurableCatalogImplTest;
friend class StorageEngineTest;
- BSONObj _findEntry(OperationContext* opCtx,
- const NamespaceString& nss,
- RecordId* out = nullptr) const;
- Status _addEntry(OperationContext* opCtx,
- const NamespaceString& nss,
- const CollectionOptions& options,
- KVPrefix prefix);
+ BSONObj _findEntry(OperationContext* opCtx, RecordId catalogId) const;
+ StatusWith<Entry> _addEntry(OperationContext* opCtx,
+ NamespaceString nss,
+ const CollectionOptions& options,
+ KVPrefix prefix);
Status _replaceEntry(OperationContext* opCtx,
- const NamespaceString& fromNss,
+ RecordId catalogId,
const NamespaceString& toNss,
bool stayTemp);
- Status _removeEntry(OperationContext* opCtx, const NamespaceString& nss);
+ Status _removeEntry(OperationContext* opCtx, RecordId catalogId);
/**
* Generates a new unique identifier for a new "thing".
* @param nss - the containing namespace
* @param kind - what this "thing" is, likely collection or index
*/
- std::string _newUniqueIdent(const NamespaceString& nss, const char* kind);
+ std::string _newUniqueIdent(NamespaceString nss, const char* kind);
// Helpers only used by constructor and init(). Don't call from elsewhere.
static std::string _newRand();
@@ -253,15 +253,9 @@ private:
std::string _rand; // effectively const after init() returns
AtomicWord<unsigned long long> _next;
- struct Entry {
- Entry() {}
- Entry(std::string i, RecordId l) : ident(i), storedLoc(l) {}
- std::string ident;
- RecordId storedLoc;
- };
- typedef std::map<std::string, Entry> NSToIdentMap;
- NSToIdentMap _idents;
- mutable Mutex _identsLock = MONGO_MAKE_LATCH("DurableCatalogImpl::_identsLock");
+ std::map<RecordId, Entry> _catalogIdToEntryMap;
+ mutable Mutex _catalogIdToEntryMapLock =
+ MONGO_MAKE_LATCH("DurableCatalogImpl::_catalogIdToEntryMap");
// Manages the feature document that may be present in the DurableCatalogImpl. '_featureTracker'
// is guaranteed to be non-null after DurableCatalogImpl::init() is called.
diff --git a/src/mongo/db/storage/durable_catalog_test_fixture.h b/src/mongo/db/storage/durable_catalog_test_fixture.h
deleted file mode 100644
index 2c895bedef7..00000000000
--- a/src/mongo/db/storage/durable_catalog_test_fixture.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * 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/storage/durable_catalog_impl.h"
-#include "mongo/unittest/unittest.h"
-
-namespace mongo {
-class DurableCatalogImplTest : public unittest::Test {
-protected:
- Status newCollection(OperationContext* opCtx,
- const NamespaceString& ns,
- const CollectionOptions& options,
- KVPrefix prefix,
- DurableCatalogImpl* catalog) {
- return catalog->_addEntry(opCtx, ns, options, prefix);
- }
- Status renameCollection(OperationContext* opCtx,
- StringData fromNS,
- StringData toNS,
- bool stayTemp,
- DurableCatalogImpl* catalog) {
- return catalog->_replaceEntry(
- opCtx, NamespaceString(fromNS), NamespaceString(toNS), stayTemp);
- }
-
- Status dropCollection(OperationContext* opCtx, StringData ns, DurableCatalogImpl* catalog) {
- return catalog->_removeEntry(opCtx, NamespaceString(ns));
- }
-};
-} // namespace mongo
diff --git a/src/mongo/db/storage/kv/durable_catalog_test.cpp b/src/mongo/db/storage/kv/durable_catalog_test.cpp
index 2a93def21d7..d8c2be64ff2 100644
--- a/src/mongo/db/storage/kv/durable_catalog_test.cpp
+++ b/src/mongo/db/storage/kv/durable_catalog_test.cpp
@@ -83,9 +83,11 @@ public:
const bool allocateDefaultSpace = true;
CollectionOptions options;
options.uuid = UUID::gen();
- auto statusWithRecordStore = _storageEngine.getCatalog()->createCollection(
+ auto swColl = _storageEngine.getCatalog()->createCollection(
opCtx.get(), _nss, options, allocateDefaultSpace);
- ASSERT_OK(statusWithRecordStore.getStatus());
+ ASSERT_OK(swColl.getStatus());
+ std::pair<RecordId, std::unique_ptr<RecordStore>> coll = std::move(swColl.getValue());
+ _catalogId = coll.first;
auto collection = std::make_unique<CollectionMock>(_nss);
CollectionCatalog::get(opCtx.get())
.registerCollection(options.uuid.get(), std::move(collection));
@@ -101,6 +103,10 @@ public:
return _storageEngine.getCatalog();
}
+ RecordId getCatalogId() {
+ return _catalogId;
+ }
+
std::string createIndex(BSONObj keyPattern,
std::string indexType = IndexNames::BTREE,
IndexBuildProtocol protocol = IndexBuildProtocol::kSinglePhase) {
@@ -116,7 +122,7 @@ public:
WriteUnitOfWork wuow(opCtx.get());
const bool isSecondaryBackgroundIndexBuild = false;
ASSERT_OK(_storageEngine.getCatalog()->prepareForIndexBuild(
- opCtx.get(), _nss, &desc, protocol, isSecondaryBackgroundIndexBuild));
+ opCtx.get(), _catalogId, &desc, protocol, isSecondaryBackgroundIndexBuild));
wuow.commit();
}
@@ -153,6 +159,7 @@ private:
const NamespaceString _nss;
StorageEngineImpl _storageEngine;
size_t numIndexesCreated = 0;
+ RecordId _catalogId;
};
TEST_F(DurableCatalogTest, MultikeyPathsForBtreeIndexInitializedToVectorOfEmptySets) {
@@ -161,7 +168,7 @@ TEST_F(DurableCatalogTest, MultikeyPathsForBtreeIndexInitializedToVectorOfEmptyS
DurableCatalog* catalog = getCatalog();
{
MultikeyPaths multikeyPaths;
- ASSERT(!catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(!catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
assertMultikeyPathsAreEqual(multikeyPaths, {std::set<size_t>{}, std::set<size_t>{}});
}
}
@@ -170,11 +177,12 @@ TEST_F(DurableCatalogTest, CanSetIndividualPathComponentOfBtreeIndexAsMultikey)
std::string indexName = createIndex(BSON("a" << 1 << "b" << 1));
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {std::set<size_t>{}, {0U}}));
+ ASSERT(catalog->setIndexIsMultikey(
+ opCtx.get(), getCatalogId(), indexName, {std::set<size_t>{}, {0U}}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
assertMultikeyPathsAreEqual(multikeyPaths, {std::set<size_t>{}, {0U}});
}
}
@@ -183,19 +191,21 @@ TEST_F(DurableCatalogTest, MultikeyPathsAccumulateOnDifferentFields) {
std::string indexName = createIndex(BSON("a" << 1 << "b" << 1));
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {std::set<size_t>{}, {0U}}));
+ ASSERT(catalog->setIndexIsMultikey(
+ opCtx.get(), getCatalogId(), indexName, {std::set<size_t>{}, {0U}}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
assertMultikeyPathsAreEqual(multikeyPaths, {std::set<size_t>{}, {0U}});
}
- ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U}, std::set<size_t>{}}));
+ ASSERT(catalog->setIndexIsMultikey(
+ opCtx.get(), getCatalogId(), indexName, {{0U}, std::set<size_t>{}}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
assertMultikeyPathsAreEqual(multikeyPaths, {{0U}, {0U}});
}
}
@@ -204,19 +214,19 @@ TEST_F(DurableCatalogTest, MultikeyPathsAccumulateOnDifferentComponentsOfTheSame
std::string indexName = createIndex(BSON("a.b" << 1));
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U}}));
+ ASSERT(catalog->setIndexIsMultikey(opCtx.get(), getCatalogId(), indexName, {{0U}}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
assertMultikeyPathsAreEqual(multikeyPaths, {{0U}});
}
- ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{1U}}));
+ ASSERT(catalog->setIndexIsMultikey(opCtx.get(), getCatalogId(), indexName, {{1U}}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
assertMultikeyPathsAreEqual(multikeyPaths, {{0U, 1U}});
}
}
@@ -225,19 +235,19 @@ TEST_F(DurableCatalogTest, NoOpWhenSpecifiedPathComponentsAlreadySetAsMultikey)
std::string indexName = createIndex(BSON("a" << 1));
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U}}));
+ ASSERT(catalog->setIndexIsMultikey(opCtx.get(), getCatalogId(), indexName, {{0U}}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
assertMultikeyPathsAreEqual(multikeyPaths, {{0U}});
}
- ASSERT(!catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U}}));
+ ASSERT(!catalog->setIndexIsMultikey(opCtx.get(), getCatalogId(), indexName, {{0U}}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
assertMultikeyPathsAreEqual(multikeyPaths, {{0U}});
}
}
@@ -246,11 +256,12 @@ TEST_F(DurableCatalogTest, CanSetMultipleFieldsAndComponentsAsMultikey) {
std::string indexName = createIndex(BSON("a.b.c" << 1 << "a.b.d" << 1));
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U, 1U}, {0U, 1U}}));
+ ASSERT(
+ catalog->setIndexIsMultikey(opCtx.get(), getCatalogId(), indexName, {{0U, 1U}, {0U, 1U}}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
assertMultikeyPathsAreEqual(multikeyPaths, {{0U, 1U}, {0U, 1U}});
}
}
@@ -261,7 +272,7 @@ DEATH_TEST_F(DurableCatalogTest,
std::string indexName = createIndex(BSON("a" << 1 << "b" << 1));
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, MultikeyPaths{});
+ catalog->setIndexIsMultikey(opCtx.get(), getCatalogId(), indexName, MultikeyPaths{});
}
DEATH_TEST_F(DurableCatalogTest,
@@ -271,7 +282,7 @@ DEATH_TEST_F(DurableCatalogTest,
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
catalog->setIndexIsMultikey(
- opCtx.get(), ns(), indexName, {std::set<size_t>{}, std::set<size_t>{}});
+ opCtx.get(), getCatalogId(), indexName, {std::set<size_t>{}, std::set<size_t>{}});
}
TEST_F(DurableCatalogTest, PathLevelMultikeyTrackingIsSupportedBy2dsphereIndexes) {
@@ -281,7 +292,7 @@ TEST_F(DurableCatalogTest, PathLevelMultikeyTrackingIsSupportedBy2dsphereIndexes
DurableCatalog* catalog = getCatalog();
{
MultikeyPaths multikeyPaths;
- ASSERT(!catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(!catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
assertMultikeyPathsAreEqual(multikeyPaths, {std::set<size_t>{}, std::set<size_t>{}});
}
}
@@ -296,7 +307,8 @@ TEST_F(DurableCatalogTest, PathLevelMultikeyTrackingIsNotSupportedByAllIndexType
DurableCatalog* catalog = getCatalog();
{
MultikeyPaths multikeyPaths;
- ASSERT(!catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(
+ !catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
ASSERT(multikeyPaths.empty());
}
}
@@ -307,11 +319,11 @@ TEST_F(DurableCatalogTest, CanSetEntireTextIndexAsMultikey) {
std::string indexName = createIndex(BSON("a" << indexType << "b" << 1), indexType);
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, MultikeyPaths{}));
+ ASSERT(catalog->setIndexIsMultikey(opCtx.get(), getCatalogId(), indexName, MultikeyPaths{}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
ASSERT(multikeyPaths.empty());
}
}
@@ -321,19 +333,19 @@ TEST_F(DurableCatalogTest, NoOpWhenEntireIndexAlreadySetAsMultikey) {
std::string indexName = createIndex(BSON("a" << indexType << "b" << 1), indexType);
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, MultikeyPaths{}));
+ ASSERT(catalog->setIndexIsMultikey(opCtx.get(), getCatalogId(), indexName, MultikeyPaths{}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
ASSERT(multikeyPaths.empty());
}
- ASSERT(!catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, MultikeyPaths{}));
+ ASSERT(!catalog->setIndexIsMultikey(opCtx.get(), getCatalogId(), indexName, MultikeyPaths{}));
{
MultikeyPaths multikeyPaths;
- ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths));
+ ASSERT(catalog->isIndexMultikey(opCtx.get(), getCatalogId(), indexName, &multikeyPaths));
ASSERT(multikeyPaths.empty());
}
}
@@ -343,23 +355,25 @@ TEST_F(DurableCatalogTest, SinglePhaseIndexBuild) {
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- ASSERT_EQ(kExpectedVersion, catalog->getIndexBuildVersion(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexReady(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isTwoPhaseIndexBuild(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexBuildScanning(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexBuildDraining(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->getSideWritesIdent(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->getConstraintViolationsIdent(opCtx.get(), ns(), indexName));
-
- catalog->indexBuildSuccess(opCtx.get(), ns(), indexName);
-
- ASSERT_EQ(kExpectedVersion, catalog->getIndexBuildVersion(opCtx.get(), ns(), indexName));
- ASSERT_TRUE(catalog->isIndexReady(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isTwoPhaseIndexBuild(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexBuildScanning(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexBuildDraining(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->getSideWritesIdent(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->getConstraintViolationsIdent(opCtx.get(), ns(), indexName));
+ ASSERT_EQ(kExpectedVersion,
+ catalog->getIndexBuildVersion(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexReady(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isTwoPhaseIndexBuild(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexBuildScanning(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexBuildDraining(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->getSideWritesIdent(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->getConstraintViolationsIdent(opCtx.get(), getCatalogId(), indexName));
+
+ catalog->indexBuildSuccess(opCtx.get(), getCatalogId(), indexName);
+
+ ASSERT_EQ(kExpectedVersion,
+ catalog->getIndexBuildVersion(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_TRUE(catalog->isIndexReady(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isTwoPhaseIndexBuild(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexBuildScanning(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexBuildDraining(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->getSideWritesIdent(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->getConstraintViolationsIdent(opCtx.get(), getCatalogId(), indexName));
}
TEST_F(DurableCatalogTest, TwoPhaseIndexBuild) {
@@ -368,46 +382,55 @@ TEST_F(DurableCatalogTest, TwoPhaseIndexBuild) {
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- ASSERT_EQ(kExpectedVersion, catalog->getIndexBuildVersion(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexReady(opCtx.get(), ns(), indexName));
- ASSERT_TRUE(catalog->isTwoPhaseIndexBuild(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexBuildScanning(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexBuildDraining(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->getSideWritesIdent(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->getConstraintViolationsIdent(opCtx.get(), ns(), indexName));
-
- catalog->setIndexBuildScanning(
- opCtx.get(), ns(), indexName, kSideWritesTableIdent, kConstraintViolationsTableIdent);
-
- ASSERT_EQ(kExpectedVersion, catalog->getIndexBuildVersion(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexReady(opCtx.get(), ns(), indexName));
- ASSERT_TRUE(catalog->isTwoPhaseIndexBuild(opCtx.get(), ns(), indexName));
- ASSERT_TRUE(catalog->isIndexBuildScanning(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexBuildDraining(opCtx.get(), ns(), indexName));
- ASSERT_EQ(kSideWritesTableIdent, catalog->getSideWritesIdent(opCtx.get(), ns(), indexName));
+ ASSERT_EQ(kExpectedVersion,
+ catalog->getIndexBuildVersion(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexReady(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_TRUE(catalog->isTwoPhaseIndexBuild(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexBuildScanning(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexBuildDraining(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->getSideWritesIdent(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->getConstraintViolationsIdent(opCtx.get(), getCatalogId(), indexName));
+
+ catalog->setIndexBuildScanning(opCtx.get(),
+ getCatalogId(),
+ indexName,
+ kSideWritesTableIdent,
+ kConstraintViolationsTableIdent);
+
+ ASSERT_EQ(kExpectedVersion,
+ catalog->getIndexBuildVersion(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexReady(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_TRUE(catalog->isTwoPhaseIndexBuild(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_TRUE(catalog->isIndexBuildScanning(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexBuildDraining(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_EQ(kSideWritesTableIdent,
+ catalog->getSideWritesIdent(opCtx.get(), getCatalogId(), indexName));
ASSERT_EQ(kConstraintViolationsTableIdent,
- catalog->getConstraintViolationsIdent(opCtx.get(), ns(), indexName));
-
- catalog->setIndexBuildDraining(opCtx.get(), ns(), indexName);
-
- ASSERT_EQ(kExpectedVersion, catalog->getIndexBuildVersion(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexReady(opCtx.get(), ns(), indexName));
- ASSERT_TRUE(catalog->isTwoPhaseIndexBuild(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexBuildScanning(opCtx.get(), ns(), indexName));
- ASSERT_TRUE(catalog->isIndexBuildDraining(opCtx.get(), ns(), indexName));
- ASSERT_EQ(kSideWritesTableIdent, catalog->getSideWritesIdent(opCtx.get(), ns(), indexName));
+ catalog->getConstraintViolationsIdent(opCtx.get(), getCatalogId(), indexName));
+
+ catalog->setIndexBuildDraining(opCtx.get(), getCatalogId(), indexName);
+
+ ASSERT_EQ(kExpectedVersion,
+ catalog->getIndexBuildVersion(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexReady(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_TRUE(catalog->isTwoPhaseIndexBuild(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexBuildScanning(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_TRUE(catalog->isIndexBuildDraining(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_EQ(kSideWritesTableIdent,
+ catalog->getSideWritesIdent(opCtx.get(), getCatalogId(), indexName));
ASSERT_EQ(kConstraintViolationsTableIdent,
- catalog->getConstraintViolationsIdent(opCtx.get(), ns(), indexName));
-
- catalog->indexBuildSuccess(opCtx.get(), ns(), indexName);
-
- ASSERT_EQ(kExpectedVersion, catalog->getIndexBuildVersion(opCtx.get(), ns(), indexName));
- ASSERT(catalog->isIndexReady(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexBuildScanning(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isIndexBuildDraining(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->isTwoPhaseIndexBuild(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->getSideWritesIdent(opCtx.get(), ns(), indexName));
- ASSERT_FALSE(catalog->getConstraintViolationsIdent(opCtx.get(), ns(), indexName));
+ catalog->getConstraintViolationsIdent(opCtx.get(), getCatalogId(), indexName));
+
+ catalog->indexBuildSuccess(opCtx.get(), getCatalogId(), indexName);
+
+ ASSERT_EQ(kExpectedVersion,
+ catalog->getIndexBuildVersion(opCtx.get(), getCatalogId(), indexName));
+ ASSERT(catalog->isIndexReady(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexBuildScanning(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isIndexBuildDraining(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->isTwoPhaseIndexBuild(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->getSideWritesIdent(opCtx.get(), getCatalogId(), indexName));
+ ASSERT_FALSE(catalog->getConstraintViolationsIdent(opCtx.get(), getCatalogId(), indexName));
}
DEATH_TEST_F(DurableCatalogTest,
@@ -417,8 +440,11 @@ DEATH_TEST_F(DurableCatalogTest,
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- catalog->setIndexBuildScanning(
- opCtx.get(), ns(), indexName, kSideWritesTableIdent, kConstraintViolationsTableIdent);
+ catalog->setIndexBuildScanning(opCtx.get(),
+ getCatalogId(),
+ indexName,
+ kSideWritesTableIdent,
+ kConstraintViolationsTableIdent);
}
DEATH_TEST_F(DurableCatalogTest,
@@ -427,7 +453,7 @@ DEATH_TEST_F(DurableCatalogTest,
std::string indexName = createIndex(BSON("a" << 1));
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- catalog->setIndexBuildDraining(opCtx.get(), ns(), indexName);
+ catalog->setIndexBuildDraining(opCtx.get(), getCatalogId(), indexName);
}
DEATH_TEST_F(DurableCatalogTest,
@@ -437,7 +463,7 @@ DEATH_TEST_F(DurableCatalogTest,
std::string indexName = createIndex(BSON("a" << indexType << "b" << 1), indexType);
auto opCtx = newOperationContext();
DurableCatalog* catalog = getCatalog();
- catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U}, {0U}});
+ catalog->setIndexIsMultikey(opCtx.get(), getCatalogId(), indexName, {{0U}, {0U}});
}
} // namespace
diff --git a/src/mongo/db/storage/kv/kv_engine_test_harness.cpp b/src/mongo/db/storage/kv/kv_engine_test_harness.cpp
index 8cdd2610162..e9c07d7fdbd 100644
--- a/src/mongo/db/storage/kv/kv_engine_test_harness.cpp
+++ b/src/mongo/db/storage/kv/kv_engine_test_harness.cpp
@@ -32,7 +32,7 @@
#include "mongo/db/catalog/collection_impl.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/operation_context_noop.h"
-#include "mongo/db/storage/durable_catalog_test_fixture.h"
+#include "mongo/db/storage/durable_catalog_impl.h"
#include "mongo/db/storage/kv/kv_engine.h"
#include "mongo/db/storage/kv/kv_prefix.h"
#include "mongo/db/storage/record_store.h"
@@ -44,6 +44,34 @@
#include "mongo/util/scopeguard.h"
namespace mongo {
+
+class DurableCatalogImplTest : public unittest::Test {
+protected:
+ RecordId newCollection(OperationContext* opCtx,
+ const NamespaceString& ns,
+ const CollectionOptions& options,
+ KVPrefix prefix,
+ DurableCatalogImpl* catalog) {
+ auto swEntry = catalog->_addEntry(opCtx, ns, options, prefix);
+ ASSERT_OK(swEntry.getStatus());
+ return swEntry.getValue().catalogId;
+ }
+
+ Status renameCollection(OperationContext* opCtx,
+ RecordId catalogId,
+ StringData toNS,
+ bool stayTemp,
+ DurableCatalogImpl* catalog) {
+ return catalog->_replaceEntry(opCtx, catalogId, NamespaceString(toNS), stayTemp);
+ }
+
+ Status dropCollection(OperationContext* opCtx,
+ RecordId catalogId,
+ DurableCatalogImpl* catalog) {
+ return catalog->_removeEntry(opCtx, catalogId);
+ }
+};
+
namespace {
std::function<std::unique_ptr<KVHarnessHelper>()> basicFactory =
@@ -161,7 +189,8 @@ TEST(KVEngineTestHarness, SimpleSorted1) {
{
MyOperationContext opCtx(engine);
WriteUnitOfWork uow(&opCtx);
- collection = std::make_unique<CollectionImpl>(&opCtx, ns, UUID::gen(), std::move(rs));
+ collection =
+ std::make_unique<CollectionImpl>(&opCtx, ns, RecordId(0), UUID::gen(), std::move(rs));
uow.commit();
}
@@ -318,19 +347,20 @@ TEST_F(DurableCatalogImplTest, Coll1) {
uow.commit();
}
+ RecordId catalogId;
{
MyOperationContext opCtx(engine);
WriteUnitOfWork uow(&opCtx);
- ASSERT_OK(newCollection(&opCtx,
- NamespaceString("a.b"),
- CollectionOptions(),
- KVPrefix::kNotPrefixed,
- catalog.get()));
- ASSERT_NOT_EQUALS("a.b", catalog->getCollectionIdent(NamespaceString("a.b")));
+ catalogId = newCollection(&opCtx,
+ NamespaceString("a.b"),
+ CollectionOptions(),
+ KVPrefix::kNotPrefixed,
+ catalog.get());
+ ASSERT_NOT_EQUALS("a.b", catalog->getEntry(catalogId).ident);
uow.commit();
}
- std::string ident = catalog->getCollectionIdent(NamespaceString("a.b"));
+ std::string ident = catalog->getEntry(catalogId).ident;
{
MyOperationContext opCtx(engine);
WriteUnitOfWork uow(&opCtx);
@@ -338,21 +368,21 @@ TEST_F(DurableCatalogImplTest, Coll1) {
catalog->init(&opCtx);
uow.commit();
}
- ASSERT_EQUALS(ident, catalog->getCollectionIdent(NamespaceString("a.b")));
+ ASSERT_EQUALS(ident, catalog->getEntry(catalogId).ident);
+ RecordId newCatalogId;
{
MyOperationContext opCtx(engine);
WriteUnitOfWork uow(&opCtx);
- dropCollection(&opCtx, "a.b", catalog.get()).transitional_ignore();
- newCollection(&opCtx,
- NamespaceString("a.b"),
- CollectionOptions(),
- KVPrefix::kNotPrefixed,
- catalog.get())
- .transitional_ignore();
+ dropCollection(&opCtx, catalogId, catalog.get()).transitional_ignore();
+ newCatalogId = newCollection(&opCtx,
+ NamespaceString("a.b"),
+ CollectionOptions(),
+ KVPrefix::kNotPrefixed,
+ catalog.get());
uow.commit();
}
- ASSERT_NOT_EQUALS(ident, catalog->getCollectionIdent(NamespaceString("a.b")));
+ ASSERT_NOT_EQUALS(ident, catalog->getEntry(newCatalogId).ident);
}
TEST_F(DurableCatalogImplTest, Idx1) {
@@ -370,16 +400,17 @@ TEST_F(DurableCatalogImplTest, Idx1) {
uow.commit();
}
+ RecordId catalogId;
{
MyOperationContext opCtx(engine);
WriteUnitOfWork uow(&opCtx);
- ASSERT_OK(newCollection(&opCtx,
- NamespaceString("a.b"),
- CollectionOptions(),
- KVPrefix::kNotPrefixed,
- catalog.get()));
- ASSERT_NOT_EQUALS("a.b", catalog->getCollectionIdent(NamespaceString("a.b")));
- ASSERT_TRUE(catalog->isUserDataIdent(catalog->getCollectionIdent(NamespaceString("a.b"))));
+ catalogId = newCollection(&opCtx,
+ NamespaceString("a.b"),
+ CollectionOptions(),
+ KVPrefix::kNotPrefixed,
+ catalog.get());
+ ASSERT_NOT_EQUALS("a.b", catalog->getEntry(catalogId).ident);
+ ASSERT_TRUE(catalog->isUserDataIdent(catalog->getEntry(catalogId).ident));
uow.commit();
}
@@ -398,21 +429,20 @@ TEST_F(DurableCatalogImplTest, Idx1) {
imd.prefix = KVPrefix::kNotPrefixed;
imd.isBackgroundSecondaryBuild = false;
md.indexes.push_back(imd);
- catalog->putMetaData(&opCtx, NamespaceString("a.b"), md);
+ catalog->putMetaData(&opCtx, catalogId, md);
uow.commit();
}
std::string idxIndent;
{
MyOperationContext opCtx(engine);
- idxIndent = catalog->getIndexIdent(&opCtx, NamespaceString("a.b"), "foo");
+ idxIndent = catalog->getIndexIdent(&opCtx, catalogId, "foo");
}
{
MyOperationContext opCtx(engine);
- ASSERT_EQUALS(idxIndent, catalog->getIndexIdent(&opCtx, NamespaceString("a.b"), "foo"));
- ASSERT_TRUE(catalog->isUserDataIdent(
- catalog->getIndexIdent(&opCtx, NamespaceString("a.b"), "foo")));
+ ASSERT_EQUALS(idxIndent, catalog->getIndexIdent(&opCtx, catalogId, "foo"));
+ ASSERT_TRUE(catalog->isUserDataIdent(catalog->getIndexIdent(&opCtx, catalogId, "foo")));
}
{
@@ -421,7 +451,7 @@ TEST_F(DurableCatalogImplTest, Idx1) {
BSONCollectionCatalogEntry::MetaData md;
md.ns = "a.b";
- catalog->putMetaData(&opCtx, NamespaceString("a.b"), md); // remove index
+ catalog->putMetaData(&opCtx, catalogId, md); // remove index
BSONCollectionCatalogEntry::IndexMetaData imd;
imd.spec = BSON("name"
@@ -431,13 +461,13 @@ TEST_F(DurableCatalogImplTest, Idx1) {
imd.prefix = KVPrefix::kNotPrefixed;
imd.isBackgroundSecondaryBuild = false;
md.indexes.push_back(imd);
- catalog->putMetaData(&opCtx, NamespaceString("a.b"), md);
+ catalog->putMetaData(&opCtx, catalogId, md);
uow.commit();
}
{
MyOperationContext opCtx(engine);
- ASSERT_NOT_EQUALS(idxIndent, catalog->getIndexIdent(&opCtx, NamespaceString("a.b"), "foo"));
+ ASSERT_NOT_EQUALS(idxIndent, catalog->getIndexIdent(&opCtx, catalogId, "foo"));
}
}
@@ -456,16 +486,17 @@ TEST_F(DurableCatalogImplTest, DirectoryPerDb1) {
uow.commit();
}
+ RecordId catalogId;
{ // collection
MyOperationContext opCtx(engine);
WriteUnitOfWork uow(&opCtx);
- ASSERT_OK(newCollection(&opCtx,
- NamespaceString("a.b"),
- CollectionOptions(),
- KVPrefix::kNotPrefixed,
- catalog.get()));
- ASSERT_STRING_CONTAINS(catalog->getCollectionIdent(NamespaceString("a.b")), "a/");
- ASSERT_TRUE(catalog->isUserDataIdent(catalog->getCollectionIdent(NamespaceString("a.b"))));
+ catalogId = newCollection(&opCtx,
+ NamespaceString("a.b"),
+ CollectionOptions(),
+ KVPrefix::kNotPrefixed,
+ catalog.get());
+ ASSERT_STRING_CONTAINS(catalog->getEntry(catalogId).ident, "a/");
+ ASSERT_TRUE(catalog->isUserDataIdent(catalog->getEntry(catalogId).ident));
uow.commit();
}
@@ -484,10 +515,9 @@ TEST_F(DurableCatalogImplTest, DirectoryPerDb1) {
imd.prefix = KVPrefix::kNotPrefixed;
imd.isBackgroundSecondaryBuild = false;
md.indexes.push_back(imd);
- catalog->putMetaData(&opCtx, NamespaceString("a.b"), md);
- ASSERT_STRING_CONTAINS(catalog->getIndexIdent(&opCtx, NamespaceString("a.b"), "foo"), "a/");
- ASSERT_TRUE(catalog->isUserDataIdent(
- catalog->getIndexIdent(&opCtx, NamespaceString("a.b"), "foo")));
+ catalog->putMetaData(&opCtx, catalogId, md);
+ ASSERT_STRING_CONTAINS(catalog->getIndexIdent(&opCtx, catalogId, "foo"), "a/");
+ ASSERT_TRUE(catalog->isUserDataIdent(catalog->getIndexIdent(&opCtx, catalogId, "foo")));
uow.commit();
}
}
@@ -507,16 +537,17 @@ TEST_F(DurableCatalogImplTest, Split1) {
uow.commit();
}
+ RecordId catalogId;
{
MyOperationContext opCtx(engine);
WriteUnitOfWork uow(&opCtx);
- ASSERT_OK(newCollection(&opCtx,
- NamespaceString("a.b"),
- CollectionOptions(),
- KVPrefix::kNotPrefixed,
- catalog.get()));
- ASSERT_STRING_CONTAINS(catalog->getCollectionIdent(NamespaceString("a.b")), "collection/");
- ASSERT_TRUE(catalog->isUserDataIdent(catalog->getCollectionIdent(NamespaceString("a.b"))));
+ catalogId = newCollection(&opCtx,
+ NamespaceString("a.b"),
+ CollectionOptions(),
+ KVPrefix::kNotPrefixed,
+ catalog.get());
+ ASSERT_STRING_CONTAINS(catalog->getEntry(catalogId).ident, "collection/");
+ ASSERT_TRUE(catalog->isUserDataIdent(catalog->getEntry(catalogId).ident));
uow.commit();
}
@@ -535,11 +566,9 @@ TEST_F(DurableCatalogImplTest, Split1) {
imd.prefix = KVPrefix::kNotPrefixed;
imd.isBackgroundSecondaryBuild = false;
md.indexes.push_back(imd);
- catalog->putMetaData(&opCtx, NamespaceString("a.b"), md);
- ASSERT_STRING_CONTAINS(catalog->getIndexIdent(&opCtx, NamespaceString("a.b"), "foo"),
- "index/");
- ASSERT_TRUE(catalog->isUserDataIdent(
- catalog->getIndexIdent(&opCtx, NamespaceString("a.b"), "foo")));
+ catalog->putMetaData(&opCtx, catalogId, md);
+ ASSERT_STRING_CONTAINS(catalog->getIndexIdent(&opCtx, catalogId, "foo"), "index/");
+ ASSERT_TRUE(catalog->isUserDataIdent(catalog->getIndexIdent(&opCtx, catalogId, "foo")));
uow.commit();
}
}
@@ -559,17 +588,17 @@ TEST_F(DurableCatalogImplTest, DirectoryPerAndSplit1) {
uow.commit();
}
+ RecordId catalogId;
{
MyOperationContext opCtx(engine);
WriteUnitOfWork uow(&opCtx);
- ASSERT_OK(newCollection(&opCtx,
- NamespaceString("a.b"),
- CollectionOptions(),
- KVPrefix::kNotPrefixed,
- catalog.get()));
- ASSERT_STRING_CONTAINS(catalog->getCollectionIdent(NamespaceString("a.b")),
- "a/collection/");
- ASSERT_TRUE(catalog->isUserDataIdent(catalog->getCollectionIdent(NamespaceString("a.b"))));
+ catalogId = newCollection(&opCtx,
+ NamespaceString("a.b"),
+ CollectionOptions(),
+ KVPrefix::kNotPrefixed,
+ catalog.get());
+ ASSERT_STRING_CONTAINS(catalog->getEntry(catalogId).ident, "a/collection/");
+ ASSERT_TRUE(catalog->isUserDataIdent(catalog->getEntry(catalogId).ident));
uow.commit();
}
@@ -588,85 +617,13 @@ TEST_F(DurableCatalogImplTest, DirectoryPerAndSplit1) {
imd.prefix = KVPrefix::kNotPrefixed;
imd.isBackgroundSecondaryBuild = false;
md.indexes.push_back(imd);
- catalog->putMetaData(&opCtx, NamespaceString("a.b"), md);
- ASSERT_STRING_CONTAINS(catalog->getIndexIdent(&opCtx, NamespaceString("a.b"), "foo"),
- "a/index/");
- ASSERT_TRUE(catalog->isUserDataIdent(
- catalog->getIndexIdent(&opCtx, NamespaceString("a.b"), "foo")));
+ catalog->putMetaData(&opCtx, catalogId, md);
+ ASSERT_STRING_CONTAINS(catalog->getIndexIdent(&opCtx, catalogId, "foo"), "a/index/");
+ ASSERT_TRUE(catalog->isUserDataIdent(catalog->getIndexIdent(&opCtx, catalogId, "foo")));
uow.commit();
}
}
-TEST_F(DurableCatalogImplTest, RestartForPrefixes) {
- storageGlobalParams.groupCollections = true;
- ON_BLOCK_EXIT([&] { storageGlobalParams.groupCollections = false; });
-
- KVPrefix abCollPrefix = KVPrefix::getNextPrefix(NamespaceString("a.b"));
- KVPrefix fooIndexPrefix = KVPrefix::getNextPrefix(NamespaceString("a.b"));
-
- std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
- KVEngine* engine = helper->getEngine();
- {
- std::unique_ptr<RecordStore> rs;
- std::unique_ptr<DurableCatalogImpl> catalog;
- {
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- ASSERT_OK(engine->createRecordStore(&opCtx, "catalog", "catalog", CollectionOptions()));
- rs = engine->getRecordStore(&opCtx, "catalog", "catalog", CollectionOptions());
- catalog = std::make_unique<DurableCatalogImpl>(rs.get(), false, false, nullptr);
- uow.commit();
- }
-
- {
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- ASSERT_OK(newCollection(
- &opCtx, NamespaceString("a.b"), CollectionOptions(), abCollPrefix, catalog.get()));
- ASSERT_NOT_EQUALS("a.b", catalog->getCollectionIdent(NamespaceString("a.b")));
- ASSERT_TRUE(
- catalog->isUserDataIdent(catalog->getCollectionIdent(NamespaceString("a.b"))));
- uow.commit();
- }
-
- {
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
-
- BSONCollectionCatalogEntry::MetaData md;
- md.ns = "a.b";
-
- BSONCollectionCatalogEntry::IndexMetaData imd;
- imd.spec = BSON("name"
- << "foo");
- imd.ready = false;
- imd.multikey = false;
- imd.prefix = fooIndexPrefix;
- imd.isBackgroundSecondaryBuild = false;
- md.indexes.push_back(imd);
- md.prefix = abCollPrefix;
- catalog->putMetaData(&opCtx, NamespaceString("a.b"), md);
- uow.commit();
- }
- }
-
- engine = helper->restartEngine();
- {
- MyOperationContext opCtx(engine);
- WriteUnitOfWork uow(&opCtx);
- std::unique_ptr<RecordStore> rs =
- engine->getRecordStore(&opCtx, "catalog", "catalog", CollectionOptions());
- auto catalog = std::make_unique<DurableCatalogImpl>(rs.get(), false, false, nullptr);
- catalog->init(&opCtx);
-
- const BSONCollectionCatalogEntry::MetaData md =
- catalog->getMetaData(&opCtx, NamespaceString("a.b"));
- ASSERT_EQ("a.b", md.ns);
- ASSERT_EQ(abCollPrefix, md.prefix);
- ASSERT_EQ(fooIndexPrefix, md.indexes[md.findIndexOffset("foo")].prefix);
- }
-}
-
TEST_F(DurableCatalogImplTest, BackupImplemented) {
std::unique_ptr<KVHarnessHelper> helper(KVHarnessHelper::create());
KVEngine* engine = helper->getEngine();
@@ -701,7 +658,8 @@ DEATH_TEST_F(DurableCatalogImplTest, TerminateOnNonNumericIndexVersion, "Fatal A
{
MyOperationContext opCtx(engine);
WriteUnitOfWork uow(&opCtx);
- collection = std::make_unique<CollectionImpl>(&opCtx, ns, UUID::gen(), std::move(rs));
+ collection =
+ std::make_unique<CollectionImpl>(&opCtx, ns, RecordId(0), UUID::gen(), std::move(rs));
uow.commit();
}
diff --git a/src/mongo/db/storage/kv/storage_engine_test.cpp b/src/mongo/db/storage/kv/storage_engine_test.cpp
index cf3f7d10b70..93423116d78 100644
--- a/src/mongo/db/storage/kv/storage_engine_test.cpp
+++ b/src/mongo/db/storage/kv/storage_engine_test.cpp
@@ -62,8 +62,8 @@ TEST_F(StorageEngineTest, ReconcileIdentsTest) {
// Add a collection, `db.coll1` to both the DurableCatalog and KVEngine. The returned value is
// the `ident` name given to the collection.
- auto swIdentName = createCollection(opCtx.get(), NamespaceString("db.coll1"));
- ASSERT_OK(swIdentName);
+ auto swCollInfo = createCollection(opCtx.get(), NamespaceString("db.coll1"));
+ ASSERT_OK(swCollInfo.getStatus());
// Create a table in the KVEngine not reflected in the DurableCatalog. This should be dropped
// when reconciling.
ASSERT_OK(createCollTable(opCtx.get(), NamespaceString("db.coll2")));
@@ -72,7 +72,7 @@ TEST_F(StorageEngineTest, ReconcileIdentsTest) {
auto idents = std::set<std::string>(identsVec.begin(), identsVec.end());
// There are two idents. `_mdb_catalog` and the ident for `db.coll1`.
ASSERT_EQUALS(static_cast<const unsigned long>(2), idents.size());
- ASSERT_TRUE(idents.find(swIdentName.getValue()) != idents.end());
+ ASSERT_TRUE(idents.find(swCollInfo.getValue().ident) != idents.end());
ASSERT_TRUE(idents.find("_mdb_catalog") != idents.end());
// Create a catalog entry for the `_id` index. Drop the created the table.
@@ -83,12 +83,12 @@ TEST_F(StorageEngineTest, ReconcileIdentsTest) {
auto reconcileStatus = reconcile(opCtx.get());
ASSERT_OK(reconcileStatus.getStatus());
ASSERT_EQUALS(static_cast<const unsigned long>(1), reconcileStatus.getValue().size());
- StorageEngine::CollectionIndexNamePair& toRebuild = reconcileStatus.getValue()[0];
- ASSERT_EQUALS("db.coll1", toRebuild.first);
- ASSERT_EQUALS("_id", toRebuild.second);
+ StorageEngine::IndexIdentifier& toRebuild = reconcileStatus.getValue()[0];
+ ASSERT_EQUALS("db.coll1", toRebuild.nss.ns());
+ ASSERT_EQUALS("_id", toRebuild.indexName);
// Now drop the `db.coll1` table, while leaving the DurableCatalog entry.
- ASSERT_OK(dropIdent(opCtx.get(), swIdentName.getValue()));
+ ASSERT_OK(dropIdent(opCtx.get(), swCollInfo.getValue().ident));
ASSERT_EQUALS(static_cast<const unsigned long>(1), getAllKVEngineIdents(opCtx.get()).size());
// Reconciling this should result in an error.
@@ -101,10 +101,10 @@ TEST_F(StorageEngineTest, LoadCatalogDropsOrphansAfterUncleanShutdown) {
auto opCtx = cc().makeOperationContext();
const NamespaceString collNs("db.coll1");
- auto swIdentName = createCollection(opCtx.get(), collNs);
- ASSERT_OK(swIdentName);
+ auto swCollInfo = createCollection(opCtx.get(), collNs);
+ ASSERT_OK(swCollInfo.getStatus());
- ASSERT_OK(dropIdent(opCtx.get(), swIdentName.getValue()));
+ ASSERT_OK(dropIdent(opCtx.get(), swCollInfo.getValue().ident));
ASSERT(collectionExists(opCtx.get(), collNs));
// After the catalog is reloaded, we expect that the collection has been dropped because the
@@ -116,7 +116,7 @@ TEST_F(StorageEngineTest, LoadCatalogDropsOrphansAfterUncleanShutdown) {
_storageEngine->loadCatalog(opCtx.get());
}
- ASSERT(!identExists(opCtx.get(), swIdentName.getValue()));
+ ASSERT(!identExists(opCtx.get(), swCollInfo.getValue().ident));
ASSERT(!collectionExists(opCtx.get(), collNs));
}
@@ -167,8 +167,8 @@ TEST_F(StorageEngineTest, ReconcileDoesNotDropIndexBuildTempTables) {
const NamespaceString ns("db.coll1");
const std::string indexName("a_1");
- auto swIdentName = createCollection(opCtx.get(), ns);
- ASSERT_OK(swIdentName);
+ auto swCollInfo = createCollection(opCtx.get(), ns);
+ ASSERT_OK(swCollInfo.getStatus());
const bool isBackgroundSecondaryBuild = false;
ASSERT_OK(startIndexBuild(opCtx.get(), ns, indexName, isBackgroundSecondaryBuild));
@@ -176,7 +176,8 @@ TEST_F(StorageEngineTest, ReconcileDoesNotDropIndexBuildTempTables) {
auto sideWrites = makeTemporary(opCtx.get());
auto constraintViolations = makeTemporary(opCtx.get());
- const auto indexIdent = _storageEngine->getCatalog()->getIndexIdent(opCtx.get(), ns, indexName);
+ const auto indexIdent = _storageEngine->getCatalog()->getIndexIdent(
+ opCtx.get(), swCollInfo.getValue().catalogId, indexName);
indexBuildScan(opCtx.get(),
ns,
@@ -208,8 +209,8 @@ TEST_F(StorageEngineTest, ReconcileDoesNotDropIndexBuildTempTablesBackgroundSeco
const NamespaceString ns("db.coll1");
const std::string indexName("a_1");
- auto swIdentName = createCollection(opCtx.get(), ns);
- ASSERT_OK(swIdentName);
+ auto swCollInfo = createCollection(opCtx.get(), ns);
+ ASSERT_OK(swCollInfo.getStatus());
const bool isBackgroundSecondaryBuild = true;
ASSERT_OK(startIndexBuild(opCtx.get(), ns, indexName, isBackgroundSecondaryBuild));
@@ -217,7 +218,8 @@ TEST_F(StorageEngineTest, ReconcileDoesNotDropIndexBuildTempTablesBackgroundSeco
auto sideWrites = makeTemporary(opCtx.get());
auto constraintViolations = makeTemporary(opCtx.get());
- const auto indexIdent = _storageEngine->getCatalog()->getIndexIdent(opCtx.get(), ns, indexName);
+ const auto indexIdent = _storageEngine->getCatalog()->getIndexIdent(
+ opCtx.get(), swCollInfo.getValue().catalogId, indexName);
indexBuildScan(opCtx.get(),
ns,
@@ -233,9 +235,9 @@ TEST_F(StorageEngineTest, ReconcileDoesNotDropIndexBuildTempTablesBackgroundSeco
// Because this backgroundSecondary index is unfinished, reconcile will identify that it should
// be rebuilt.
ASSERT_EQUALS(1UL, reconcileStatus.getValue().size());
- StorageEngine::CollectionIndexNamePair& toRebuild = reconcileStatus.getValue()[0];
- ASSERT_EQUALS(ns.toString(), toRebuild.first);
- ASSERT_EQUALS(indexName, toRebuild.second);
+ StorageEngine::IndexIdentifier& toRebuild = reconcileStatus.getValue()[0];
+ ASSERT_EQUALS(ns, toRebuild.nss);
+ ASSERT_EQUALS(indexName, toRebuild.indexName);
// Because these temporary idents were associated with an in-progress index build, they are not
// dropped.
@@ -250,10 +252,10 @@ TEST_F(StorageEngineRepairTest, LoadCatalogRecoversOrphans) {
auto opCtx = cc().makeOperationContext();
const NamespaceString collNs("db.coll1");
- auto swIdentName = createCollection(opCtx.get(), collNs);
- ASSERT_OK(swIdentName);
+ auto swCollInfo = createCollection(opCtx.get(), collNs);
+ ASSERT_OK(swCollInfo.getStatus());
- ASSERT_OK(dropIdent(opCtx.get(), swIdentName.getValue()));
+ ASSERT_OK(dropIdent(opCtx.get(), swCollInfo.getValue().ident));
ASSERT(collectionExists(opCtx.get(), collNs));
// After the catalog is reloaded, we expect that the ident has been recovered because the
@@ -264,7 +266,7 @@ TEST_F(StorageEngineRepairTest, LoadCatalogRecoversOrphans) {
_storageEngine->loadCatalog(opCtx.get());
}
- ASSERT(identExists(opCtx.get(), swIdentName.getValue()));
+ ASSERT(identExists(opCtx.get(), swCollInfo.getValue().ident));
ASSERT(collectionExists(opCtx.get(), collNs));
StorageRepairObserver::get(getGlobalServiceContext())->onRepairDone(opCtx.get());
ASSERT_EQ(1U, StorageRepairObserver::get(getGlobalServiceContext())->getModifications().size());
@@ -274,17 +276,17 @@ TEST_F(StorageEngineRepairTest, ReconcileSucceeds) {
auto opCtx = cc().makeOperationContext();
const NamespaceString collNs("db.coll1");
- auto swIdentName = createCollection(opCtx.get(), collNs);
- ASSERT_OK(swIdentName);
+ auto swCollInfo = createCollection(opCtx.get(), collNs);
+ ASSERT_OK(swCollInfo.getStatus());
- ASSERT_OK(dropIdent(opCtx.get(), swIdentName.getValue()));
+ ASSERT_OK(dropIdent(opCtx.get(), swCollInfo.getValue().ident));
ASSERT(collectionExists(opCtx.get(), collNs));
// Reconcile would normally return an error if a collection existed with a missing ident in the
// storage engine. When in a repair context, that should not be the case.
ASSERT_OK(reconcile(opCtx.get()).getStatus());
- ASSERT(!identExists(opCtx.get(), swIdentName.getValue()));
+ ASSERT(!identExists(opCtx.get(), swCollInfo.getValue().ident));
ASSERT(collectionExists(opCtx.get(), collNs));
StorageRepairObserver::get(getGlobalServiceContext())->onRepairDone(opCtx.get());
ASSERT_EQ(0U, StorageRepairObserver::get(getGlobalServiceContext())->getModifications().size());
@@ -294,8 +296,8 @@ TEST_F(StorageEngineRepairTest, LoadCatalogRecoversOrphansInCatalog) {
auto opCtx = cc().makeOperationContext();
const NamespaceString collNs("db.coll1");
- auto swIdentName = createCollection(opCtx.get(), collNs);
- ASSERT_OK(swIdentName);
+ auto swCollInfo = createCollection(opCtx.get(), collNs);
+ ASSERT_OK(swCollInfo.getStatus());
ASSERT(collectionExists(opCtx.get(), collNs));
AutoGetDb db(opCtx.get(), collNs.db(), LockMode::MODE_X);
@@ -307,11 +309,11 @@ TEST_F(StorageEngineRepairTest, LoadCatalogRecoversOrphansInCatalog) {
// When in a repair context, loadCatalog() recreates catalog entries for orphaned idents.
_storageEngine->loadCatalog(opCtx.get());
- auto identNs = swIdentName.getValue();
+ auto identNs = swCollInfo.getValue().ident;
std::replace(identNs.begin(), identNs.end(), '-', '_');
NamespaceString orphanNs = NamespaceString("local.orphan." + identNs);
- ASSERT(identExists(opCtx.get(), swIdentName.getValue()));
+ ASSERT(identExists(opCtx.get(), swCollInfo.getValue().ident));
ASSERT(collectionExists(opCtx.get(), orphanNs));
StorageRepairObserver::get(getGlobalServiceContext())->onRepairDone(opCtx.get());
@@ -322,8 +324,8 @@ TEST_F(StorageEngineTest, LoadCatalogDropsOrphans) {
auto opCtx = cc().makeOperationContext();
const NamespaceString collNs("db.coll1");
- auto swIdentName = createCollection(opCtx.get(), collNs);
- ASSERT_OK(swIdentName);
+ auto swCollInfo = createCollection(opCtx.get(), collNs);
+ ASSERT_OK(swCollInfo.getStatus());
ASSERT(collectionExists(opCtx.get(), collNs));
AutoGetDb db(opCtx.get(), collNs.db(), LockMode::MODE_X);
@@ -339,8 +341,8 @@ TEST_F(StorageEngineTest, LoadCatalogDropsOrphans) {
// reconcileCatalogAndIdents() drops orphaned idents.
ASSERT_OK(reconcile(opCtx.get()).getStatus());
- ASSERT(!identExists(opCtx.get(), swIdentName.getValue()));
- auto identNs = swIdentName.getValue();
+ ASSERT(!identExists(opCtx.get(), swCollInfo.getValue().ident));
+ auto identNs = swCollInfo.getValue().ident;
std::replace(identNs.begin(), identNs.end(), '-', '_');
NamespaceString orphanNs = NamespaceString("local.orphan." + identNs);
ASSERT(!collectionExists(opCtx.get(), orphanNs));
diff --git a/src/mongo/db/storage/storage_engine.h b/src/mongo/db/storage/storage_engine.h
index 28b9aeb5f59..6b156ce3de6 100644
--- a/src/mongo/db/storage/storage_engine.h
+++ b/src/mongo/db/storage/storage_engine.h
@@ -313,7 +313,9 @@ public:
* Generally, this method should not be called directly except by the repairDatabase()
* free function.
*/
- virtual Status repairRecordStore(OperationContext* opCtx, const NamespaceString& nss) = 0;
+ virtual Status repairRecordStore(OperationContext* opCtx,
+ RecordId catalogId,
+ const NamespaceString& nss) = 0;
/**
* Creates a temporary RecordStore on the storage engine. This record store will drop itself
@@ -488,14 +490,17 @@ public:
*/
virtual void triggerJournalFlush() const = 0;
- // (CollectionName, IndexName)
- typedef std::pair<std::string, std::string> CollectionIndexNamePair;
+ struct IndexIdentifier {
+ const RecordId catalogId;
+ const NamespaceString nss;
+ const std::string indexName;
+ };
/**
* Drop abandoned idents. In the successful case, returns a list of collection, index name
* pairs to rebuild.
*/
- virtual StatusWith<std::vector<CollectionIndexNamePair>> reconcileCatalogAndIdents(
+ virtual StatusWith<std::vector<IndexIdentifier>> reconcileCatalogAndIdents(
OperationContext* opCtx) = 0;
/**
diff --git a/src/mongo/db/storage/storage_engine_impl.cpp b/src/mongo/db/storage/storage_engine_impl.cpp
index 1ab796a55ea..f7b203741a6 100644
--- a/src/mongo/db/storage/storage_engine_impl.cpp
+++ b/src/mongo/db/storage/storage_engine_impl.cpp
@@ -137,8 +137,7 @@ void StorageEngineImpl::loadCatalog(OperationContext* opCtx) {
std::sort(identsKnownToStorageEngine.begin(), identsKnownToStorageEngine.end());
}
- auto collectionsKnownToCatalog = _catalog->getAllCollections();
-
+ std::vector<DurableCatalog::Entry> catalogEntries = _catalog->getAllCatalogEntries(opCtx);
if (_options.forRepair) {
// It's possible that there are collection files on disk that are unknown to the catalog. In
// a repair context, if we can't find an ident in the catalog, we generate a catalog entry
@@ -146,12 +145,10 @@ void StorageEngineImpl::loadCatalog(OperationContext* opCtx) {
// will be dropped in reconcileCatalogAndIdents().
for (const auto& ident : identsKnownToStorageEngine) {
if (_catalog->isCollectionIdent(ident)) {
- bool isOrphan = !std::any_of(collectionsKnownToCatalog.begin(),
- collectionsKnownToCatalog.end(),
- [this, &ident](const auto& coll) {
- return _catalog->getCollectionIdent(
- NamespaceString(coll)) == ident;
- });
+ bool isOrphan = !std::any_of(
+ catalogEntries.begin(),
+ catalogEntries.end(),
+ [this, &ident](DurableCatalog::Entry entry) { return entry.ident == ident; });
if (isOrphan) {
// If the catalog does not have information about this
// collection, we create an new entry for it.
@@ -185,15 +182,13 @@ void StorageEngineImpl::loadCatalog(OperationContext* opCtx) {
}
KVPrefix maxSeenPrefix = KVPrefix::kNotPrefixed;
- for (const auto& nss : collectionsKnownToCatalog) {
- std::string dbName = nss.db().toString();
-
+ for (DurableCatalog::Entry entry : catalogEntries) {
if (loadingFromUncleanShutdownOrRepair) {
// If we are loading the catalog after an unclean shutdown or during repair, it's
// possible that there are collections in the catalog that are unknown to the storage
// engine. If we can't find a table in the list of storage engine idents, either
// attempt to recover the ident or drop it.
- const auto collectionIdent = _catalog->getCollectionIdent(nss);
+ const auto collectionIdent = entry.ident;
bool orphan = !std::binary_search(identsKnownToStorageEngine.begin(),
identsKnownToStorageEngine.end(),
collectionIdent);
@@ -201,17 +196,18 @@ void StorageEngineImpl::loadCatalog(OperationContext* opCtx) {
// store, drop it from the catalog and skip initializing it by continuing past the
// following logic.
if (orphan) {
- auto status = _recoverOrphanedCollection(opCtx, nss, collectionIdent);
+ auto status =
+ _recoverOrphanedCollection(opCtx, entry.catalogId, entry.nss, collectionIdent);
if (!status.isOK()) {
- warning() << "Failed to recover orphaned data file for collection '" << nss
- << "': " << status;
+ warning() << "Failed to recover orphaned data file for collection '"
+ << entry.nss << "': " << status;
WriteUnitOfWork wuow(opCtx);
- fassert(50716, _catalog->_removeEntry(opCtx, nss));
+ fassert(50716, _catalog->_removeEntry(opCtx, entry.catalogId));
if (_options.forRepair) {
StorageRepairObserver::get(getGlobalServiceContext())
->invalidatingModification(str::stream()
- << "Collection " << nss
+ << "Collection " << entry.nss
<< " dropped: " << status.reason());
}
wuow.commit();
@@ -220,12 +216,12 @@ void StorageEngineImpl::loadCatalog(OperationContext* opCtx) {
}
}
- _initCollection(opCtx, nss, _options.forRepair);
- auto maxPrefixForCollection = _catalog->getMetaData(opCtx, nss).getMaxPrefix();
+ _initCollection(opCtx, entry.catalogId, entry.nss, _options.forRepair);
+ auto maxPrefixForCollection = _catalog->getMetaData(opCtx, entry.catalogId).getMaxPrefix();
maxSeenPrefix = std::max(maxSeenPrefix, maxPrefixForCollection);
- if (nss.isOrphanCollection()) {
- log() << "Orphaned collection found: " << nss;
+ if (entry.nss.isOrphanCollection()) {
+ log() << "Orphaned collection found: " << entry.nss;
}
}
@@ -238,14 +234,15 @@ void StorageEngineImpl::loadCatalog(OperationContext* opCtx) {
}
void StorageEngineImpl::_initCollection(OperationContext* opCtx,
+ RecordId catalogId,
const NamespaceString& nss,
bool forRepair) {
- BSONCollectionCatalogEntry::MetaData md = _catalog->getMetaData(opCtx, nss);
+ BSONCollectionCatalogEntry::MetaData md = _catalog->getMetaData(opCtx, catalogId);
uassert(ErrorCodes::MustDowngrade,
str::stream() << "Collection does not have UUID in KVCatalog. Collection: " << nss,
md.options.uuid);
- auto ident = _catalog->getCollectionIdent(nss);
+ auto ident = _catalog->getEntry(catalogId).ident;
std::unique_ptr<RecordStore> rs;
if (forRepair) {
@@ -257,10 +254,10 @@ void StorageEngineImpl::_initCollection(OperationContext* opCtx,
invariant(rs);
}
- auto uuid = _catalog->getCollectionOptions(opCtx, nss).uuid.get();
+ auto uuid = _catalog->getCollectionOptions(opCtx, catalogId).uuid.get();
auto collectionFactory = Collection::Factory::get(getGlobalServiceContext());
- auto collection = collectionFactory->make(opCtx, nss, uuid, std::move(rs));
+ auto collection = collectionFactory->make(opCtx, nss, catalogId, uuid, std::move(rs));
auto& collectionCatalog = CollectionCatalog::get(getGlobalServiceContext());
collectionCatalog.registerCollection(uuid, std::move(collection));
@@ -279,6 +276,7 @@ void StorageEngineImpl::closeCatalog(OperationContext* opCtx) {
}
Status StorageEngineImpl::_recoverOrphanedCollection(OperationContext* opCtx,
+ RecordId catalogId,
const NamespaceString& collectionName,
StringData collectionIdent) {
if (!_options.forRepair) {
@@ -289,11 +287,10 @@ Status StorageEngineImpl::_recoverOrphanedCollection(OperationContext* opCtx,
<< collectionIdent;
WriteUnitOfWork wuow(opCtx);
- const auto metadata = _catalog->getMetaData(opCtx, collectionName);
- auto status =
+ const auto metadata = _catalog->getMetaData(opCtx, catalogId);
+ Status status =
_engine->recoverOrphanedIdent(opCtx, collectionName, collectionIdent, metadata.options);
-
bool dataModified = status.code() == ErrorCodes::DataModifiedByRepair;
if (!status.isOK() && !dataModified) {
return status;
@@ -320,7 +317,7 @@ Status StorageEngineImpl::_recoverOrphanedCollection(OperationContext* opCtx,
* Third, a DurableCatalog may have an index ident that the KVEngine does not. This method will
* rebuild the index.
*/
-StatusWith<std::vector<StorageEngine::CollectionIndexNamePair>>
+StatusWith<std::vector<StorageEngine::IndexIdentifier>>
StorageEngineImpl::reconcileCatalogAndIdents(OperationContext* opCtx) {
// Gather all tables known to the storage engine and drop those that aren't cross-referenced
// in the _mdb_catalog. This can happen for two reasons.
@@ -392,14 +389,13 @@ StorageEngineImpl::reconcileCatalogAndIdents(OperationContext* opCtx) {
// engine. An omission here is fatal. A missing ident could mean a collection drop was rolled
// back. Note that startup already attempts to open tables; this should only catch errors in
// other contexts such as `recoverToStableTimestamp`.
- auto collections = _catalog->getAllCollections();
+ std::vector<DurableCatalog::Entry> catalogEntries = _catalog->getAllCatalogEntries(opCtx);
if (!_options.forRepair) {
- for (const auto& coll : collections) {
- const auto& identForColl = _catalog->getCollectionIdent(coll);
- if (engineIdents.find(identForColl) == engineIdents.end()) {
+ for (DurableCatalog::Entry entry : catalogEntries) {
+ if (engineIdents.find(entry.ident) == engineIdents.end()) {
return {ErrorCodes::UnrecoverableRollbackError,
- str::stream() << "Expected collection does not exist. Collection: " << coll
- << " Ident: " << identForColl};
+ str::stream() << "Expected collection does not exist. Collection: "
+ << entry.nss << " Ident: " << entry.ident};
}
}
}
@@ -409,15 +405,17 @@ StorageEngineImpl::reconcileCatalogAndIdents(OperationContext* opCtx) {
//
// Also, remove unfinished builds except those that were background index builds started on a
// secondary.
- std::vector<CollectionIndexNamePair> ret;
- for (const auto& coll : collections) {
- BSONCollectionCatalogEntry::MetaData metaData = _catalog->getMetaData(opCtx, coll);
+ std::vector<StorageEngine::IndexIdentifier> ret;
+ for (DurableCatalog::Entry entry : catalogEntries) {
+ BSONCollectionCatalogEntry::MetaData metaData =
+ _catalog->getMetaData(opCtx, entry.catalogId);
+ NamespaceString coll(metaData.ns);
// Batch up the indexes to remove them from `metaData` outside of the iterator.
std::vector<std::string> indexesToDrop;
for (const auto& indexMetaData : metaData.indexes) {
const std::string& indexName = indexMetaData.name();
- std::string indexIdent = _catalog->getIndexIdent(opCtx, coll, indexName);
+ std::string indexIdent = _catalog->getIndexIdent(opCtx, entry.catalogId, indexName);
// Warn in case of incorrect "multikeyPath" information in catalog documents. This is
// the result of a concurrency bug which has since been fixed, but may persist in
@@ -442,7 +440,7 @@ StorageEngineImpl::reconcileCatalogAndIdents(OperationContext* opCtx) {
if (indexMetaData.ready && !foundIdent) {
log() << "Expected index data is missing, rebuilding. Collection: " << coll
<< " Index: " << indexName;
- ret.emplace_back(coll.ns(), indexName);
+ ret.push_back({entry.catalogId, coll, indexName});
continue;
}
@@ -488,7 +486,7 @@ StorageEngineImpl::reconcileCatalogAndIdents(OperationContext* opCtx) {
log() << "Expected background index build did not complete, rebuilding. "
"Collection: "
<< coll << " Index: " << indexName;
- ret.emplace_back(coll.ns(), indexName);
+ ret.push_back({entry.catalogId, coll, indexName});
continue;
}
@@ -515,7 +513,7 @@ StorageEngineImpl::reconcileCatalogAndIdents(OperationContext* opCtx) {
}
if (indexesToDrop.size() > 0) {
WriteUnitOfWork wuow(opCtx);
- _catalog->putMetaData(opCtx, coll, metaData);
+ _catalog->putMetaData(opCtx, entry.catalogId, metaData);
wuow.commit();
}
}
@@ -629,17 +627,17 @@ Status StorageEngineImpl::_dropCollectionsNoTimestamp(OperationContext* opCtx,
WriteUnitOfWork untimestampedDropWuow(opCtx);
for (auto& nss : toDrop) {
invariant(getCatalog());
- auto uuid = CollectionCatalog::get(opCtx).lookupUUIDByNSS(nss).get();
- Status result = getCatalog()->dropCollection(opCtx, nss);
+ auto coll = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(nss);
+ Status result = getCatalog()->dropCollection(opCtx, coll->getCatalogId());
if (!result.isOK() && firstError.isOK()) {
firstError = result;
}
- auto removedColl = CollectionCatalog::get(opCtx).deregisterCollection(uuid);
+ auto removedColl = CollectionCatalog::get(opCtx).deregisterCollection(coll->uuid());
opCtx->recoveryUnit()->registerChange(
CollectionCatalog::get(opCtx).makeFinishDropCollectionChange(std::move(removedColl),
- uuid));
+ coll->uuid()));
}
untimestampedDropWuow.commit();
@@ -697,11 +695,13 @@ SnapshotManager* StorageEngineImpl::getSnapshotManager() const {
return _engine->getSnapshotManager();
}
-Status StorageEngineImpl::repairRecordStore(OperationContext* opCtx, const NamespaceString& nss) {
+Status StorageEngineImpl::repairRecordStore(OperationContext* opCtx,
+ RecordId catalogId,
+ const NamespaceString& nss) {
auto repairObserver = StorageRepairObserver::get(getGlobalServiceContext());
invariant(repairObserver->isIncomplete());
- Status status = _engine->repairIdent(opCtx, _catalog->getCollectionIdent(nss));
+ Status status = _engine->repairIdent(opCtx, _catalog->getEntry(catalogId).ident);
bool dataModified = status.code() == ErrorCodes::DataModifiedByRepair;
if (!status.isOK() && !dataModified) {
return status;
@@ -716,7 +716,7 @@ Status StorageEngineImpl::repairRecordStore(OperationContext* opCtx, const Names
auto& collectionCatalog = CollectionCatalog::get(getGlobalServiceContext());
auto uuid = collectionCatalog.lookupUUIDByNSS(nss).get();
collectionCatalog.deregisterCollection(uuid);
- _initCollection(opCtx, nss, false);
+ _initCollection(opCtx, catalogId, nss, false);
return Status::OK();
}
@@ -1012,10 +1012,11 @@ int64_t StorageEngineImpl::sizeOnDiskForDb(OperationContext* opCtx, StringData d
size += collection->getRecordStore()->storageSize(opCtx);
std::vector<std::string> indexNames;
- _catalog->getAllIndexes(opCtx, collection->ns(), &indexNames);
+ _catalog->getAllIndexes(opCtx, collection->getCatalogId(), &indexNames);
for (size_t i = 0; i < indexNames.size(); i++) {
- std::string ident = _catalog->getIndexIdent(opCtx, collection->ns(), indexNames[i]);
+ std::string ident =
+ _catalog->getIndexIdent(opCtx, collection->getCatalogId(), indexNames[i]);
size += _engine->getIdentSize(opCtx, ident);
}
diff --git a/src/mongo/db/storage/storage_engine_impl.h b/src/mongo/db/storage/storage_engine_impl.h
index 461534cc28d..3dda7d220f6 100644
--- a/src/mongo/db/storage/storage_engine_impl.h
+++ b/src/mongo/db/storage/storage_engine_impl.h
@@ -111,7 +111,9 @@ public:
virtual bool isEphemeral() const override;
- virtual Status repairRecordStore(OperationContext* opCtx, const NamespaceString& nss) override;
+ virtual Status repairRecordStore(OperationContext* opCtx,
+ RecordId catalogId,
+ const NamespaceString& nss) override;
virtual std::unique_ptr<TemporaryRecordStore> makeTemporaryRecordStore(
OperationContext* opCtx) override;
@@ -343,9 +345,9 @@ public:
}
/**
- * Drop abandoned idents. Returns a parallel list of index name, index spec pairs to rebuild.
+ * Drop abandoned idents. Returns a list of indexes to rebuild.
*/
- StatusWith<std::vector<StorageEngine::CollectionIndexNamePair>> reconcileCatalogAndIdents(
+ StatusWith<std::vector<StorageEngine::IndexIdentifier>> reconcileCatalogAndIdents(
OperationContext* opCtx) override;
std::string getFilesystemPathForDb(const std::string& dbName) const override;
@@ -376,7 +378,10 @@ public:
private:
using CollIter = std::list<std::string>::iterator;
- void _initCollection(OperationContext* opCtx, const NamespaceString& nss, bool forRepair);
+ void _initCollection(OperationContext* opCtx,
+ RecordId catalogId,
+ const NamespaceString& nss,
+ bool forRepair);
Status _dropCollectionsNoTimestamp(OperationContext* opCtx,
std::vector<NamespaceString>& toDrop);
@@ -392,6 +397,7 @@ private:
* collection.
*/
Status _recoverOrphanedCollection(OperationContext* opCtx,
+ RecordId catalogId,
const NamespaceString& collectionName,
StringData collectionIdent);
diff --git a/src/mongo/db/storage/storage_engine_test_fixture.h b/src/mongo/db/storage/storage_engine_test_fixture.h
index 42afa6a0646..de657637577 100644
--- a/src/mongo/db/storage/storage_engine_test_fixture.h
+++ b/src/mongo/db/storage/storage_engine_test_fixture.h
@@ -48,19 +48,19 @@ public:
StorageEngineTest() : StorageEngineTest(RepairAction::kNoRepair) {}
- /**
- * Create a collection in the catalog and in the KVEngine. Return the storage engine's `ident`.
- */
- StatusWith<std::string> createCollection(OperationContext* opCtx, NamespaceString ns) {
+ StatusWith<DurableCatalog::Entry> createCollection(OperationContext* opCtx,
+ NamespaceString ns) {
AutoGetDb db(opCtx, ns.db(), LockMode::MODE_X);
CollectionOptions options;
options.uuid = UUID::gen();
- auto rs = unittest::assertGet(
+ RecordId catalogId;
+ std::unique_ptr<RecordStore> rs;
+ std::tie(catalogId, rs) = unittest::assertGet(
_storageEngine->getCatalog()->createCollection(opCtx, ns, options, true));
- CollectionCatalog::get(opCtx).registerCollection(options.uuid.get(),
- std::make_unique<CollectionMock>(ns));
+ CollectionCatalog::get(opCtx).registerCollection(
+ options.uuid.get(), std::make_unique<CollectionMock>(ns, catalogId));
- return _storageEngine->getCatalog()->getCollectionIdent(ns);
+ return {{_storageEngine->getCatalog()->getEntry(catalogId)}};
}
std::unique_ptr<TemporaryRecordStore> makeTemporary(OperationContext* opCtx) {
@@ -77,7 +77,10 @@ public:
}
Status dropIndexTable(OperationContext* opCtx, NamespaceString nss, std::string indexName) {
- std::string indexIdent = _storageEngine->getCatalog()->getIndexIdent(opCtx, nss, indexName);
+ RecordId catalogId =
+ CollectionCatalog::get(opCtx).lookupCollectionByNamespace(nss)->getCatalogId();
+ std::string indexIdent =
+ _storageEngine->getCatalog()->getIndexIdent(opCtx, catalogId, indexName);
return dropIdent(opCtx, indexIdent);
}
@@ -85,8 +88,7 @@ public:
return _storageEngine->getEngine()->dropIdent(opCtx, ident);
}
- StatusWith<std::vector<StorageEngine::CollectionIndexNamePair>> reconcile(
- OperationContext* opCtx) {
+ StatusWith<std::vector<StorageEngine::IndexIdentifier>> reconcile(OperationContext* opCtx) {
return _storageEngine->reconcileCatalogAndIdents(opCtx);
}
@@ -95,9 +97,13 @@ public:
}
bool collectionExists(OperationContext* opCtx, const NamespaceString& nss) {
- auto allCollections = _storageEngine->getCatalog()->getAllCollections();
- return std::count(allCollections.begin(), allCollections.end(), nss);
+ std::vector<DurableCatalog::Entry> allCollections =
+ _storageEngine->getCatalog()->getAllCatalogEntries(opCtx);
+ return std::count_if(allCollections.begin(), allCollections.end(), [&](auto& entry) {
+ return nss == entry.nss;
+ });
}
+
bool identExists(OperationContext* opCtx, const std::string& ident) {
auto idents = getAllKVEngineIdents(opCtx);
return std::find(idents.begin(), idents.end(), ident) != idents.end();
@@ -130,13 +136,16 @@ public:
}
BSONObj spec = builder.append("name", key).append("v", 2).done();
- auto collection = std::make_unique<CollectionMock>(collNs);
- auto descriptor = std::make_unique<IndexDescriptor>(
- collection.get(), IndexNames::findPluginName(spec), spec);
+ Collection* collection = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(collNs);
+ auto descriptor =
+ std::make_unique<IndexDescriptor>(collection, IndexNames::findPluginName(spec), spec);
const auto protocol = IndexBuildProtocol::kTwoPhase;
- auto ret = DurableCatalog::get(opCtx)->prepareForIndexBuild(
- opCtx, collNs, descriptor.get(), protocol, isBackgroundSecondaryBuild);
+ auto ret = DurableCatalog::get(opCtx)->prepareForIndexBuild(opCtx,
+ collection->getCatalogId(),
+ descriptor.get(),
+ protocol,
+ isBackgroundSecondaryBuild);
return ret;
}
@@ -145,20 +154,26 @@ public:
std::string key,
std::string sideWritesIdent,
std::string constraintViolationsIdent) {
+ Collection* collection = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(collNs);
DurableCatalog::get(opCtx)->setIndexBuildScanning(
- opCtx, collNs, key, sideWritesIdent, constraintViolationsIdent);
+ opCtx, collection->getCatalogId(), key, sideWritesIdent, constraintViolationsIdent);
}
void indexBuildDrain(OperationContext* opCtx, NamespaceString collNs, std::string key) {
- DurableCatalog::get(opCtx)->setIndexBuildDraining(opCtx, collNs, key);
+ Collection* collection = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(collNs);
+ DurableCatalog::get(opCtx)->setIndexBuildDraining(opCtx, collection->getCatalogId(), key);
}
void indexBuildSuccess(OperationContext* opCtx, NamespaceString collNs, std::string key) {
- DurableCatalog::get(opCtx)->indexBuildSuccess(opCtx, collNs, key);
+ Collection* collection = CollectionCatalog::get(opCtx).lookupCollectionByNamespace(collNs);
+ DurableCatalog::get(opCtx)->indexBuildSuccess(opCtx, collection->getCatalogId(), key);
}
- Status removeEntry(OperationContext* opCtx, StringData ns, DurableCatalog* catalog) {
- return dynamic_cast<DurableCatalogImpl*>(catalog)->_removeEntry(opCtx, NamespaceString(ns));
+ Status removeEntry(OperationContext* opCtx, StringData collNs, DurableCatalog* catalog) {
+ Collection* collection =
+ CollectionCatalog::get(opCtx).lookupCollectionByNamespace(NamespaceString(collNs));
+ return dynamic_cast<DurableCatalogImpl*>(catalog)->_removeEntry(opCtx,
+ collection->getCatalogId());
}
StorageEngine* _storageEngine;
diff --git a/src/mongo/db/ttl.cpp b/src/mongo/db/ttl.cpp
index 398ad6b1c8c..0e514afb651 100644
--- a/src/mongo/db/ttl.cpp
+++ b/src/mongo/db/ttl.cpp
@@ -157,19 +157,21 @@ private:
if (!coll || coll->uuid() != uuid)
continue;
- if (!DurableCatalog::get(opCtxPtr.get())->isIndexPresent(&opCtx, *nss, indexName)) {
+ if (!DurableCatalog::get(opCtxPtr.get())
+ ->isIndexPresent(&opCtx, coll->getCatalogId(), indexName)) {
ttlCollectionCache.deregisterTTLInfo(ttlInfo);
continue;
}
- BSONObj spec =
- DurableCatalog::get(opCtxPtr.get())->getIndexSpec(&opCtx, *nss, indexName);
+ BSONObj spec = DurableCatalog::get(opCtxPtr.get())
+ ->getIndexSpec(&opCtx, coll->getCatalogId(), indexName);
if (!spec.hasField(secondsExpireField)) {
ttlCollectionCache.deregisterTTLInfo(ttlInfo);
continue;
}
- if (!DurableCatalog::get(opCtxPtr.get())->isIndexReady(&opCtx, *nss, indexName))
+ if (!DurableCatalog::get(opCtxPtr.get())
+ ->isIndexReady(&opCtx, coll->getCatalogId(), indexName))
continue;
ttlIndexes.push_back(std::make_pair(*nss, spec.getOwned()));