diff options
-rw-r--r-- | src/mongo/db/catalog/collection_impl.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/startup_recovery.cpp | 30 | ||||
-rw-r--r-- | src/mongo/db/storage/durable_catalog.h | 6 | ||||
-rw-r--r-- | src/mongo/db/storage/durable_catalog_feature_tracker.h | 195 | ||||
-rw-r--r-- | src/mongo/db/storage/durable_catalog_impl.cpp | 225 | ||||
-rw-r--r-- | src/mongo/db/storage/durable_catalog_impl.h | 19 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/storage/kv/durable_catalog_feature_tracker_test.cpp | 502 | ||||
-rw-r--r-- | src/mongo/db/storage/storage_engine.h | 14 | ||||
-rw-r--r-- | src/mongo/db/storage/storage_engine_impl.cpp | 20 | ||||
-rw-r--r-- | src/mongo/db/storage/storage_engine_impl.h | 18 | ||||
-rw-r--r-- | src/mongo/db/storage/storage_engine_mock.h | 4 | ||||
-rw-r--r-- | src/mongo/db/storage/storage_engine_test_fixture.h | 1 |
13 files changed, 33 insertions, 1014 deletions
diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index d79c64648d9..155dbbd6825 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -1737,8 +1737,16 @@ Status CollectionImpl::prepareForIndexBuild(OperationContext* opCtx, bool isBackgroundSecondaryBuild) { auto durableCatalog = DurableCatalog::get(opCtx); - auto imd = durableCatalog->prepareIndexMetaDataForIndexBuild( - opCtx, spec, buildUUID, isBackgroundSecondaryBuild); + BSONCollectionCatalogEntry::IndexMetaData imd; + imd.spec = spec->infoObj(); + imd.ready = false; + imd.multikey = false; + imd.isBackgroundSecondaryBuild = isBackgroundSecondaryBuild; + imd.buildUUID = buildUUID; + + if (indexTypeSupportsPathLevelMultikeyTracking(spec->getAccessMethodName())) { + imd.multikeyPaths = MultikeyPaths{static_cast<size_t>(spec->keyPattern().nFields())}; + } // Confirm that our index is not already in the current metadata. invariant(-1 == _metadata->findIndexOffset(imd.nameStringData()), diff --git a/src/mongo/db/startup_recovery.cpp b/src/mongo/db/startup_recovery.cpp index d91d484d319..ff6d18bf0db 100644 --- a/src/mongo/db/startup_recovery.cpp +++ b/src/mongo/db/startup_recovery.cpp @@ -270,34 +270,6 @@ void openDatabases(OperationContext* opCtx, const StorageEngine* storageEngine, } } -// Check for storage engine file compatibility. Exits the process if there is an incompatibility. -void assertFilesCompatible(OperationContext* opCtx, StorageEngine* storageEngine) { - auto status = storageEngine->currentFilesCompatible(opCtx); - if (status.isOK()) { - return; - } - - if (status.code() == ErrorCodes::CanRepairToDowngrade) { - // Convert CanRepairToDowngrade statuses to MustUpgrade statuses to avoid logging a - // potentially confusing and inaccurate message. - // - // TODO SERVER-24097: Log a message informing the user that they can start the current - // version of mongod with --repair and then proceed with normal startup. - status = {ErrorCodes::MustUpgrade, status.reason()}; - } - LOGV2_FATAL_CONTINUE( - 21023, - "Unable to start mongod due to an incompatibility with the data files and this version " - "of mongod: {error}. Please consult our documentation when trying to downgrade to a " - "previous major release", - "Unable to start mongod due to an incompatibility with the data files and this version " - "of mongod. Please consult our documentation when trying to downgrade to a previous " - "major release", - "error"_attr = redact(status)); - quickExit(EXIT_NEED_UPGRADE); - MONGO_UNREACHABLE; -} - /** * Returns 'true' if this server has a configuration document in local.system.replset. */ @@ -644,8 +616,6 @@ void repairAndRecoverDatabases(OperationContext* opCtx, } else { startupRecovery(opCtx, storageEngine, lastShutdownState); } - - assertFilesCompatible(opCtx, storageEngine); } } // namespace startup_recovery diff --git a/src/mongo/db/storage/durable_catalog.h b/src/mongo/db/storage/durable_catalog.h index 5d6d24848b7..ffd2a9f3e63 100644 --- a/src/mongo/db/storage/durable_catalog.h +++ b/src/mongo/db/storage/durable_catalog.h @@ -140,12 +140,6 @@ public: const CollectionOptions& collOptions, const IndexDescriptor* spec) = 0; - virtual BSONCollectionCatalogEntry::IndexMetaData prepareIndexMetaDataForIndexBuild( - OperationContext* opCtx, - const IndexDescriptor* spec, - boost::optional<UUID> buildUUID, - bool isBackgroundSecondaryBuild) = 0; - /** * Import a collection by inserting the given metadata into the durable catalog and instructing * the storage engine to import the corresponding idents. The metadata object should be a valid diff --git a/src/mongo/db/storage/durable_catalog_feature_tracker.h b/src/mongo/db/storage/durable_catalog_feature_tracker.h deleted file mode 100644 index 060a0d859a1..00000000000 --- a/src/mongo/db/storage/durable_catalog_feature_tracker.h +++ /dev/null @@ -1,195 +0,0 @@ -/** - * Copyright (C) 2018-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 <cstdint> -#include <memory> -#include <type_traits> - -#include "mongo/db/storage/durable_catalog_impl.h" - -namespace mongo { - -class OperationContext; -class RecordId; -class RecordStore; - -/** - * Manages the contents of a document in the DurableCatalogImpl used to restrict downgrade - * compatibility. - * - * When a new feature is enabled on a collection or index in the data files, a bit is set in one of - * the fields of the document. Older versions won't recognize this bit and will fail to start up as - * a result. - */ -class DurableCatalogImpl::FeatureTracker { -public: - /** - * Bit flags representing whether a particular feature is enabled on a least one collection or - * index in the data files. Features included in this enumeration always require user - * intervention on downgrade. - * - * The next feature added to this enumeration should use the current value of 'kNextFeatureBit', - * and 'kNextFeatureBit' should be changed to the next largest power of two. - */ - enum class NonRepairableFeature : std::uint64_t { - kCollation = 1 << 0, - kNextFeatureBit = 1 << 1 - }; - - using NonRepairableFeatureMask = std::underlying_type<NonRepairableFeature>::type; - - /** - * Bit flags representing whether a particular feature is enabled on a least one collection or - * index in the data files. Features included in this enumeration either (a) don't require user - * intervention on downgrade, or (b) are no longer enabled if --repair is done with an older - * version. - * - * The next feature added to this enumeration should use the current value of 'kNextFeatureBit', - * and 'kNextFeatureBit' should be changed to the next largest power of two. - */ - enum class RepairableFeature : std::uint64_t { - kPathLevelMultikeyTracking = 1 << 0, - kIndexKeyStringWithLongTypeBits = 1 << 1, - kNextFeatureBit = 1 << 2 - }; - - using RepairableFeatureMask = std::underlying_type<RepairableFeature>::type; - - /** - * Returns true if 'obj' represents the contents of the feature document that was previously - * inserted into the DurableCatalogImpl, and returns false otherwise. - * - * This function should return true for at most one document in the DurableCatalogImpl. - */ - static bool isFeatureDocument(BSONObj obj); - - /** - * Returns a FeatureTracker instance to manage the contents of the feature document located at - * 'rid' in the record store 'catalog->_rs'. - * - * It is invalid to call this function when isFeatureDocument() returns false for the record - * data associated with 'rid'. - */ - static std::unique_ptr<FeatureTracker> get(OperationContext* opCtx, - DurableCatalogImpl* catalog, - RecordId rid); - - /** - * Returns a FeatureTracker instance to manage the contents of a feature document. The feature - * document isn't inserted into 'rs' as a result of calling this function. Instead, the feature - * document is inserted into 'rs' when putInfo() is first called. - * - * It is invalid to call this function when isFeatureDocument() returns true for some document - * in the record store 'catalog->_rs'. - */ - static std::unique_ptr<FeatureTracker> create(OperationContext* opCtx, - DurableCatalogImpl* catalog); - - /** - * Returns whethers the data files are compatible with the current code: - * - * - Status::OK() if the data files are compatible with the current code. - * - * - ErrorCodes::CanRepairToDowngrade if the data files are incompatible with the current - * code, but a --repair would make them compatible. For example, when rebuilding all indexes - * in the data files would resolve the incompatibility. - * - * - ErrorCodes::MustUpgrade if the data files are incompatible with the current code and a - * newer version is required to start up. - */ - Status isCompatibleWithCurrentCode(OperationContext* opCtx) const; - - /** - * Returns true if 'feature' is tracked in the document, and returns false otherwise. - */ - bool isNonRepairableFeatureInUse(OperationContext* opCtx, NonRepairableFeature feature) const; - - /** - * Sets the specified non-repairable feature as being enabled on at least one collection or - * index in the data files. - */ - void markNonRepairableFeatureAsInUse(OperationContext* opCtx, NonRepairableFeature feature); - - /** - * Sets the specified non-repairable feature as not being enabled on any collection or index in - * the data files. - */ - void markNonRepairableFeatureAsNotInUse(OperationContext* opCtx, NonRepairableFeature feature); - - /** - * Returns true if 'feature' is tracked in the document, and returns false otherwise. - */ - bool isRepairableFeatureInUse(OperationContext* opCtx, RepairableFeature feature) const; - - /** - * Sets the specified repairable feature as being enabled on at least one collection or index in - * the data files. - */ - void markRepairableFeatureAsInUse(OperationContext* opCtx, RepairableFeature feature); - - /** - * Sets the specified repairable feature as not being enabled on any collection or index in the - * data files. - */ - void markRepairableFeatureAsNotInUse(OperationContext* opCtx, RepairableFeature feature); - - void setUsedNonRepairableFeaturesMaskForTestingOnly(NonRepairableFeatureMask mask) { - _usedNonRepairableFeaturesMask = mask; - } - - void setUsedRepairableFeaturesMaskForTestingOnly(RepairableFeatureMask mask) { - _usedRepairableFeaturesMask = mask; - } - - struct FeatureBits { - NonRepairableFeatureMask nonRepairableFeatures; - RepairableFeatureMask repairableFeatures; - }; - - FeatureBits getInfo(OperationContext* opCtx) const; - - void putInfo(OperationContext* opCtx, const FeatureBits& versionInfo); - -private: - // Must go through FeatureTracker::get() or FeatureTracker::create(). - FeatureTracker(DurableCatalogImpl* catalog, RecordId rid) : _catalog(catalog), _rid(rid) {} - - DurableCatalogImpl* _catalog; - RecordId _rid; - - NonRepairableFeatureMask _usedNonRepairableFeaturesMask = - static_cast<NonRepairableFeatureMask>(NonRepairableFeature::kNextFeatureBit) - 1; - - RepairableFeatureMask _usedRepairableFeaturesMask = - static_cast<RepairableFeatureMask>(RepairableFeature::kNextFeatureBit) - 1; -}; - -} // namespace mongo diff --git a/src/mongo/db/storage/durable_catalog_impl.cpp b/src/mongo/db/storage/durable_catalog_impl.cpp index c3bc50676fc..e607d606efb 100644 --- a/src/mongo/db/storage/durable_catalog_impl.cpp +++ b/src/mongo/db/storage/durable_catalog_impl.cpp @@ -44,7 +44,6 @@ #include "mongo/db/operation_context.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/server_options.h" -#include "mongo/db/storage/durable_catalog_feature_tracker.h" #include "mongo/db/storage/kv/kv_engine.h" #include "mongo/db/storage/record_store.h" #include "mongo/db/storage/recovery_unit.h" @@ -232,7 +231,7 @@ public: const std::string _ident; }; -bool DurableCatalogImpl::FeatureTracker::isFeatureDocument(BSONObj obj) { +bool DurableCatalogImpl::isFeatureDocument(BSONObj obj) { BSONElement firstElem = obj.firstElement(); if (firstElem.fieldNameStringData() == kIsFeatureDocumentFieldName) { return firstElem.booleanSafe(); @@ -240,158 +239,6 @@ bool DurableCatalogImpl::FeatureTracker::isFeatureDocument(BSONObj obj) { return false; } -Status DurableCatalogImpl::FeatureTracker::isCompatibleWithCurrentCode( - OperationContext* opCtx) const { - FeatureBits versionInfo = getInfo(opCtx); - - uint64_t unrecognizedNonRepairableFeatures = - versionInfo.nonRepairableFeatures & ~_usedNonRepairableFeaturesMask; - if (unrecognizedNonRepairableFeatures) { - StringBuilder sb; - sb << "The data files use features not recognized by this version of mongod; the NR feature" - " bits in positions "; - appendPositionsOfBitsSet(unrecognizedNonRepairableFeatures, &sb); - sb << " aren't recognized by this version of mongod"; - return {ErrorCodes::MustUpgrade, sb.str()}; - } - - uint64_t unrecognizedRepairableFeatures = - versionInfo.repairableFeatures & ~_usedRepairableFeaturesMask; - if (unrecognizedRepairableFeatures) { - StringBuilder sb; - sb << "The data files use features not recognized by this version of mongod; the R feature" - " bits in positions "; - appendPositionsOfBitsSet(unrecognizedRepairableFeatures, &sb); - sb << " aren't recognized by this version of mongod"; - return {ErrorCodes::CanRepairToDowngrade, sb.str()}; - } - - return Status::OK(); -} - -std::unique_ptr<DurableCatalogImpl::FeatureTracker> DurableCatalogImpl::FeatureTracker::get( - OperationContext* opCtx, DurableCatalogImpl* catalog, RecordId rid) { - auto record = catalog->_rs->dataFor(opCtx, rid); - BSONObj obj = record.toBson(); - invariant(isFeatureDocument(obj)); - return std::unique_ptr<DurableCatalogImpl::FeatureTracker>( - new DurableCatalogImpl::FeatureTracker(catalog, rid)); -} - -std::unique_ptr<DurableCatalogImpl::FeatureTracker> DurableCatalogImpl::FeatureTracker::create( - OperationContext* opCtx, DurableCatalogImpl* catalog) { - return std::unique_ptr<DurableCatalogImpl::FeatureTracker>( - new DurableCatalogImpl::FeatureTracker(catalog, RecordId())); -} - -bool DurableCatalogImpl::FeatureTracker::isNonRepairableFeatureInUse( - OperationContext* opCtx, NonRepairableFeature feature) const { - FeatureBits versionInfo = getInfo(opCtx); - return versionInfo.nonRepairableFeatures & static_cast<NonRepairableFeatureMask>(feature); -} - -void DurableCatalogImpl::FeatureTracker::markNonRepairableFeatureAsInUse( - OperationContext* opCtx, NonRepairableFeature feature) { - FeatureBits versionInfo = getInfo(opCtx); - versionInfo.nonRepairableFeatures |= static_cast<NonRepairableFeatureMask>(feature); - putInfo(opCtx, versionInfo); -} - -void DurableCatalogImpl::FeatureTracker::markNonRepairableFeatureAsNotInUse( - OperationContext* opCtx, NonRepairableFeature feature) { - FeatureBits versionInfo = getInfo(opCtx); - versionInfo.nonRepairableFeatures &= ~static_cast<NonRepairableFeatureMask>(feature); - putInfo(opCtx, versionInfo); -} - -bool DurableCatalogImpl::FeatureTracker::isRepairableFeatureInUse(OperationContext* opCtx, - RepairableFeature feature) const { - FeatureBits versionInfo = getInfo(opCtx); - return versionInfo.repairableFeatures & static_cast<RepairableFeatureMask>(feature); -} - -void DurableCatalogImpl::FeatureTracker::markRepairableFeatureAsInUse(OperationContext* opCtx, - RepairableFeature feature) { - FeatureBits versionInfo = getInfo(opCtx); - versionInfo.repairableFeatures |= static_cast<RepairableFeatureMask>(feature); - putInfo(opCtx, versionInfo); -} - -void DurableCatalogImpl::FeatureTracker::markRepairableFeatureAsNotInUse( - OperationContext* opCtx, RepairableFeature feature) { - FeatureBits versionInfo = getInfo(opCtx); - versionInfo.repairableFeatures &= ~static_cast<RepairableFeatureMask>(feature); - putInfo(opCtx, versionInfo); -} - -DurableCatalogImpl::FeatureTracker::FeatureBits DurableCatalogImpl::FeatureTracker::getInfo( - OperationContext* opCtx) const { - if (_rid.isNull()) { - return {}; - } - - auto record = _catalog->_rs->dataFor(opCtx, _rid); - BSONObj obj = record.toBson(); - invariant(isFeatureDocument(obj)); - - BSONElement nonRepairableFeaturesElem; - auto nonRepairableFeaturesStatus = bsonExtractTypedField( - obj, kNonRepairableFeaturesFieldName, BSONType::NumberLong, &nonRepairableFeaturesElem); - if (!nonRepairableFeaturesStatus.isOK()) { - LOGV2_ERROR(22215, - "error: exception extracting typed field with obj:{obj}", - "Exception extracting typed field from obj", - "obj"_attr = redact(obj), - "fieldName"_attr = kNonRepairableFeaturesFieldName); - fassert(40111, nonRepairableFeaturesStatus); - } - - BSONElement repairableFeaturesElem; - auto repairableFeaturesStatus = bsonExtractTypedField( - obj, kRepairableFeaturesFieldName, BSONType::NumberLong, &repairableFeaturesElem); - if (!repairableFeaturesStatus.isOK()) { - LOGV2_ERROR(22216, - "error: exception extracting typed field with obj:{obj}", - "Exception extracting typed field from obj", - "obj"_attr = redact(obj), - "fieldName"_attr = kRepairableFeaturesFieldName); - fassert(40112, repairableFeaturesStatus); - } - - FeatureBits versionInfo; - versionInfo.nonRepairableFeatures = - static_cast<NonRepairableFeatureMask>(nonRepairableFeaturesElem.numberLong()); - versionInfo.repairableFeatures = - static_cast<RepairableFeatureMask>(repairableFeaturesElem.numberLong()); - return versionInfo; -} - -void DurableCatalogImpl::FeatureTracker::putInfo(OperationContext* opCtx, - const FeatureBits& versionInfo) { - BSONObjBuilder bob; - bob.appendBool(kIsFeatureDocumentFieldName, true); - // We intentionally include the "ns" field with a null value in the feature document to prevent - // older versions that do 'obj["ns"].String()' from starting up. This way only versions that are - // aware of the feature document's existence can successfully start up. - bob.appendNull(kNamespaceFieldName); - bob.append(kNonRepairableFeaturesFieldName, - static_cast<long long>(versionInfo.nonRepairableFeatures)); - bob.append(kRepairableFeaturesFieldName, - static_cast<long long>(versionInfo.repairableFeatures)); - BSONObj obj = bob.done(); - - if (_rid.isNull()) { - // This is the first time a feature is being marked as in-use or not in-use, so we must - // insert the feature document rather than update it. - auto rid = _catalog->_rs->insertRecord(opCtx, obj.objdata(), obj.objsize(), Timestamp()); - fassert(40113, rid.getStatus()); - _rid = rid.getValue(); - } else { - auto status = _catalog->_rs->updateRecord(opCtx, _rid, obj.objdata(), obj.objsize()); - fassert(40114, status); - } -} - DurableCatalogImpl::DurableCatalogImpl(RecordStore* rs, bool directoryPerDb, bool directoryForIndexes, @@ -464,13 +311,8 @@ void DurableCatalogImpl::init(OperationContext* opCtx) { while (auto record = cursor->next()) { BSONObj obj = record->data.releaseToBson(); - if (FeatureTracker::isFeatureDocument(obj)) { - // There should be at most one version document in the catalog. - invariant(!_featureTracker); - - // Initialize the feature tracker and skip over the version document because it doesn't - // correspond to a namespace entry. - _featureTracker = FeatureTracker::get(opCtx, this, record->id); + // For backwards compatibility where older version have a written feature document + if (isFeatureDocument(obj)) { continue; } @@ -480,16 +322,6 @@ void DurableCatalogImpl::init(OperationContext* opCtx) { _catalogIdToEntryMap[record->id] = Entry(record->id, ident, NamespaceString(ns)); } - if (!_featureTracker) { - // If there wasn't a feature document, commit a default one to disk. All deployments will - // end up with `kPathLevelMultikeyTracking` as every `_id` index build sets this. - WriteUnitOfWork wuow(opCtx); - _featureTracker = DurableCatalogImpl::FeatureTracker::create(opCtx, this); - _featureTracker->markRepairableFeatureAsInUse( - opCtx, FeatureTracker::RepairableFeature::kPathLevelMultikeyTracking); - wuow.commit(); - } - // In the unlikely event that we have used this _rand before generate a new one. stdx::lock_guard<Latch> lk(_randLock); while (_hasEntryCollidingWithRand(lk)) { @@ -504,7 +336,7 @@ std::vector<DurableCatalog::Entry> DurableCatalogImpl::getAllCatalogEntries( auto cursor = _rs->getCursor(opCtx); while (auto record = cursor->next()) { BSONObj obj = record->data.releaseToBson(); - if (FeatureTracker::isFeatureDocument(obj)) { + if (isFeatureDocument(obj)) { // Skip over the version document because it doesn't correspond to a collection. continue; } @@ -732,7 +564,7 @@ std::vector<std::string> DurableCatalogImpl::getAllIdents(OperationContext* opCt auto cursor = _rs->getCursor(opCtx); while (auto record = cursor->next()) { BSONObj obj = record->data.releaseToBson(); - if (FeatureTracker::isFeatureDocument(obj)) { + if (isFeatureDocument(obj)) { // Skip over the version document because it doesn't correspond to a namespace entry and // therefore doesn't refer to any idents. continue; @@ -839,14 +671,6 @@ StatusWith<std::pair<RecordId, std::unique_ptr<RecordStore>>> DurableCatalogImpl if (!status.isOK()) return status; - // Mark collation feature as in use if the collection has a non-simple default collation. - if (!options.collation.isEmpty()) { - const auto feature = DurableCatalogImpl::FeatureTracker::NonRepairableFeature::kCollation; - if (getFeatureTracker()->isNonRepairableFeatureInUse(opCtx, feature)) { - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx, feature); - } - } - auto ru = opCtx->recoveryUnit(); CollectionUUID uuid = options.uuid.get(); opCtx->recoveryUnit()->onRollback([ru, catalog = this, nss, ident = entry.ident, uuid]() { @@ -959,14 +783,6 @@ StatusWith<DurableCatalog::ImportResult> DurableCatalogImpl::importCollection( } } - // Mark collation feature as in use if the collection has a non-simple default collation. - if (!md.options.collation.isEmpty()) { - const auto feature = DurableCatalogImpl::FeatureTracker::NonRepairableFeature::kCollation; - if (getFeatureTracker()->isNonRepairableFeatureInUse(opCtx, feature)) { - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx, feature); - } - } - opCtx->recoveryUnit()->onRollback( [opCtx, catalog = this, ident = entry.ident, indexIdents = indexIdents]() { catalog->_engine->getEngine()->dropIdentForImport(opCtx, ident); @@ -1007,37 +823,6 @@ Status DurableCatalogImpl::dropCollection(OperationContext* opCtx, RecordId cata return Status::OK(); } -BSONCollectionCatalogEntry::IndexMetaData DurableCatalogImpl::prepareIndexMetaDataForIndexBuild( - OperationContext* opCtx, - const IndexDescriptor* spec, - boost::optional<UUID> buildUUID, - bool isBackgroundSecondaryBuild) { - BSONCollectionCatalogEntry::IndexMetaData imd; - imd.spec = spec->infoObj(); - imd.ready = false; - imd.multikey = false; - imd.isBackgroundSecondaryBuild = isBackgroundSecondaryBuild; - imd.buildUUID = buildUUID; - - 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 = FeatureTracker::NonRepairableFeature::kCollation; - if (!getFeatureTracker()->isNonRepairableFeatureInUse(opCtx, feature)) { - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx, feature); - } - } - - return imd; -} - Status DurableCatalogImpl::dropAndRecreateIndexIdentForResume(OperationContext* opCtx, const CollectionOptions& collOptions, const IndexDescriptor* spec, diff --git a/src/mongo/db/storage/durable_catalog_impl.h b/src/mongo/db/storage/durable_catalog_impl.h index 63a8c9ec062..f0eeba00fed 100644 --- a/src/mongo/db/storage/durable_catalog_impl.h +++ b/src/mongo/db/storage/durable_catalog_impl.h @@ -49,7 +49,6 @@ class StorageEngineInterface; class DurableCatalogImpl : public DurableCatalog { public: - class FeatureTracker; /** * The RecordStore must be thread-safe, in particular with concurrent calls to * RecordStore::find, updateRecord, insertRecord, deleteRecord and dataFor. The @@ -93,11 +92,6 @@ public: bool isCollectionIdent(StringData ident) const; - FeatureTracker* getFeatureTracker() const { - invariant(_featureTracker); - return _featureTracker.get(); - } - RecordStore* getRecordStore() { return _rs; } @@ -120,12 +114,6 @@ public: const CollectionOptions& collOptions, const IndexDescriptor* spec); - BSONCollectionCatalogEntry::IndexMetaData prepareIndexMetaDataForIndexBuild( - OperationContext* opCtx, - const IndexDescriptor* spec, - boost::optional<UUID> buildUUID, - bool isBackgroundSecondaryBuild); - StatusWith<ImportResult> importCollection(OperationContext* opCtx, const NamespaceString& nss, const BSONObj& metadata, @@ -197,6 +185,9 @@ private: */ bool _hasEntryCollidingWithRand(WithLock) const; + // Allows featureDocuments to be checked with older versions + static bool isFeatureDocument(BSONObj obj); + RecordStore* _rs; // not owned const bool _directoryPerDb; const bool _directoryForIndexes; @@ -210,10 +201,6 @@ private: 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. - std::unique_ptr<FeatureTracker> _featureTracker; - StorageEngineInterface* const _engine; }; } // namespace mongo diff --git a/src/mongo/db/storage/kv/SConscript b/src/mongo/db/storage/kv/SConscript index 6e16d805457..98011a4a374 100644 --- a/src/mongo/db/storage/kv/SConscript +++ b/src/mongo/db/storage/kv/SConscript @@ -17,7 +17,6 @@ env.Library( env.Library( target='kv_engine_test_harness', source=[ - 'durable_catalog_feature_tracker_test.cpp', 'kv_engine_test_harness.cpp', 'kv_engine_timestamps_test.cpp', ], diff --git a/src/mongo/db/storage/kv/durable_catalog_feature_tracker_test.cpp b/src/mongo/db/storage/kv/durable_catalog_feature_tracker_test.cpp deleted file mode 100644 index e7cdf744c35..00000000000 --- a/src/mongo/db/storage/kv/durable_catalog_feature_tracker_test.cpp +++ /dev/null @@ -1,502 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the Server Side Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/db/storage/kv/kv_engine_test_harness.h" - -#include <memory> - -#include "mongo/db/operation_context_noop.h" -#include "mongo/db/service_context_test_fixture.h" -#include "mongo/db/storage/durable_catalog_feature_tracker.h" -#include "mongo/db/storage/kv/kv_engine.h" -#include "mongo/db/storage/record_store.h" -#include "mongo/unittest/unittest.h" - -namespace mongo { -namespace { - -using NonRepairableFeature = DurableCatalogImpl::FeatureTracker::NonRepairableFeature; -using NonRepairableFeatureMask = DurableCatalogImpl::FeatureTracker::NonRepairableFeatureMask; -using RepairableFeature = DurableCatalogImpl::FeatureTracker::RepairableFeature; -using RepairableFeatureMask = DurableCatalogImpl::FeatureTracker::RepairableFeatureMask; - -class DurableCatalogFeatureTrackerTest : public ServiceContextTest { -public: - static const NonRepairableFeature kNonRepairableFeature1 = - static_cast<NonRepairableFeature>(1 << 0); - - static const NonRepairableFeature kNonRepairableFeature2 = - static_cast<NonRepairableFeature>(1 << 1); - - static const NonRepairableFeature kNonRepairableFeature3 = - static_cast<NonRepairableFeature>(1 << 2); - - static const RepairableFeature kRepairableFeature1 = static_cast<RepairableFeature>(1 << 0); - - static const RepairableFeature kRepairableFeature2 = static_cast<RepairableFeature>(1 << 1); - - static const RepairableFeature kRepairableFeature3 = static_cast<RepairableFeature>(1 << 2); - - DurableCatalogFeatureTrackerTest() : _helper(KVHarnessHelper::create(getServiceContext())) {} - - ServiceContext::UniqueOperationContext newOperationContext() { - auto opCtx = makeOperationContext(); - opCtx->setRecoveryUnit( - std::unique_ptr<RecoveryUnit>(_helper->getEngine()->newRecoveryUnit()), - WriteUnitOfWork::RecoveryUnitState::kNotInUnitOfWork); - opCtx->swapLockState(std::make_unique<LockerNoop>(), WithLock::withoutLock()); - return opCtx; - } - - void setUp() final { - auto opCtx = newOperationContext(); - { - WriteUnitOfWork wuow(opCtx.get()); - ASSERT_OK(_helper->getEngine()->createRecordStore( - opCtx.get(), "catalog", "catalog", CollectionOptions())); - _rs = _helper->getEngine()->getRecordStore( - opCtx.get(), "catalog", "catalog", CollectionOptions()); - wuow.commit(); - } - - _catalog = std::make_unique<DurableCatalogImpl>(_rs.get(), false, false, nullptr); - _catalog->init(opCtx.get()); - - { - WriteUnitOfWork wuow(opCtx.get()); - _featureTracker = - DurableCatalogImpl::FeatureTracker::create(opCtx.get(), _catalog.get()); - wuow.commit(); - } - } - - RecordStore* getRecordStore() const { - return _rs.get(); - } - - DurableCatalogImpl::FeatureTracker* getFeatureTracker() const { - return _featureTracker.get(); - } - -private: - std::unique_ptr<KVHarnessHelper> _helper; - std::unique_ptr<RecordStore> _rs; - std::unique_ptr<DurableCatalogImpl> _catalog; - std::unique_ptr<DurableCatalogImpl::FeatureTracker> _featureTracker; -}; - -TEST_F(DurableCatalogFeatureTrackerTest, CanMarkNonRepairableFeatureAsInUse) { - { - auto opCtx = newOperationContext(); - ASSERT( - !getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx.get(), - kNonRepairableFeature1); - wuow.commit(); - } - ASSERT( - getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - - // Marking the same non-repairable feature as in-use again does nothing. - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx.get(), - kNonRepairableFeature1); - wuow.commit(); - } - ASSERT( - getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - } - - // The repairable feature bit in the same position is unaffected. - { - auto opCtx = newOperationContext(); - ASSERT(!getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - } - - // The non-repairable feature in a different position is unaffected. - { - auto opCtx = newOperationContext(); - ASSERT( - !getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature2)); - } -} - -TEST_F(DurableCatalogFeatureTrackerTest, CanMarkNonRepairableFeatureAsNotInUse) { - { - auto opCtx = newOperationContext(); - - ASSERT( - !getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx.get(), - kNonRepairableFeature1); - wuow.commit(); - } - ASSERT( - getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - - ASSERT(!getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsInUse(opCtx.get(), kRepairableFeature1); - wuow.commit(); - } - ASSERT(getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - - ASSERT( - !getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature2)); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx.get(), - kNonRepairableFeature2); - wuow.commit(); - } - ASSERT( - getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature2)); - } - - { - auto opCtx = newOperationContext(); - ASSERT( - getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsNotInUse(opCtx.get(), - kNonRepairableFeature1); - wuow.commit(); - } - ASSERT( - !getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - - // Marking the same non-repairable feature as not in-use again does nothing. - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsNotInUse(opCtx.get(), - kNonRepairableFeature1); - wuow.commit(); - } - ASSERT( - !getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - } - - // The repairable feature bit in the same position is unaffected. - { - auto opCtx = newOperationContext(); - ASSERT(getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - } - - // The non-repairable feature in a different position is unaffected. - { - auto opCtx = newOperationContext(); - ASSERT( - getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature2)); - } -} - -TEST_F(DurableCatalogFeatureTrackerTest, CanMarkRepairableFeatureAsInUse) { - { - auto opCtx = newOperationContext(); - ASSERT(!getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsInUse(opCtx.get(), kRepairableFeature1); - wuow.commit(); - } - ASSERT(getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - - // Marking the same repairable feature as in-use again does nothing. - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsInUse(opCtx.get(), kRepairableFeature1); - wuow.commit(); - } - ASSERT(getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - } - - // The non-repairable feature bit in the same position is unaffected. - { - auto opCtx = newOperationContext(); - ASSERT( - !getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - } - - // The repairable feature in a different position is unaffected. - { - auto opCtx = newOperationContext(); - ASSERT(!getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature2)); - } -} - -TEST_F(DurableCatalogFeatureTrackerTest, CanMarkRepairableFeatureAsNotInUse) { - { - auto opCtx = newOperationContext(); - - ASSERT(!getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsInUse(opCtx.get(), kRepairableFeature1); - wuow.commit(); - } - ASSERT(getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - - ASSERT( - !getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx.get(), - kNonRepairableFeature1); - wuow.commit(); - } - ASSERT( - getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - - ASSERT(!getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature2)); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsInUse(opCtx.get(), kRepairableFeature2); - wuow.commit(); - } - ASSERT(getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature2)); - } - - { - auto opCtx = newOperationContext(); - ASSERT(getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsNotInUse(opCtx.get(), kRepairableFeature1); - wuow.commit(); - } - ASSERT(!getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - - // Marking the same repairable feature as not in-use again does nothing. - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsNotInUse(opCtx.get(), kRepairableFeature1); - wuow.commit(); - } - ASSERT(!getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature1)); - } - - // The non-repairable feature bit in the same position is unaffected. - { - auto opCtx = newOperationContext(); - ASSERT( - getFeatureTracker()->isNonRepairableFeatureInUse(opCtx.get(), kNonRepairableFeature1)); - } - - // The repairable feature in a different position is unaffected. - { - auto opCtx = newOperationContext(); - ASSERT(getFeatureTracker()->isRepairableFeatureInUse(opCtx.get(), kRepairableFeature2)); - } -} - -TEST_F(DurableCatalogFeatureTrackerTest, DataFileAreCompatibleWithRecognizedNonRepairableFeature) { - getFeatureTracker()->setUsedNonRepairableFeaturesMaskForTestingOnly(0ULL); - getFeatureTracker()->setUsedRepairableFeaturesMaskForTestingOnly(0ULL); - - { - auto opCtx = newOperationContext(); - ASSERT_OK(getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get())); - } - - getFeatureTracker()->setUsedNonRepairableFeaturesMaskForTestingOnly( - static_cast<NonRepairableFeatureMask>(kNonRepairableFeature1)); - - { - auto opCtx = newOperationContext(); - ASSERT_OK(getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get())); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx.get(), - kNonRepairableFeature1); - wuow.commit(); - } - ASSERT_OK(getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get())); - } -} - -TEST_F(DurableCatalogFeatureTrackerTest, - DataFilesAreIncompatibleWithAnUnrecognizedNonRepairableFeature) { - getFeatureTracker()->setUsedNonRepairableFeaturesMaskForTestingOnly(0ULL); - getFeatureTracker()->setUsedRepairableFeaturesMaskForTestingOnly(0ULL); - - { - auto opCtx = newOperationContext(); - ASSERT_OK(getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get())); - } - - { - auto opCtx = newOperationContext(); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx.get(), - kNonRepairableFeature1); - wuow.commit(); - } - - auto status = getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get()); - ASSERT_EQ(ErrorCodes::MustUpgrade, status.code()); - ASSERT_EQ( - "The data files use features not recognized by this version of mongod; the NR feature" - " bits in positions [ 0 ] aren't recognized by this version of mongod", - status.reason()); - } -} - -TEST_F(DurableCatalogFeatureTrackerTest, - DataFilesAreIncompatibleWithMultipleUnrecognizedNonRepairableFeatures) { - getFeatureTracker()->setUsedNonRepairableFeaturesMaskForTestingOnly( - static_cast<NonRepairableFeatureMask>(kNonRepairableFeature1)); - getFeatureTracker()->setUsedRepairableFeaturesMaskForTestingOnly(0ULL); - - { - auto opCtx = newOperationContext(); - ASSERT_OK(getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get())); - } - - { - auto opCtx = newOperationContext(); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx.get(), - kNonRepairableFeature2); - wuow.commit(); - } - - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markNonRepairableFeatureAsInUse(opCtx.get(), - kNonRepairableFeature3); - wuow.commit(); - } - - auto status = getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get()); - ASSERT_EQ(ErrorCodes::MustUpgrade, status.code()); - ASSERT_EQ( - "The data files use features not recognized by this version of mongod; the NR feature" - " bits in positions [ 1, 2 ] aren't recognized by this version of mongod", - status.reason()); - } -} - -TEST_F(DurableCatalogFeatureTrackerTest, DataFilesAreCompatibleWithRecognizedRepairableFeature) { - getFeatureTracker()->setUsedNonRepairableFeaturesMaskForTestingOnly(0ULL); - getFeatureTracker()->setUsedRepairableFeaturesMaskForTestingOnly(0ULL); - - { - auto opCtx = newOperationContext(); - ASSERT_OK(getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get())); - } - - getFeatureTracker()->setUsedRepairableFeaturesMaskForTestingOnly( - static_cast<RepairableFeatureMask>(kRepairableFeature1)); - - { - auto opCtx = newOperationContext(); - ASSERT_OK(getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get())); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsInUse(opCtx.get(), kRepairableFeature1); - wuow.commit(); - } - ASSERT_OK(getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get())); - } -} - -TEST_F(DurableCatalogFeatureTrackerTest, - DataFilesAreIncompatibleWithAnUnrecognizedRepairableFeature) { - getFeatureTracker()->setUsedNonRepairableFeaturesMaskForTestingOnly(0ULL); - getFeatureTracker()->setUsedRepairableFeaturesMaskForTestingOnly(0ULL); - - { - auto opCtx = newOperationContext(); - ASSERT_OK(getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get())); - } - - { - auto opCtx = newOperationContext(); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsInUse(opCtx.get(), kRepairableFeature1); - wuow.commit(); - } - - auto status = getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get()); - ASSERT_EQ(ErrorCodes::CanRepairToDowngrade, status.code()); - ASSERT_EQ( - "The data files use features not recognized by this version of mongod; the R feature" - " bits in positions [ 0 ] aren't recognized by this version of mongod", - status.reason()); - } -} - -TEST_F(DurableCatalogFeatureTrackerTest, - DataFilesAreIncompatibleWithMultipleUnrecognizedRepairableFeatures) { - getFeatureTracker()->setUsedNonRepairableFeaturesMaskForTestingOnly(0ULL); - getFeatureTracker()->setUsedRepairableFeaturesMaskForTestingOnly( - static_cast<RepairableFeatureMask>(kRepairableFeature1)); - - { - auto opCtx = newOperationContext(); - ASSERT_OK(getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get())); - } - - { - auto opCtx = newOperationContext(); - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsInUse(opCtx.get(), kRepairableFeature2); - wuow.commit(); - } - - { - WriteUnitOfWork wuow(opCtx.get()); - getFeatureTracker()->markRepairableFeatureAsInUse(opCtx.get(), kRepairableFeature3); - wuow.commit(); - } - - auto status = getFeatureTracker()->isCompatibleWithCurrentCode(opCtx.get()); - ASSERT_EQ(ErrorCodes::CanRepairToDowngrade, status.code()); - ASSERT_EQ( - "The data files use features not recognized by this version of mongod; the R feature" - " bits in positions [ 1, 2 ] aren't recognized by this version of mongod", - status.reason()); - } -} - -} // namespace -} // namespace mongo diff --git a/src/mongo/db/storage/storage_engine.h b/src/mongo/db/storage/storage_engine.h index aed7c3978d4..a99638bf85f 100644 --- a/src/mongo/db/storage/storage_engine.h +++ b/src/mongo/db/storage/storage_engine.h @@ -641,20 +641,6 @@ public: */ virtual std::string getFilesystemPathForDb(const std::string& dbName) const = 0; - /** - * Returns whethers the data files are compatible with the current code: - * - * - Status::OK() if the data files are compatible with the current code. - * - * - ErrorCodes::CanRepairToDowngrade if the data files are incompatible with the current - * code, but a --repair would make them compatible. For example, when rebuilding all indexes - * in the data files would resolve the incompatibility. - * - * - ErrorCodes::MustUpgrade if the data files are incompatible with the current code and a - * newer version is required to start up. - */ - virtual Status currentFilesCompatible(OperationContext* opCtx) const = 0; - virtual int64_t sizeOnDiskForDb(OperationContext* opCtx, StringData dbName) = 0; virtual bool isUsingDirectoryPerDb() const = 0; diff --git a/src/mongo/db/storage/storage_engine_impl.cpp b/src/mongo/db/storage/storage_engine_impl.cpp index 466ed068640..bc2ae2ca72a 100644 --- a/src/mongo/db/storage/storage_engine_impl.cpp +++ b/src/mongo/db/storage/storage_engine_impl.cpp @@ -43,7 +43,7 @@ #include "mongo/db/index_builds_coordinator.h" #include "mongo/db/operation_context.h" #include "mongo/db/server_options.h" -#include "mongo/db/storage/durable_catalog_feature_tracker.h" +#include "mongo/db/storage/durable_catalog_impl.h" #include "mongo/db/storage/durable_history_pin.h" #include "mongo/db/storage/kv/kv_engine.h" #include "mongo/db/storage/kv/temporary_kv_record_store.h" @@ -992,16 +992,6 @@ bool StorageEngineImpl::supportsRecoveryTimestamp() const { StatusWith<Timestamp> StorageEngineImpl::recoverToStableTimestamp(OperationContext* opCtx) { invariant(opCtx->lockState()->isW()); - // The "feature document" should not be rolled back. Perform a non-timestamped update to the - // feature document to lock in the current state. - DurableCatalogImpl::FeatureTracker::FeatureBits featureInfo; - { - WriteUnitOfWork wuow(opCtx); - featureInfo = _catalog->getFeatureTracker()->getInfo(opCtx); - _catalog->getFeatureTracker()->putInfo(opCtx, featureInfo); - wuow.commit(); - } - auto state = catalog::closeCatalog(opCtx); StatusWith<Timestamp> swTimestamp = _engine->recoverToStableTimestamp(opCtx); @@ -1270,4 +1260,12 @@ void StorageEngineImpl::setPinnedOplogTimestamp(const Timestamp& pinnedTimestamp _engine->setPinnedOplogTimestamp(pinnedTimestamp); } +DurableCatalog* StorageEngineImpl::getCatalog() { + return _catalog.get(); +} + +const DurableCatalog* StorageEngineImpl::getCatalog() const { + return _catalog.get(); +} + } // namespace mongo diff --git a/src/mongo/db/storage/storage_engine_impl.h b/src/mongo/db/storage/storage_engine_impl.h index 119de49c4bf..94662c3ede2 100644 --- a/src/mongo/db/storage/storage_engine_impl.h +++ b/src/mongo/db/storage/storage_engine_impl.h @@ -39,7 +39,6 @@ #include "mongo/bson/timestamp.h" #include "mongo/db/namespace_string.h" #include "mongo/db/storage/durable_catalog.h" -#include "mongo/db/storage/durable_catalog_feature_tracker.h" #include "mongo/db/storage/journal_listener.h" #include "mongo/db/storage/kv/kv_drop_pending_ident_reaper.h" #include "mongo/db/storage/record_store.h" @@ -320,19 +319,15 @@ public: void checkpoint() override; - DurableCatalog* getCatalog() override { - return _catalog.get(); - } - - const DurableCatalog* getCatalog() const override { - return _catalog.get(); - } - StatusWith<ReconcileResult> reconcileCatalogAndIdents( OperationContext* opCtx, LastShutdownState lastShutdownState) override; std::string getFilesystemPathForDb(const std::string& dbName) const override; + DurableCatalog* getCatalog() override; + + const DurableCatalog* getCatalog() const override; + /** * When loading after an unclean shutdown, this performs cleanup on the DurableCatalogImpl. */ @@ -348,11 +343,6 @@ public: return _dropPendingIdentReaper.getAllIdentNames(); } - Status currentFilesCompatible(OperationContext* opCtx) const override { - // Delegate to the FeatureTracker as to whether the data files are compatible or not. - return _catalog->getFeatureTracker()->isCompatibleWithCurrentCode(opCtx); - } - int64_t sizeOnDiskForDb(OperationContext* opCtx, StringData dbName) override; bool isUsingDirectoryPerDb() const override { diff --git a/src/mongo/db/storage/storage_engine_mock.h b/src/mongo/db/storage/storage_engine_mock.h index 3d69c854a5b..01b7f0409c0 100644 --- a/src/mongo/db/storage/storage_engine_mock.h +++ b/src/mongo/db/storage/storage_engine_mock.h @@ -170,9 +170,7 @@ public: std::shared_ptr<Ident> ident, DropIdentCallback&& onDrop) final {} void checkpoint() final {} - Status currentFilesCompatible(OperationContext* opCtx) const final { - return Status::OK(); - } + int64_t sizeOnDiskForDb(OperationContext* opCtx, StringData dbName) final { return 0; } diff --git a/src/mongo/db/storage/storage_engine_test_fixture.h b/src/mongo/db/storage/storage_engine_test_fixture.h index 57b50a1d32c..0a3d839fae5 100644 --- a/src/mongo/db/storage/storage_engine_test_fixture.h +++ b/src/mongo/db/storage/storage_engine_test_fixture.h @@ -37,6 +37,7 @@ #include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/db/service_context_d_test_fixture.h" #include "mongo/db/storage/durable_catalog.h" +#include "mongo/db/storage/durable_catalog_impl.h" #include "mongo/db/storage/kv/kv_engine.h" #include "mongo/db/storage/storage_engine_impl.h" #include "mongo/db/storage/storage_repair_observer.h" |