diff options
author | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2019-06-14 22:27:55 -0400 |
---|---|---|
committer | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2019-06-28 11:22:17 -0400 |
commit | 121f870957007a37896470b216ab3a2c365005a1 (patch) | |
tree | a7d30a30f8248f3ddcd1cf98d23f91f98cf730aa /src/mongo/db/storage/kv | |
parent | 175a88d703b549de2de7216c025ed9251df25b5b (diff) | |
download | mongo-121f870957007a37896470b216ab3a2c365005a1.tar.gz |
SERVER-41819 Move methods from KVCollectionCatalogEntry to KVCatalog
(cherry picked from commit 77ccfbefcd740051597d1cb4eb36d25776926f72)
Diffstat (limited to 'src/mongo/db/storage/kv')
-rw-r--r-- | src/mongo/db/storage/kv/SConscript | 9 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/kv_catalog.cpp | 473 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/kv_catalog.h | 121 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/kv_collection_catalog_entry.cpp | 341 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/kv_collection_catalog_entry.h | 69 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/kv_collection_catalog_entry_test.cpp | 234 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/kv_drop_pending_ident_reaper_test.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/kv_engine.h | 4 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/kv_engine_test_harness.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/storage_engine_impl.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/storage_engine_impl.h | 7 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/storage_engine_interface.h | 4 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/storage_engine_test.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/storage_engine_test_fixture.h | 27 |
14 files changed, 731 insertions, 592 deletions
diff --git a/src/mongo/db/storage/kv/SConscript b/src/mongo/db/storage/kv/SConscript index 69bba58c8fc..799904611c0 100644 --- a/src/mongo/db/storage/kv/SConscript +++ b/src/mongo/db/storage/kv/SConscript @@ -18,7 +18,7 @@ env.Library( source=[ 'kv_catalog.cpp', 'kv_collection_catalog_entry.cpp', - ], + ], LIBDEPS=[ '$BUILD_DIR/mongo/bson/util/bson_extract', '$BUILD_DIR/mongo/db/concurrency/lock_manager', @@ -29,8 +29,11 @@ env.Library( '$BUILD_DIR/mongo/db/catalog/collection_catalog', 'kv_drop_pending_ident_reaper', 'kv_prefix', - ], - ) + ], + LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/db/catalog/disable_index_spec_namespace_generation', + ], +) # Should not be referenced outside this SConscript file. env.Library( diff --git a/src/mongo/db/storage/kv/kv_catalog.cpp b/src/mongo/db/storage/kv/kv_catalog.cpp index d0dad7d8657..262a65eaedc 100644 --- a/src/mongo/db/storage/kv/kv_catalog.cpp +++ b/src/mongo/db/storage/kv/kv_catalog.cpp @@ -35,7 +35,9 @@ #include "mongo/bson/util/bson_extract.h" #include "mongo/bson/util/builder.h" +#include "mongo/db/catalog/disable_index_spec_namespace_generation_gen.h" #include "mongo/db/concurrency/d_concurrency.h" +#include "mongo/db/index/index_descriptor.h" #include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" #include "mongo/db/storage/kv/kv_catalog_feature_tracker.h" @@ -132,6 +134,10 @@ std::string escapeDbName(StringData dbname) { return escaped; } +bool indexTypeSupportsPathLevelMultikeyTracking(StringData accessMethod) { + return accessMethod == IndexNames::BTREE || accessMethod == IndexNames::GEO_2DSPHERE; +} + } // namespace using std::unique_ptr; @@ -168,6 +174,61 @@ public: const Entry _entry; }; +class KVCatalog::AddIndexChange : public RecoveryUnit::Change { +public: + AddIndexChange(OperationContext* opCtx, StorageEngineInterface* engine, StringData ident) + : _opCtx(opCtx), _engine(engine), _ident(ident.toString()) {} + + virtual void commit(boost::optional<Timestamp>) {} + virtual void rollback() { + // Intentionally ignoring failure. + auto kvEngine = _engine->getEngine(); + MONGO_COMPILER_VARIABLE_UNUSED auto status = kvEngine->dropIdent(_opCtx, _ident); + } + + OperationContext* const _opCtx; + StorageEngineInterface* _engine; + const std::string _ident; +}; + +class KVCatalog::RemoveIndexChange : public RecoveryUnit::Change { +public: + RemoveIndexChange(OperationContext* opCtx, + StorageEngineInterface* engine, + OptionalCollectionUUID uuid, + const NamespaceString& indexNss, + StringData indexName, + StringData ident) + : _opCtx(opCtx), + _engine(engine), + _uuid(uuid), + _indexNss(indexNss), + _indexName(indexName), + _ident(ident.toString()) {} + + virtual void rollback() {} + virtual void commit(boost::optional<Timestamp> commitTimestamp) { + // Intentionally ignoring failure here. Since we've removed the metadata pointing to the + // index, we should never see it again anyway. + if (_engine->getStorageEngine()->supportsPendingDrops() && commitTimestamp) { + log() << "Deferring table drop for index '" << _indexName << "' on collection '" + << _indexNss << (_uuid ? " (" + _uuid->toString() + ")'" : "") << ". Ident: '" + << _ident << "', commit timestamp: '" << commitTimestamp << "'"; + _engine->addDropPendingIdent(*commitTimestamp, _indexNss, _ident); + } else { + auto kvEngine = _engine->getEngine(); + MONGO_COMPILER_VARIABLE_UNUSED auto status = kvEngine->dropIdent(_opCtx, _ident); + } + } + + OperationContext* const _opCtx; + StorageEngineInterface* _engine; + OptionalCollectionUUID _uuid; + const NamespaceString _indexNss; + const std::string _indexName; + const std::string _ident; +}; + bool KVCatalog::FeatureTracker::isFeatureDocument(BSONObj obj) { BSONElement firstElem = obj.firstElement(); if (firstElem.fieldNameStringData() == kIsFeatureDocumentFieldName) { @@ -726,8 +787,7 @@ std::unique_ptr<CollectionCatalogEntry> KVCatalog::makeCollectionCatalogEntry( invariant(rs); } - return std::make_unique<KVCollectionCatalogEntry>( - _engine, this, nss.ns(), ident, std::move(rs)); + return std::make_unique<KVCollectionCatalogEntry>(_engine, nss.ns(), ident, std::move(rs)); } StatusWith<std::unique_ptr<CollectionCatalogEntry>> KVCatalog::createCollection( @@ -774,8 +834,7 @@ StatusWith<std::unique_ptr<CollectionCatalogEntry>> KVCatalog::createCollection( auto rs = _engine->getEngine()->getGroupedRecordStore(opCtx, nss.ns(), ident, options, prefix); invariant(rs); - return std::make_unique<KVCollectionCatalogEntry>( - _engine, this, nss.ns(), ident, std::move(rs)); + return std::make_unique<KVCollectionCatalogEntry>(_engine, nss.ns(), ident, std::move(rs)); } Status KVCatalog::renameCollection(OperationContext* opCtx, @@ -814,17 +873,17 @@ Status KVCatalog::dropCollection(OperationContext* opCtx, const NamespaceString& auto& catalog = CollectionCatalog::get(opCtx); auto uuid = catalog.lookupUUIDByNSS(nss); - invariant(entry->getTotalIndexCount(opCtx) == entry->getCompletedIndexCount(opCtx)); + invariant(getTotalIndexCount(opCtx, nss) == getCompletedIndexCount(opCtx, nss)); { std::vector<std::string> indexNames; - entry->getAllIndexes(opCtx, &indexNames); + getAllIndexes(opCtx, nss, &indexNames); for (size_t i = 0; i < indexNames.size(); i++) { - entry->removeIndex(opCtx, indexNames[i]).transitional_ignore(); + Status status = removeIndex(opCtx, nss, indexNames[i]); } } - invariant(entry->getTotalIndexCount(opCtx) == 0); + invariant(getTotalIndexCount(opCtx, nss) == 0); const std::string ident = getCollectionIdent(nss); @@ -854,4 +913,402 @@ Status KVCatalog::dropCollection(OperationContext* opCtx, const NamespaceString& return Status::OK(); } + +void KVCatalog::updateCappedSize(OperationContext* opCtx, NamespaceString ns, long long size) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + md.options.cappedSize = size; + putMetaData(opCtx, ns, md); +} + +void KVCatalog::updateTTLSetting(OperationContext* opCtx, + NamespaceString ns, + StringData idxName, + long long newExpireSeconds) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(idxName); + invariant(offset >= 0); + md.indexes[offset].updateTTLSetting(newExpireSeconds); + putMetaData(opCtx, ns, md); +} + +bool KVCatalog::isEqualToMetadataUUID(OperationContext* opCtx, + NamespaceString ns, + OptionalCollectionUUID uuid) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + return md.options.uuid && md.options.uuid == uuid; +} + +void KVCatalog::setIsTemp(OperationContext* opCtx, NamespaceString ns, bool isTemp) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + md.options.temp = isTemp; + putMetaData(opCtx, ns, md); +} + +boost::optional<std::string> KVCatalog::getSideWritesIdent(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + return md.indexes[offset].sideWritesIdent; +} + +void KVCatalog::setIndexKeyStringWithLongTypeBitsExistsOnDisk(OperationContext* opCtx) { + const auto feature = FeatureTracker::RepairableFeature::kIndexKeyStringWithLongTypeBits; + if (!getFeatureTracker()->isRepairableFeatureInUse(opCtx, feature)) { + getFeatureTracker()->markRepairableFeatureAsInUse(opCtx, feature); + } +} + +void KVCatalog::updateValidator(OperationContext* opCtx, + NamespaceString ns, + const BSONObj& validator, + StringData validationLevel, + StringData validationAction) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + md.options.validator = validator; + md.options.validationLevel = validationLevel.toString(); + md.options.validationAction = validationAction.toString(); + putMetaData(opCtx, ns, md); +} + +void KVCatalog::updateIndexMetadata(OperationContext* opCtx, + NamespaceString ns, + const IndexDescriptor* desc) { + // Update any metadata Ident has for this index + const string ident = getIndexIdent(opCtx, ns, desc->indexName()); + auto kvEngine = _engine->getEngine(); + kvEngine->alterIdentMetadata(opCtx, ident, desc); +} + +Status KVCatalog::removeIndex(OperationContext* opCtx, NamespaceString ns, StringData indexName) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + if (md.findIndexOffset(indexName) < 0) + return Status::OK(); // never had the index so nothing to do. + + const string ident = getIndexIdent(opCtx, ns, indexName); + + md.eraseIndex(indexName); + putMetaData(opCtx, ns, md); + + // Lazily remove to isolate underlying engine from rollback. + opCtx->recoveryUnit()->registerChange(new RemoveIndexChange( + opCtx, _engine, md.options.uuid, ns.makeIndexNamespace(indexName), indexName, ident)); + return Status::OK(); +} + +Status KVCatalog::prepareForIndexBuild(OperationContext* opCtx, + NamespaceString ns, + const IndexDescriptor* spec, + IndexBuildProtocol indexBuildProtocol, + bool isBackgroundSecondaryBuild) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + KVPrefix prefix = KVPrefix::getNextPrefix(ns); + BSONCollectionCatalogEntry::IndexMetaData imd; + imd.spec = spec->infoObj(); + imd.ready = false; + imd.multikey = false; + imd.prefix = prefix; + imd.isBackgroundSecondaryBuild = isBackgroundSecondaryBuild; + imd.runTwoPhaseBuild = indexBuildProtocol == IndexBuildProtocol::kTwoPhase; + + if (indexTypeSupportsPathLevelMultikeyTracking(spec->getAccessMethodName())) { + const auto feature = FeatureTracker::RepairableFeature::kPathLevelMultikeyTracking; + if (!getFeatureTracker()->isRepairableFeatureInUse(opCtx, feature)) { + getFeatureTracker()->markRepairableFeatureAsInUse(opCtx, feature); + } + imd.multikeyPaths = MultikeyPaths{static_cast<size_t>(spec->keyPattern().nFields())}; + } + + // Mark collation feature as in use if the index has a non-simple collation. + if (imd.spec["collation"]) { + const auto feature = KVCatalog::FeatureTracker::NonRepairableFeature::kCollation; + if (!getFeatureTracker()->isNonRepairableFeatureInUse(opCtx, feature)) { + getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx, feature); + } + } + + md.indexes.push_back(imd); + putMetaData(opCtx, ns, md); + + string ident = getIndexIdent(opCtx, ns, spec->indexName()); + + auto kvEngine = _engine->getEngine(); + const Status status = kvEngine->createGroupedSortedDataInterface( + opCtx, getCollectionOptions(opCtx, ns), ident, spec, prefix); + if (status.isOK()) { + opCtx->recoveryUnit()->registerChange(new AddIndexChange(opCtx, _engine, ident)); + } + + return status; +} + +bool KVCatalog::isTwoPhaseIndexBuild(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + return md.indexes[offset].runTwoPhaseBuild; +} + +void KVCatalog::setIndexBuildScanning(OperationContext* opCtx, + NamespaceString ns, + StringData indexName, + std::string sideWritesIdent, + boost::optional<std::string> constraintViolationsIdent) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + invariant(!md.indexes[offset].ready); + invariant(!md.indexes[offset].buildPhase); + invariant(md.indexes[offset].runTwoPhaseBuild); + + md.indexes[offset].buildPhase = BSONCollectionCatalogEntry::kIndexBuildScanning.toString(); + md.indexes[offset].sideWritesIdent = sideWritesIdent; + md.indexes[offset].constraintViolationsIdent = constraintViolationsIdent; + putMetaData(opCtx, ns, md); +} + +bool KVCatalog::isIndexBuildScanning(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + return md.indexes[offset].buildPhase == + BSONCollectionCatalogEntry::kIndexBuildScanning.toString(); +} + +void KVCatalog::setIndexBuildDraining(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + invariant(!md.indexes[offset].ready); + invariant(md.indexes[offset].runTwoPhaseBuild); + invariant(md.indexes[offset].buildPhase == + BSONCollectionCatalogEntry::kIndexBuildScanning.toString()); + + md.indexes[offset].buildPhase = BSONCollectionCatalogEntry::kIndexBuildDraining.toString(); + putMetaData(opCtx, ns, md); +} + +bool KVCatalog::isIndexBuildDraining(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + return md.indexes[offset].buildPhase == + BSONCollectionCatalogEntry::kIndexBuildDraining.toString(); +} + +void KVCatalog::indexBuildSuccess(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + md.indexes[offset].ready = true; + md.indexes[offset].runTwoPhaseBuild = false; + md.indexes[offset].buildPhase = boost::none; + md.indexes[offset].sideWritesIdent = boost::none; + md.indexes[offset].constraintViolationsIdent = boost::none; + putMetaData(opCtx, ns, md); +} + +bool KVCatalog::isIndexMultikey(OperationContext* opCtx, + NamespaceString ns, + StringData indexName, + MultikeyPaths* multikeyPaths) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + + if (multikeyPaths && !md.indexes[offset].multikeyPaths.empty()) { + *multikeyPaths = md.indexes[offset].multikeyPaths; + } + + return md.indexes[offset].multikey; +} + +bool KVCatalog::setIndexIsMultikey(OperationContext* opCtx, + NamespaceString ns, + StringData indexName, + const MultikeyPaths& multikeyPaths) { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + + const bool tracksPathLevelMultikeyInfo = !md.indexes[offset].multikeyPaths.empty(); + if (tracksPathLevelMultikeyInfo) { + invariant(!multikeyPaths.empty()); + invariant(multikeyPaths.size() == md.indexes[offset].multikeyPaths.size()); + } else { + invariant(multikeyPaths.empty()); + + if (md.indexes[offset].multikey) { + // The index is already set as multikey and we aren't tracking path-level multikey + // information for it. We return false to indicate that the index metadata is unchanged. + return false; + } + } + + md.indexes[offset].multikey = true; + + if (tracksPathLevelMultikeyInfo) { + bool newPathIsMultikey = false; + bool somePathIsMultikey = false; + + // Store new path components that cause this index to be multikey in catalog's index + // metadata. + for (size_t i = 0; i < multikeyPaths.size(); ++i) { + std::set<size_t>& indexMultikeyComponents = md.indexes[offset].multikeyPaths[i]; + for (const auto multikeyComponent : multikeyPaths[i]) { + auto result = indexMultikeyComponents.insert(multikeyComponent); + newPathIsMultikey = newPathIsMultikey || result.second; + somePathIsMultikey = true; + } + } + + // If all of the sets in the multikey paths vector were empty, then no component of any + // indexed field caused the index to be multikey. setIndexIsMultikey() therefore shouldn't + // have been called. + invariant(somePathIsMultikey); + + if (!newPathIsMultikey) { + // We return false to indicate that the index metadata is unchanged. + return false; + } + } + + putMetaData(opCtx, ns, md); + return true; +} + +boost::optional<std::string> KVCatalog::getConstraintViolationsIdent(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + return md.indexes[offset].constraintViolationsIdent; +} + +long KVCatalog::getIndexBuildVersion(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + return md.indexes[offset].versionOfBuild; +} + +CollectionOptions KVCatalog::getCollectionOptions(OperationContext* opCtx, + NamespaceString ns) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + return md.options; +} + +int KVCatalog::getTotalIndexCount(OperationContext* opCtx, NamespaceString ns) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + return static_cast<int>(md.indexes.size()); +} + +int KVCatalog::getCompletedIndexCount(OperationContext* opCtx, NamespaceString ns) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + int num = 0; + for (unsigned i = 0; i < md.indexes.size(); i++) { + if (md.indexes[i].ready) + num++; + } + return num; +} + +BSONObj KVCatalog::getIndexSpec(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + + BSONObj spec = md.indexes[offset].spec.getOwned(); + if (spec.hasField("ns") || disableIndexSpecNamespaceGeneration.load()) { + return spec; + } + + BSONObj nsObj = BSON("ns" << ns.ns()); + spec = spec.addField(nsObj.firstElement()); + return spec; +} + +void KVCatalog::getAllIndexes(OperationContext* opCtx, + NamespaceString ns, + std::vector<std::string>* names) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + for (unsigned i = 0; i < md.indexes.size(); i++) { + names->push_back(md.indexes[i].spec["name"].String()); + } +} + +void KVCatalog::getReadyIndexes(OperationContext* opCtx, + NamespaceString ns, + std::vector<std::string>* names) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + for (unsigned i = 0; i < md.indexes.size(); i++) { + if (md.indexes[i].ready) + names->push_back(md.indexes[i].spec["name"].String()); + } +} + +void KVCatalog::getAllUniqueIndexes(OperationContext* opCtx, + NamespaceString ns, + std::vector<std::string>* names) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + for (unsigned i = 0; i < md.indexes.size(); i++) { + if (md.indexes[i].spec["unique"]) { + std::string indexName = md.indexes[i].spec["name"].String(); + names->push_back(indexName); + } + } +} + +bool KVCatalog::isIndexPresent(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + return offset >= 0; +} + +bool KVCatalog::isIndexReady(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + return md.indexes[offset].ready; +} + +KVPrefix KVCatalog::getIndexPrefix(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const { + BSONCollectionCatalogEntry::MetaData md = getMetaData(opCtx, ns); + int offset = md.findIndexOffset(indexName); + invariant(offset >= 0); + return md.indexes[offset].prefix; +} } diff --git a/src/mongo/db/storage/kv/kv_catalog.h b/src/mongo/db/storage/kv/kv_catalog.h index 957b12c38e1..6d46dcc482b 100644 --- a/src/mongo/db/storage/kv/kv_catalog.h +++ b/src/mongo/db/storage/kv/kv_catalog.h @@ -38,6 +38,7 @@ #include "mongo/db/catalog/collection_options.h" #include "mongo/db/record_id.h" #include "mongo/db/storage/bson_collection_catalog_entry.h" +#include "mongo/db/storage/durable_catalog.h" #include "mongo/db/storage/kv/kv_prefix.h" #include "mongo/stdx/mutex.h" @@ -47,7 +48,7 @@ class OperationContext; class RecordStore; class StorageEngineInterface; -class KVCatalog { +class KVCatalog : public DurableCatalog { public: class FeatureTracker; @@ -96,19 +97,10 @@ public: return _rs; } - /** - * Create an entry in the catalog for an orphaned collection found in the - * storage engine. Return the generated ns of the collection. - * Note that this function does not recreate the _id index on the collection because it does not - * have access to index catalog. - */ StatusWith<std::string> newOrphanedIdent(OperationContext* opCtx, std::string ident); std::string getFilesystemPathForDb(const std::string& dbName) const; - /** - * Generate an internal ident name. - */ std::string newInternalIdent(); std::unique_ptr<CollectionCatalogEntry> makeCollectionCatalogEntry(OperationContext* opCtx, @@ -128,9 +120,118 @@ public: Status dropCollection(OperationContext* opCtx, const NamespaceString& nss); + void updateCappedSize(OperationContext* opCtx, NamespaceString ns, long long size); + + void updateTTLSetting(OperationContext* opCtx, + NamespaceString ns, + StringData idxName, + long long newExpireSeconds); + + bool isEqualToMetadataUUID(OperationContext* opCtx, + NamespaceString ns, + OptionalCollectionUUID uuid); + + void setIsTemp(OperationContext* opCtx, NamespaceString ns, bool isTemp); + + boost::optional<std::string> getSideWritesIdent(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const; + + // TODO SERVER-36385 Remove this function: we don't set the feature tracker bit in 4.4 because + // 4.4 can only downgrade to 4.2 which can read long TypeBits. + void setIndexKeyStringWithLongTypeBitsExistsOnDisk(OperationContext* opCtx); + + void updateValidator(OperationContext* opCtx, + NamespaceString ns, + const BSONObj& validator, + StringData validationLevel, + StringData validationAction); + + void updateIndexMetadata(OperationContext* opCtx, + NamespaceString ns, + const IndexDescriptor* desc); + + Status removeIndex(OperationContext* opCtx, NamespaceString ns, StringData indexName); + + Status prepareForIndexBuild(OperationContext* opCtx, + NamespaceString ns, + const IndexDescriptor* spec, + IndexBuildProtocol indexBuildProtocol, + bool isBackgroundSecondaryBuild); + + bool isTwoPhaseIndexBuild(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const; + + void setIndexBuildScanning(OperationContext* opCtx, + NamespaceString ns, + StringData indexName, + std::string sideWritesIdent, + boost::optional<std::string> constraintViolationsIdent); + + + bool isIndexBuildScanning(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const; + + void setIndexBuildDraining(OperationContext* opCtx, NamespaceString ns, StringData indexName); + + bool isIndexBuildDraining(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const; + + void indexBuildSuccess(OperationContext* opCtx, NamespaceString ns, StringData indexName); + + bool isIndexMultikey(OperationContext* opCtx, + NamespaceString ns, + StringData indexName, + MultikeyPaths* multikeyPaths) const; + + bool setIndexIsMultikey(OperationContext* opCtx, + NamespaceString ns, + StringData indexName, + const MultikeyPaths& multikeyPaths); + + boost::optional<std::string> getConstraintViolationsIdent(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const; + + long getIndexBuildVersion(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const; + + CollectionOptions getCollectionOptions(OperationContext* opCtx, NamespaceString ns) const; + + int getTotalIndexCount(OperationContext* opCtx, NamespaceString ns) const; + + int getCompletedIndexCount(OperationContext* opCtx, NamespaceString ns) const; + + BSONObj getIndexSpec(OperationContext* opCtx, NamespaceString ns, StringData indexName) const; + + void getAllIndexes(OperationContext* opCtx, + NamespaceString ns, + std::vector<std::string>* names) const; + + void getReadyIndexes(OperationContext* opCtx, + NamespaceString ns, + std::vector<std::string>* names) const; + void getAllUniqueIndexes(OperationContext* opCtx, + NamespaceString ns, + std::vector<std::string>* names) const; + + bool isIndexPresent(OperationContext* opCtx, NamespaceString ns, StringData indexName) const; + + bool isIndexReady(OperationContext* opCtx, NamespaceString ns, StringData indexName) const; + + KVPrefix getIndexPrefix(OperationContext* opCtx, + NamespaceString ns, + StringData indexName) const; + private: class AddIdentChange; class RemoveIdentChange; + class AddIndexChange; + class RemoveIndexChange; friend class StorageEngineImpl; friend class KVCatalogTest; diff --git a/src/mongo/db/storage/kv/kv_collection_catalog_entry.cpp b/src/mongo/db/storage/kv/kv_collection_catalog_entry.cpp index 43150b4d6b3..d971924cadd 100644 --- a/src/mongo/db/storage/kv/kv_collection_catalog_entry.cpp +++ b/src/mongo/db/storage/kv/kv_collection_catalog_entry.cpp @@ -37,7 +37,7 @@ #include "mongo/db/catalog/collection_catalog.h" #include "mongo/db/index/index_descriptor.h" -#include "mongo/db/storage/kv/kv_catalog.h" +#include "mongo/db/storage/durable_catalog.h" #include "mongo/db/storage/kv/kv_catalog_feature_tracker.h" #include "mongo/db/storage/kv/kv_engine.h" #include "mongo/db/storage/kv/storage_engine_impl.h" @@ -47,351 +47,12 @@ namespace mongo { using std::string; -namespace { - -bool indexTypeSupportsPathLevelMultikeyTracking(StringData accessMethod) { - return accessMethod == IndexNames::BTREE || accessMethod == IndexNames::GEO_2DSPHERE; -} - -} // namespace - -class KVCollectionCatalogEntry::AddIndexChange : public RecoveryUnit::Change { -public: - AddIndexChange(OperationContext* opCtx, KVCollectionCatalogEntry* cce, StringData ident) - : _opCtx(opCtx), _cce(cce), _ident(ident.toString()) {} - - virtual void commit(boost::optional<Timestamp>) {} - virtual void rollback() { - // Intentionally ignoring failure. - auto kvEngine = _cce->_engine->getEngine(); - MONGO_COMPILER_VARIABLE_UNUSED auto status = kvEngine->dropIdent(_opCtx, _ident); - } - - OperationContext* const _opCtx; - KVCollectionCatalogEntry* const _cce; - const std::string _ident; -}; - -class KVCollectionCatalogEntry::RemoveIndexChange : public RecoveryUnit::Change { -public: - RemoveIndexChange(OperationContext* opCtx, - KVCollectionCatalogEntry* cce, - OptionalCollectionUUID uuid, - const NamespaceString& indexNss, - StringData indexName, - StringData ident) - : _opCtx(opCtx), - _cce(cce), - _uuid(uuid), - _indexNss(indexNss), - _indexName(indexName), - _ident(ident.toString()) {} - - virtual void rollback() {} - virtual void commit(boost::optional<Timestamp> commitTimestamp) { - // Intentionally ignoring failure here. Since we've removed the metadata pointing to the - // index, we should never see it again anyway. - auto engine = _cce->_engine; - auto storageEngine = engine->getStorageEngine(); - if (storageEngine->supportsPendingDrops() && commitTimestamp) { - log() << "Deferring table drop for index '" << _indexName << "' on collection '" - << _indexNss << (_uuid ? " (" + _uuid->toString() + ")'" : "") << ". Ident: '" - << _ident << "', commit timestamp: '" << commitTimestamp << "'"; - engine->addDropPendingIdent(*commitTimestamp, _indexNss, _ident); - } else { - auto kvEngine = engine->getEngine(); - MONGO_COMPILER_VARIABLE_UNUSED auto status = kvEngine->dropIdent(_opCtx, _ident); - } - } - - OperationContext* const _opCtx; - KVCollectionCatalogEntry* const _cce; - OptionalCollectionUUID _uuid; - const NamespaceString _indexNss; - const std::string _indexName; - const std::string _ident; -}; - - KVCollectionCatalogEntry::KVCollectionCatalogEntry(StorageEngineInterface* engine, - KVCatalog* catalog, StringData ns, StringData ident, std::unique_ptr<RecordStore> rs) : BSONCollectionCatalogEntry(ns), _engine(engine), - _catalog(catalog), _ident(ident.toString()), _recordStore(std::move(rs)) {} - -KVCollectionCatalogEntry::~KVCollectionCatalogEntry() {} - -bool KVCollectionCatalogEntry::setIndexIsMultikey(OperationContext* opCtx, - StringData indexName, - const MultikeyPaths& multikeyPaths) { - MetaData md = _getMetaData(opCtx); - - int offset = md.findIndexOffset(indexName); - invariant(offset >= 0); - - const bool tracksPathLevelMultikeyInfo = !md.indexes[offset].multikeyPaths.empty(); - if (tracksPathLevelMultikeyInfo) { - invariant(!multikeyPaths.empty()); - invariant(multikeyPaths.size() == md.indexes[offset].multikeyPaths.size()); - } else { - invariant(multikeyPaths.empty()); - - if (md.indexes[offset].multikey) { - // The index is already set as multikey and we aren't tracking path-level multikey - // information for it. We return false to indicate that the index metadata is unchanged. - return false; - } - } - - md.indexes[offset].multikey = true; - - if (tracksPathLevelMultikeyInfo) { - bool newPathIsMultikey = false; - bool somePathIsMultikey = false; - - // Store new path components that cause this index to be multikey in catalog's index - // metadata. - for (size_t i = 0; i < multikeyPaths.size(); ++i) { - std::set<size_t>& indexMultikeyComponents = md.indexes[offset].multikeyPaths[i]; - for (const auto multikeyComponent : multikeyPaths[i]) { - auto result = indexMultikeyComponents.insert(multikeyComponent); - newPathIsMultikey = newPathIsMultikey || result.second; - somePathIsMultikey = true; - } - } - - // If all of the sets in the multikey paths vector were empty, then no component of any - // indexed field caused the index to be multikey. setIndexIsMultikey() therefore shouldn't - // have been called. - invariant(somePathIsMultikey); - - if (!newPathIsMultikey) { - // We return false to indicate that the index metadata is unchanged. - return false; - } - } - - _catalog->putMetaData(opCtx, ns(), md); - return true; -} - -void KVCollectionCatalogEntry::setIndexKeyStringWithLongTypeBitsExistsOnDisk( - OperationContext* opCtx) { - const auto feature = - KVCatalog::FeatureTracker::RepairableFeature::kIndexKeyStringWithLongTypeBits; - if (!_catalog->getFeatureTracker()->isRepairableFeatureInUse(opCtx, feature)) { - _catalog->getFeatureTracker()->markRepairableFeatureAsInUse(opCtx, feature); - } -} - -Status KVCollectionCatalogEntry::removeIndex(OperationContext* opCtx, StringData indexName) { - MetaData md = _getMetaData(opCtx); - - if (md.findIndexOffset(indexName) < 0) - return Status::OK(); // never had the index so nothing to do. - - const string ident = _catalog->getIndexIdent(opCtx, ns(), indexName); - - md.eraseIndex(indexName); - _catalog->putMetaData(opCtx, ns(), md); - - // Lazily remove to isolate underlying engine from rollback. - opCtx->recoveryUnit()->registerChange(new RemoveIndexChange( - opCtx, this, md.options.uuid, ns().makeIndexNamespace(indexName), indexName, ident)); - return Status::OK(); -} - -Status KVCollectionCatalogEntry::prepareForIndexBuild(OperationContext* opCtx, - const IndexDescriptor* spec, - IndexBuildProtocol indexBuildProtocol, - bool isBackgroundSecondaryBuild) { - MetaData md = _getMetaData(opCtx); - - KVPrefix prefix = KVPrefix::getNextPrefix(ns()); - IndexMetaData imd; - imd.spec = spec->infoObj(); - imd.ready = false; - imd.multikey = false; - imd.prefix = prefix; - imd.isBackgroundSecondaryBuild = isBackgroundSecondaryBuild; - imd.runTwoPhaseBuild = indexBuildProtocol == IndexBuildProtocol::kTwoPhase; - - if (indexTypeSupportsPathLevelMultikeyTracking(spec->getAccessMethodName())) { - const auto feature = - KVCatalog::FeatureTracker::RepairableFeature::kPathLevelMultikeyTracking; - if (!_catalog->getFeatureTracker()->isRepairableFeatureInUse(opCtx, feature)) { - _catalog->getFeatureTracker()->markRepairableFeatureAsInUse(opCtx, feature); - } - imd.multikeyPaths = MultikeyPaths{static_cast<size_t>(spec->keyPattern().nFields())}; - } - - // Mark collation feature as in use if the index has a non-simple collation. - if (imd.spec["collation"]) { - const auto feature = KVCatalog::FeatureTracker::NonRepairableFeature::kCollation; - if (!_catalog->getFeatureTracker()->isNonRepairableFeatureInUse(opCtx, feature)) { - _catalog->getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx, feature); - } - } - - md.indexes.push_back(imd); - _catalog->putMetaData(opCtx, ns(), md); - - string ident = _catalog->getIndexIdent(opCtx, ns(), spec->indexName()); - - auto kvEngine = _engine->getEngine(); - const Status status = kvEngine->createGroupedSortedDataInterface(opCtx, ident, spec, prefix); - if (status.isOK()) { - opCtx->recoveryUnit()->registerChange(new AddIndexChange(opCtx, this, ident)); - } - - return status; -} - -bool KVCollectionCatalogEntry::isTwoPhaseIndexBuild(OperationContext* opCtx, - StringData indexName) const { - MetaData md = _getMetaData(opCtx); - int offset = md.findIndexOffset(indexName); - invariant(offset >= 0); - return md.indexes[offset].runTwoPhaseBuild; -} - -long KVCollectionCatalogEntry::getIndexBuildVersion(OperationContext* opCtx, - StringData indexName) const { - MetaData md = _getMetaData(opCtx); - int offset = md.findIndexOffset(indexName); - invariant(offset >= 0); - return md.indexes[offset].versionOfBuild; -} - -void KVCollectionCatalogEntry::setIndexBuildScanning( - OperationContext* opCtx, - StringData indexName, - std::string sideWritesIdent, - boost::optional<std::string> constraintViolationsIdent) { - MetaData md = _getMetaData(opCtx); - int offset = md.findIndexOffset(indexName); - invariant(offset >= 0); - invariant(!md.indexes[offset].ready); - invariant(!md.indexes[offset].buildPhase); - invariant(md.indexes[offset].runTwoPhaseBuild); - - md.indexes[offset].buildPhase = kIndexBuildScanning.toString(); - md.indexes[offset].sideWritesIdent = sideWritesIdent; - md.indexes[offset].constraintViolationsIdent = constraintViolationsIdent; - _catalog->putMetaData(opCtx, ns(), md); -} - -bool KVCollectionCatalogEntry::isIndexBuildScanning(OperationContext* opCtx, - StringData indexName) const { - MetaData md = _getMetaData(opCtx); - int offset = md.findIndexOffset(indexName); - invariant(offset >= 0); - return md.indexes[offset].buildPhase == kIndexBuildScanning.toString(); -} - -void KVCollectionCatalogEntry::setIndexBuildDraining(OperationContext* opCtx, - StringData indexName) { - MetaData md = _getMetaData(opCtx); - int offset = md.findIndexOffset(indexName); - invariant(offset >= 0); - invariant(!md.indexes[offset].ready); - invariant(md.indexes[offset].runTwoPhaseBuild); - invariant(md.indexes[offset].buildPhase == kIndexBuildScanning.toString()); - - md.indexes[offset].buildPhase = kIndexBuildDraining.toString(); - _catalog->putMetaData(opCtx, ns(), md); -} - -bool KVCollectionCatalogEntry::isIndexBuildDraining(OperationContext* opCtx, - StringData indexName) const { - MetaData md = _getMetaData(opCtx); - int offset = md.findIndexOffset(indexName); - invariant(offset >= 0); - return md.indexes[offset].buildPhase == kIndexBuildDraining.toString(); -} - -void KVCollectionCatalogEntry::indexBuildSuccess(OperationContext* opCtx, StringData indexName) { - MetaData md = _getMetaData(opCtx); - int offset = md.findIndexOffset(indexName); - invariant(offset >= 0); - md.indexes[offset].ready = true; - md.indexes[offset].runTwoPhaseBuild = false; - md.indexes[offset].buildPhase = boost::none; - md.indexes[offset].sideWritesIdent = boost::none; - md.indexes[offset].constraintViolationsIdent = boost::none; - _catalog->putMetaData(opCtx, ns(), md); -} - -boost::optional<std::string> KVCollectionCatalogEntry::getSideWritesIdent( - OperationContext* opCtx, StringData indexName) const { - MetaData md = _getMetaData(opCtx); - int offset = md.findIndexOffset(indexName); - invariant(offset >= 0); - return md.indexes[offset].sideWritesIdent; -} - -boost::optional<std::string> KVCollectionCatalogEntry::getConstraintViolationsIdent( - OperationContext* opCtx, StringData indexName) const { - MetaData md = _getMetaData(opCtx); - int offset = md.findIndexOffset(indexName); - invariant(offset >= 0); - return md.indexes[offset].constraintViolationsIdent; -} - -void KVCollectionCatalogEntry::updateTTLSetting(OperationContext* opCtx, - StringData idxName, - long long newExpireSeconds) { - MetaData md = _getMetaData(opCtx); - int offset = md.findIndexOffset(idxName); - invariant(offset >= 0); - md.indexes[offset].updateTTLSetting(newExpireSeconds); - _catalog->putMetaData(opCtx, ns(), md); -} - -void KVCollectionCatalogEntry::updateIndexMetadata(OperationContext* opCtx, - const IndexDescriptor* desc) { - // Update any metadata Ident has for this index - const string ident = _catalog->getIndexIdent(opCtx, ns(), desc->indexName()); - auto kvEngine = _engine->getEngine(); - kvEngine->alterIdentMetadata(opCtx, ident, desc); -} - -bool KVCollectionCatalogEntry::isEqualToMetadataUUID(OperationContext* opCtx, - OptionalCollectionUUID uuid) { - MetaData md = _getMetaData(opCtx); - return md.options.uuid && md.options.uuid == uuid; -} - -void KVCollectionCatalogEntry::updateValidator(OperationContext* opCtx, - const BSONObj& validator, - StringData validationLevel, - StringData validationAction) { - MetaData md = _getMetaData(opCtx); - md.options.validator = validator; - md.options.validationLevel = validationLevel.toString(); - md.options.validationAction = validationAction.toString(); - _catalog->putMetaData(opCtx, ns(), md); -} - -void KVCollectionCatalogEntry::setIsTemp(OperationContext* opCtx, bool isTemp) { - MetaData md = _getMetaData(opCtx); - md.options.temp = isTemp; - _catalog->putMetaData(opCtx, ns(), md); -} - -void KVCollectionCatalogEntry::updateCappedSize(OperationContext* opCtx, long long size) { - MetaData md = _getMetaData(opCtx); - md.options.cappedSize = size; - _catalog->putMetaData(opCtx, ns(), md); -} - -BSONCollectionCatalogEntry::MetaData KVCollectionCatalogEntry::_getMetaData( - OperationContext* opCtx) const { - return _catalog->getMetaData(opCtx, ns()); -} } diff --git a/src/mongo/db/storage/kv/kv_collection_catalog_entry.h b/src/mongo/db/storage/kv/kv_collection_catalog_entry.h index 644a00f8943..e9133a607f5 100644 --- a/src/mongo/db/storage/kv/kv_collection_catalog_entry.h +++ b/src/mongo/db/storage/kv/kv_collection_catalog_entry.h @@ -38,76 +38,16 @@ namespace mongo { -class KVCatalog; class StorageEngineInterface; class KVCollectionCatalogEntry final : public BSONCollectionCatalogEntry { public: KVCollectionCatalogEntry(StorageEngineInterface* engine, - KVCatalog* catalog, StringData ns, StringData ident, std::unique_ptr<RecordStore> rs); - ~KVCollectionCatalogEntry() final; - - int getMaxAllowedIndexes() const final { - return 64; - }; - - bool setIndexIsMultikey(OperationContext* opCtx, - StringData indexName, - const MultikeyPaths& multikeyPaths) final; - - // TODO SERVER-36385 Remove this function: we don't set the feature tracker bit in 4.4 because - // 4.4 can only downgrade to 4.2 which can read long TypeBits. - void setIndexKeyStringWithLongTypeBitsExistsOnDisk(OperationContext* opCtx) final; - - Status removeIndex(OperationContext* opCtx, StringData indexName) final; - - Status prepareForIndexBuild(OperationContext* opCtx, - const IndexDescriptor* spec, - IndexBuildProtocol indexBuildProtocol, - bool isBackgroundSecondaryBuild) final; - - bool isTwoPhaseIndexBuild(OperationContext* opCtx, StringData indexName) const final; - - long getIndexBuildVersion(OperationContext* opCtx, StringData indexName) const final; - - void setIndexBuildScanning(OperationContext* opCtx, - StringData indexName, - std::string sideWritesIdent, - boost::optional<std::string> constraintViolationsIdent) final; - - bool isIndexBuildScanning(OperationContext* opCtx, StringData indexName) const final; - - void setIndexBuildDraining(OperationContext* opCtx, StringData indexName) final; - - bool isIndexBuildDraining(OperationContext* opCtx, StringData indexName) const final; - - void indexBuildSuccess(OperationContext* opCtx, StringData indexName) final; - - boost::optional<std::string> getSideWritesIdent(OperationContext* opCtx, - StringData indexName) const final; - - boost::optional<std::string> getConstraintViolationsIdent(OperationContext* opCtx, - StringData indexName) const final; - void updateTTLSetting(OperationContext* opCtx, - StringData idxName, - long long newExpireSeconds) final; - - void updateIndexMetadata(OperationContext* opCtx, const IndexDescriptor* desc) final; - - void updateValidator(OperationContext* opCtx, - const BSONObj& validator, - StringData validationLevel, - StringData validationAction) final; - - void setIsTemp(OperationContext* opCtx, bool isTemp); - - void updateCappedSize(OperationContext*, long long int) final; - - bool isEqualToMetadataUUID(OperationContext* opCtx, OptionalCollectionUUID uuid) final; + ~KVCollectionCatalogEntry() final {} RecordStore* getRecordStore() { return _recordStore.get(); @@ -116,15 +56,8 @@ public: return _recordStore.get(); } -protected: - MetaData _getMetaData(OperationContext* opCtx) const final; - private: - class AddIndexChange; - class RemoveIndexChange; - StorageEngineInterface* const _engine; // not owned - KVCatalog* _catalog; // not owned std::string _ident; std::unique_ptr<RecordStore> _recordStore; // owned }; diff --git a/src/mongo/db/storage/kv/kv_collection_catalog_entry_test.cpp b/src/mongo/db/storage/kv/kv_collection_catalog_entry_test.cpp index 14b70f282fc..c521b880e3e 100644 --- a/src/mongo/db/storage/kv/kv_collection_catalog_entry_test.cpp +++ b/src/mongo/db/storage/kv/kv_collection_catalog_entry_test.cpp @@ -96,9 +96,12 @@ public: } } - CollectionCatalogEntry* getCollectionCatalogEntry() { - return CollectionCatalog::get(getGlobalServiceContext()) - .lookupCollectionCatalogEntryByNamespace(_nss); + NamespaceString ns() { + return _nss; + } + + DurableCatalog* getCatalog() { + return _storageEngine.getCatalog(); } std::string createIndex(BSONObj keyPattern, @@ -116,8 +119,8 @@ public: { WriteUnitOfWork wuow(opCtx.get()); const bool isSecondaryBackgroundIndexBuild = false; - ASSERT_OK(getCollectionCatalogEntry()->prepareForIndexBuild( - opCtx.get(), &desc, protocol, isSecondaryBackgroundIndexBuild)); + ASSERT_OK(_storageEngine.getCatalog()->prepareForIndexBuild( + opCtx.get(), _nss, &desc, protocol, isSecondaryBackgroundIndexBuild)); wuow.commit(); } @@ -159,106 +162,100 @@ private: TEST_F(KVCollectionCatalogEntryTest, MultikeyPathsForBtreeIndexInitializedToVectorOfEmptySets) { std::string indexName = createIndex(BSON("a" << 1 << "b" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); + DurableCatalog* catalog = getCatalog(); { MultikeyPaths multikeyPaths; - ASSERT(!collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(!catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); assertMultikeyPathsAreEqual(multikeyPaths, {std::set<size_t>{}, std::set<size_t>{}}); } } TEST_F(KVCollectionCatalogEntryTest, CanSetIndividualPathComponentOfBtreeIndexAsMultikey) { std::string indexName = createIndex(BSON("a" << 1 << "b" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - ASSERT(collEntry->setIndexIsMultikey(opCtx.get(), indexName, {std::set<size_t>{}, {0U}})); + DurableCatalog* catalog = getCatalog(); + ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {std::set<size_t>{}, {0U}})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); assertMultikeyPathsAreEqual(multikeyPaths, {std::set<size_t>{}, {0U}}); } } TEST_F(KVCollectionCatalogEntryTest, MultikeyPathsAccumulateOnDifferentFields) { std::string indexName = createIndex(BSON("a" << 1 << "b" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - ASSERT(collEntry->setIndexIsMultikey(opCtx.get(), indexName, {std::set<size_t>{}, {0U}})); + DurableCatalog* catalog = getCatalog(); + ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {std::set<size_t>{}, {0U}})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); assertMultikeyPathsAreEqual(multikeyPaths, {std::set<size_t>{}, {0U}}); } - ASSERT(collEntry->setIndexIsMultikey(opCtx.get(), indexName, {{0U}, std::set<size_t>{}})); + ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U}, std::set<size_t>{}})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); assertMultikeyPathsAreEqual(multikeyPaths, {{0U}, {0U}}); } } TEST_F(KVCollectionCatalogEntryTest, MultikeyPathsAccumulateOnDifferentComponentsOfTheSameField) { std::string indexName = createIndex(BSON("a.b" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - ASSERT(collEntry->setIndexIsMultikey(opCtx.get(), indexName, {{0U}})); + DurableCatalog* catalog = getCatalog(); + ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U}})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); assertMultikeyPathsAreEqual(multikeyPaths, {{0U}}); } - ASSERT(collEntry->setIndexIsMultikey(opCtx.get(), indexName, {{1U}})); + ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{1U}})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); assertMultikeyPathsAreEqual(multikeyPaths, {{0U, 1U}}); } } TEST_F(KVCollectionCatalogEntryTest, NoOpWhenSpecifiedPathComponentsAlreadySetAsMultikey) { std::string indexName = createIndex(BSON("a" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - ASSERT(collEntry->setIndexIsMultikey(opCtx.get(), indexName, {{0U}})); + DurableCatalog* catalog = getCatalog(); + ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U}})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); assertMultikeyPathsAreEqual(multikeyPaths, {{0U}}); } - ASSERT(!collEntry->setIndexIsMultikey(opCtx.get(), indexName, {{0U}})); + ASSERT(!catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U}})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); assertMultikeyPathsAreEqual(multikeyPaths, {{0U}}); } } TEST_F(KVCollectionCatalogEntryTest, CanSetMultipleFieldsAndComponentsAsMultikey) { std::string indexName = createIndex(BSON("a.b.c" << 1 << "a.b.d" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - ASSERT(collEntry->setIndexIsMultikey(opCtx.get(), indexName, {{0U, 1U}, {0U, 1U}})); + DurableCatalog* catalog = getCatalog(); + ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U, 1U}, {0U, 1U}})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); assertMultikeyPathsAreEqual(multikeyPaths, {{0U, 1U}, {0U, 1U}}); } } @@ -267,31 +264,29 @@ DEATH_TEST_F(KVCollectionCatalogEntryTest, CannotOmitPathLevelMultikeyInfoWithBtreeIndex, "Invariant failure !multikeyPaths.empty()") { std::string indexName = createIndex(BSON("a" << 1 << "b" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - collEntry->setIndexIsMultikey(opCtx.get(), indexName, MultikeyPaths{}); + DurableCatalog* catalog = getCatalog(); + catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, MultikeyPaths{}); } DEATH_TEST_F(KVCollectionCatalogEntryTest, AtLeastOnePathComponentMustCauseIndexToBeMultikey, "Invariant failure somePathIsMultikey") { std::string indexName = createIndex(BSON("a" << 1 << "b" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - collEntry->setIndexIsMultikey(opCtx.get(), indexName, {std::set<size_t>{}, std::set<size_t>{}}); + DurableCatalog* catalog = getCatalog(); + catalog->setIndexIsMultikey( + opCtx.get(), ns(), indexName, {std::set<size_t>{}, std::set<size_t>{}}); } TEST_F(KVCollectionCatalogEntryTest, PathLevelMultikeyTrackingIsSupportedBy2dsphereIndexes) { std::string indexType = IndexNames::GEO_2DSPHERE; std::string indexName = createIndex(BSON("a" << indexType << "b" << 1), indexType); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); + DurableCatalog* catalog = getCatalog(); { MultikeyPaths multikeyPaths; - ASSERT(!collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(!catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); assertMultikeyPathsAreEqual(multikeyPaths, {std::set<size_t>{}, std::set<size_t>{}}); } } @@ -302,12 +297,11 @@ TEST_F(KVCollectionCatalogEntryTest, PathLevelMultikeyTrackingIsNotSupportedByAl for (auto&& indexType : indexTypes) { std::string indexName = createIndex(BSON("a" << indexType << "b" << 1), indexType); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); + DurableCatalog* catalog = getCatalog(); { MultikeyPaths multikeyPaths; - ASSERT(!collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(!catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); ASSERT(multikeyPaths.empty()); } } @@ -316,14 +310,13 @@ TEST_F(KVCollectionCatalogEntryTest, PathLevelMultikeyTrackingIsNotSupportedByAl TEST_F(KVCollectionCatalogEntryTest, CanSetEntireTextIndexAsMultikey) { std::string indexType = IndexNames::TEXT; std::string indexName = createIndex(BSON("a" << indexType << "b" << 1), indexType); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - ASSERT(collEntry->setIndexIsMultikey(opCtx.get(), indexName, MultikeyPaths{})); + DurableCatalog* catalog = getCatalog(); + ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, MultikeyPaths{})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); ASSERT(multikeyPaths.empty()); } } @@ -331,119 +324,115 @@ TEST_F(KVCollectionCatalogEntryTest, CanSetEntireTextIndexAsMultikey) { TEST_F(KVCollectionCatalogEntryTest, NoOpWhenEntireIndexAlreadySetAsMultikey) { std::string indexType = IndexNames::TEXT; std::string indexName = createIndex(BSON("a" << indexType << "b" << 1), indexType); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - ASSERT(collEntry->setIndexIsMultikey(opCtx.get(), indexName, MultikeyPaths{})); + DurableCatalog* catalog = getCatalog(); + ASSERT(catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, MultikeyPaths{})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); ASSERT(multikeyPaths.empty()); } - ASSERT(!collEntry->setIndexIsMultikey(opCtx.get(), indexName, MultikeyPaths{})); + ASSERT(!catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, MultikeyPaths{})); { MultikeyPaths multikeyPaths; - ASSERT(collEntry->isIndexMultikey(opCtx.get(), indexName, &multikeyPaths)); + ASSERT(catalog->isIndexMultikey(opCtx.get(), ns(), indexName, &multikeyPaths)); ASSERT(multikeyPaths.empty()); } } TEST_F(KVCollectionCatalogEntryTest, SinglePhaseIndexBuild) { std::string indexName = createIndex(BSON("a" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - - ASSERT_EQ(kExpectedVersion, collEntry->getIndexBuildVersion(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexReady(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isTwoPhaseIndexBuild(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexBuildScanning(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexBuildDraining(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->getSideWritesIdent(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->getConstraintViolationsIdent(opCtx.get(), indexName)); - - collEntry->indexBuildSuccess(opCtx.get(), indexName); - - ASSERT_EQ(kExpectedVersion, collEntry->getIndexBuildVersion(opCtx.get(), indexName)); - ASSERT_TRUE(collEntry->isIndexReady(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isTwoPhaseIndexBuild(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexBuildScanning(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexBuildDraining(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->getSideWritesIdent(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->getConstraintViolationsIdent(opCtx.get(), indexName)); + 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)); } TEST_F(KVCollectionCatalogEntryTest, TwoPhaseIndexBuild) { std::string indexName = createIndex(BSON("a" << 1), IndexNames::BTREE, IndexBuildProtocol::kTwoPhase); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - - ASSERT_EQ(kExpectedVersion, collEntry->getIndexBuildVersion(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexReady(opCtx.get(), indexName)); - ASSERT_TRUE(collEntry->isTwoPhaseIndexBuild(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexBuildScanning(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexBuildDraining(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->getSideWritesIdent(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->getConstraintViolationsIdent(opCtx.get(), indexName)); - - collEntry->setIndexBuildScanning( - opCtx.get(), indexName, kSideWritesTableIdent, kConstraintViolationsTableIdent); - - ASSERT_EQ(kExpectedVersion, collEntry->getIndexBuildVersion(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexReady(opCtx.get(), indexName)); - ASSERT_TRUE(collEntry->isTwoPhaseIndexBuild(opCtx.get(), indexName)); - ASSERT_TRUE(collEntry->isIndexBuildScanning(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexBuildDraining(opCtx.get(), indexName)); - ASSERT_EQ(kSideWritesTableIdent, collEntry->getSideWritesIdent(opCtx.get(), indexName)); + 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(kConstraintViolationsTableIdent, - collEntry->getConstraintViolationsIdent(opCtx.get(), indexName)); + catalog->getConstraintViolationsIdent(opCtx.get(), ns(), indexName)); - collEntry->setIndexBuildDraining(opCtx.get(), indexName); + catalog->setIndexBuildDraining(opCtx.get(), ns(), indexName); - ASSERT_EQ(kExpectedVersion, collEntry->getIndexBuildVersion(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexReady(opCtx.get(), indexName)); - ASSERT_TRUE(collEntry->isTwoPhaseIndexBuild(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexBuildScanning(opCtx.get(), indexName)); - ASSERT_TRUE(collEntry->isIndexBuildDraining(opCtx.get(), indexName)); - ASSERT_EQ(kSideWritesTableIdent, collEntry->getSideWritesIdent(opCtx.get(), 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)); ASSERT_EQ(kConstraintViolationsTableIdent, - collEntry->getConstraintViolationsIdent(opCtx.get(), indexName)); + catalog->getConstraintViolationsIdent(opCtx.get(), ns(), indexName)); - collEntry->indexBuildSuccess(opCtx.get(), indexName); + catalog->indexBuildSuccess(opCtx.get(), ns(), indexName); - ASSERT_EQ(kExpectedVersion, collEntry->getIndexBuildVersion(opCtx.get(), indexName)); - ASSERT(collEntry->isIndexReady(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexBuildScanning(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isIndexBuildDraining(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->isTwoPhaseIndexBuild(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->getSideWritesIdent(opCtx.get(), indexName)); - ASSERT_FALSE(collEntry->getConstraintViolationsIdent(opCtx.get(), 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)); } DEATH_TEST_F(KVCollectionCatalogEntryTest, SinglePhaseIllegalScanPhase, "Invariant failure md.indexes[offset].runTwoPhaseBuild") { std::string indexName = createIndex(BSON("a" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - collEntry->setIndexBuildScanning( - opCtx.get(), indexName, kSideWritesTableIdent, kConstraintViolationsTableIdent); + DurableCatalog* catalog = getCatalog(); + + catalog->setIndexBuildScanning( + opCtx.get(), ns(), indexName, kSideWritesTableIdent, kConstraintViolationsTableIdent); } DEATH_TEST_F(KVCollectionCatalogEntryTest, SinglePhaseIllegalDrainPhase, "Invariant failure md.indexes[offset].runTwoPhaseBuild") { std::string indexName = createIndex(BSON("a" << 1)); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - collEntry->setIndexBuildDraining(opCtx.get(), indexName); + DurableCatalog* catalog = getCatalog(); + catalog->setIndexBuildDraining(opCtx.get(), ns(), indexName); } DEATH_TEST_F(KVCollectionCatalogEntryTest, @@ -451,10 +440,9 @@ DEATH_TEST_F(KVCollectionCatalogEntryTest, "Invariant failure multikeyPaths.empty()") { std::string indexType = IndexNames::TEXT; std::string indexName = createIndex(BSON("a" << indexType << "b" << 1), indexType); - CollectionCatalogEntry* collEntry = getCollectionCatalogEntry(); - auto opCtx = newOperationContext(); - collEntry->setIndexIsMultikey(opCtx.get(), indexName, {{0U}, {0U}}); + DurableCatalog* catalog = getCatalog(); + catalog->setIndexIsMultikey(opCtx.get(), ns(), indexName, {{0U}, {0U}}); } } // namespace diff --git a/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper_test.cpp b/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper_test.cpp index 6cbb5572554..309d5825266 100644 --- a/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper_test.cpp +++ b/src/mongo/db/storage/kv/kv_drop_pending_ident_reaper_test.cpp @@ -88,6 +88,7 @@ public: return {}; } Status createSortedDataInterface(OperationContext* opCtx, + const CollectionOptions& collOptions, StringData ident, const IndexDescriptor* desc) override { return Status::OK(); diff --git a/src/mongo/db/storage/kv/kv_engine.h b/src/mongo/db/storage/kv/kv_engine.h index b9e65bfd24f..2c0e56a0c33 100644 --- a/src/mongo/db/storage/kv/kv_engine.h +++ b/src/mongo/db/storage/kv/kv_engine.h @@ -144,6 +144,7 @@ public: } virtual Status createSortedDataInterface(OperationContext* opCtx, + const CollectionOptions& collOptions, StringData ident, const IndexDescriptor* desc) = 0; @@ -158,11 +159,12 @@ public: * share a table. Sharing indexes belonging to different databases is forbidden. */ virtual Status createGroupedSortedDataInterface(OperationContext* opCtx, + const CollectionOptions& collOptions, StringData ident, const IndexDescriptor* desc, KVPrefix prefix) { invariant(prefix == KVPrefix::kNotPrefixed); - return createSortedDataInterface(opCtx, ident, desc); + return createSortedDataInterface(opCtx, collOptions, ident, desc); } virtual int64_t getIdentSize(OperationContext* opCtx, StringData ident) = 0; 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 72935625b70..14c91e85938 100644 --- a/src/mongo/db/storage/kv/kv_engine_test_harness.cpp +++ b/src/mongo/db/storage/kv/kv_engine_test_harness.cpp @@ -33,7 +33,6 @@ #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/kv/kv_catalog.h" #include "mongo/db/storage/kv/kv_catalog_test_fixture.h" #include "mongo/db/storage/kv/kv_engine.h" #include "mongo/db/storage/kv/kv_prefix.h" @@ -181,7 +180,7 @@ TEST(KVEngineTestHarness, SimpleSorted1) { unique_ptr<SortedDataInterface> sorted; { MyOperationContext opCtx(engine); - ASSERT_OK(engine->createSortedDataInterface(&opCtx, ident, &desc)); + ASSERT_OK(engine->createSortedDataInterface(&opCtx, CollectionOptions(), ident, &desc)); sorted.reset(engine->getSortedDataInterface(&opCtx, ident, &desc)); ASSERT(sorted); } @@ -724,7 +723,7 @@ DEATH_TEST_F(KVCatalogTest, TerminateOnNonNumericIndexVersion, "Fatal Assertion unique_ptr<SortedDataInterface> sorted; { MyOperationContext opCtx(engine); - ASSERT_OK(engine->createSortedDataInterface(&opCtx, ident, &desc)); + ASSERT_OK(engine->createSortedDataInterface(&opCtx, CollectionOptions(), ident, &desc)); sorted.reset(engine->getSortedDataInterface(&opCtx, ident, &desc)); ASSERT(sorted); } diff --git a/src/mongo/db/storage/kv/storage_engine_impl.cpp b/src/mongo/db/storage/kv/storage_engine_impl.cpp index 3aa39b1c123..cd23a9208bb 100644 --- a/src/mongo/db/storage/kv/storage_engine_impl.cpp +++ b/src/mongo/db/storage/kv/storage_engine_impl.cpp @@ -92,7 +92,7 @@ void StorageEngineImpl::loadCatalog(OperationContext* opCtx) { if (status.code() == ErrorCodes::DataModifiedByRepair) { warning() << "Catalog data modified by repair: " << status.reason(); - repairObserver->onModification(str::stream() << "KVCatalog repaired: " + repairObserver->onModification(str::stream() << "DurableCatalog repaired: " << status.reason()); } else { fassertNoTrace(50926, status); @@ -239,10 +239,10 @@ void StorageEngineImpl::_initCollection(OperationContext* opCtx, const NamespaceString& nss, bool forRepair) { auto catalogEntry = _catalog->makeCollectionCatalogEntry(opCtx, nss, forRepair); - auto uuid = catalogEntry->getCollectionOptions(opCtx).uuid.get(); + auto uuid = _catalog->getCollectionOptions(opCtx, nss).uuid.get(); auto collectionFactory = Collection::Factory::get(getGlobalServiceContext()); - auto collection = collectionFactory->make(opCtx, catalogEntry.get()); + auto collection = collectionFactory->make(opCtx, uuid, catalogEntry.get()); auto& collectionCatalog = CollectionCatalog::get(getGlobalServiceContext()); collectionCatalog.registerCollection(uuid, std::move(catalogEntry), std::move(collection)); @@ -291,15 +291,15 @@ Status StorageEngineImpl::_recoverOrphanedCollection(OperationContext* opCtx, /** * This method reconciles differences between idents the KVEngine is aware of and the - * KVCatalog. There are three differences to consider: + * DurableCatalog. There are three differences to consider: * - * First, a KVEngine may know of an ident that the KVCatalog does not. This method will drop + * First, a KVEngine may know of an ident that the DurableCatalog does not. This method will drop * the ident from the KVEngine. * - * Second, a KVCatalog may have a collection ident that the KVEngine does not. This is an + * Second, a DurableCatalog may have a collection ident that the KVEngine does not. This is an * illegal state and this method fasserts. * - * Third, a KVCatalog may have an index ident that the KVEngine does not. This method will + * Third, a DurableCatalog may have an index ident that the KVEngine does not. This method will * rebuild the index. */ StatusWith<std::vector<StorageEngine::CollectionIndexNamePair>> @@ -964,7 +964,7 @@ int64_t StorageEngineImpl::sizeOnDiskForDb(OperationContext* opCtx, StringData d size += catalogEntry->getRecordStore()->storageSize(opCtx); std::vector<std::string> indexNames; - catalogEntry->getAllIndexes(opCtx, &indexNames); + _catalog->getAllIndexes(opCtx, collection->ns(), &indexNames); for (size_t i = 0; i < indexNames.size(); i++) { std::string ident = diff --git a/src/mongo/db/storage/kv/storage_engine_impl.h b/src/mongo/db/storage/kv/storage_engine_impl.h index 81a2ad3f476..c8084559b80 100644 --- a/src/mongo/db/storage/kv/storage_engine_impl.h +++ b/src/mongo/db/storage/kv/storage_engine_impl.h @@ -36,8 +36,9 @@ #include "mongo/base/string_data.h" #include "mongo/bson/timestamp.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/storage/durable_catalog.h" +#include "mongo/db/storage/durable_catalog.h" #include "mongo/db/storage/journal_listener.h" -#include "mongo/db/storage/kv/kv_catalog.h" #include "mongo/db/storage/kv/kv_catalog_feature_tracker.h" #include "mongo/db/storage/kv/kv_drop_pending_ident_reaper.h" #include "mongo/db/storage/kv/storage_engine_interface.h" @@ -307,10 +308,10 @@ public: const NamespaceString& nss, StringData ident) override; - KVCatalog* getCatalog() { + DurableCatalog* getCatalog() { return _catalog.get(); } - const KVCatalog* getCatalog() const { + const DurableCatalog* getCatalog() const { return _catalog.get(); } diff --git a/src/mongo/db/storage/kv/storage_engine_interface.h b/src/mongo/db/storage/kv/storage_engine_interface.h index 89ab71b83b2..db7201c1492 100644 --- a/src/mongo/db/storage/kv/storage_engine_interface.h +++ b/src/mongo/db/storage/kv/storage_engine_interface.h @@ -32,7 +32,7 @@ namespace mongo { class KVEngine; -class KVCatalog; +class DurableCatalog; class StorageEngine; class StorageEngineInterface { @@ -44,6 +44,6 @@ public: virtual void addDropPendingIdent(const Timestamp& dropTimestamp, const NamespaceString& nss, StringData ident) = 0; - virtual KVCatalog* getCatalog() = 0; + virtual DurableCatalog* getCatalog() = 0; }; } diff --git a/src/mongo/db/storage/kv/storage_engine_test.cpp b/src/mongo/db/storage/kv/storage_engine_test.cpp index 5465a5ff31f..d80d9da9043 100644 --- a/src/mongo/db/storage/kv/storage_engine_test.cpp +++ b/src/mongo/db/storage/kv/storage_engine_test.cpp @@ -41,8 +41,8 @@ #include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/db/service_context_d_test_fixture.h" #include "mongo/db/storage/devnull/devnull_kv_engine.h" +#include "mongo/db/storage/durable_catalog.h" #include "mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.h" -#include "mongo/db/storage/kv/kv_catalog.h" #include "mongo/db/storage/kv/kv_engine.h" #include "mongo/db/storage/kv/storage_engine_impl.h" #include "mongo/db/storage/kv/storage_engine_test_fixture.h" @@ -59,12 +59,12 @@ namespace { TEST_F(StorageEngineTest, ReconcileIdentsTest) { auto opCtx = cc().makeOperationContext(); - // Add a collection, `db.coll1` to both the KVCatalog and KVEngine. The returned value is the - // `ident` name given to the collection. + // 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); - // Create a table in the KVEngine not reflected in the KVCatalog. This should be dropped when - // reconciling. + // 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"))); ASSERT_OK(reconcile(opCtx.get()).getStatus()); auto identsVec = getAllKVEngineIdents(opCtx.get()); @@ -86,7 +86,7 @@ TEST_F(StorageEngineTest, ReconcileIdentsTest) { ASSERT_EQUALS("db.coll1", toRebuild.first); ASSERT_EQUALS("_id", toRebuild.second); - // Now drop the `db.coll1` table, while leaving the KVCatalog entry. + // Now drop the `db.coll1` table, while leaving the DurableCatalog entry. ASSERT_OK(dropIdent(opCtx.get(), swIdentName.getValue())); ASSERT_EQUALS(static_cast<const unsigned long>(1), getAllKVEngineIdents(opCtx.get()).size()); diff --git a/src/mongo/db/storage/kv/storage_engine_test_fixture.h b/src/mongo/db/storage/kv/storage_engine_test_fixture.h index 7f3bddb4bc8..7c588c991cd 100644 --- a/src/mongo/db/storage/kv/storage_engine_test_fixture.h +++ b/src/mongo/db/storage/kv/storage_engine_test_fixture.h @@ -33,7 +33,7 @@ #include "mongo/db/catalog/collection_mock.h" #include "mongo/db/catalog_raii.h" #include "mongo/db/service_context_d_test_fixture.h" -#include "mongo/db/storage/kv/kv_catalog.h" +#include "mongo/db/storage/durable_catalog.h" #include "mongo/db/storage/kv/kv_engine.h" #include "mongo/db/storage/kv/storage_engine_impl.h" #include "mongo/db/storage/storage_repair_observer.h" @@ -68,7 +68,7 @@ public: } /** - * Create a collection table in the KVEngine not reflected in the KVCatalog. + * Create a collection table in the KVEngine not reflected in the DurableCatalog. */ Status createCollTable(OperationContext* opCtx, NamespaceString collName) { const std::string identName = "collection-" + collName.ns(); @@ -134,11 +134,9 @@ public: auto descriptor = std::make_unique<IndexDescriptor>( collection.get(), IndexNames::findPluginName(spec), spec); - CollectionCatalogEntry* cce = - CollectionCatalog::get(opCtx).lookupCollectionCatalogEntryByNamespace(collNs); const auto protocol = IndexBuildProtocol::kTwoPhase; - auto ret = cce->prepareForIndexBuild( - opCtx, descriptor.get(), protocol, isBackgroundSecondaryBuild); + auto ret = DurableCatalog::get(opCtx)->prepareForIndexBuild( + opCtx, collNs, descriptor.get(), protocol, isBackgroundSecondaryBuild); return ret; } @@ -147,25 +145,20 @@ public: std::string key, std::string sideWritesIdent, std::string constraintViolationsIdent) { - CollectionCatalogEntry* cce = - CollectionCatalog::get(opCtx).lookupCollectionCatalogEntryByNamespace(collNs); - cce->setIndexBuildScanning(opCtx, key, sideWritesIdent, constraintViolationsIdent); + DurableCatalog::get(opCtx)->setIndexBuildScanning( + opCtx, collNs, key, sideWritesIdent, constraintViolationsIdent); } void indexBuildDrain(OperationContext* opCtx, NamespaceString collNs, std::string key) { - CollectionCatalogEntry* cce = - CollectionCatalog::get(opCtx).lookupCollectionCatalogEntryByNamespace(collNs); - cce->setIndexBuildDraining(opCtx, key); + DurableCatalog::get(opCtx)->setIndexBuildDraining(opCtx, collNs, key); } void indexBuildSuccess(OperationContext* opCtx, NamespaceString collNs, std::string key) { - CollectionCatalogEntry* cce = - CollectionCatalog::get(opCtx).lookupCollectionCatalogEntryByNamespace(collNs); - cce->indexBuildSuccess(opCtx, key); + DurableCatalog::get(opCtx)->indexBuildSuccess(opCtx, collNs, key); } - Status removeEntry(OperationContext* opCtx, StringData ns, KVCatalog* catalog) { - return catalog->_removeEntry(opCtx, NamespaceString(ns)); + Status removeEntry(OperationContext* opCtx, StringData ns, DurableCatalog* catalog) { + return dynamic_cast<KVCatalog*>(catalog)->_removeEntry(opCtx, NamespaceString(ns)); } StorageEngine* _storageEngine; |