diff options
author | Dianna Hohensee <dianna.hohensee@10gen.com> | 2018-02-09 17:07:01 -0500 |
---|---|---|
committer | Dianna Hohensee <dianna.hohensee@10gen.com> | 2018-02-26 10:08:11 -0500 |
commit | bebdcf721eaa24fa589977bf48459a8cdd0fb2a2 (patch) | |
tree | 2ad878b058af53ab5f6c796787af9fe2f28b94fd /src/mongo | |
parent | 67d04f1a286b23ea824bdfb7042462d7da1b515d (diff) | |
download | mongo-bebdcf721eaa24fa589977bf48459a8cdd0fb2a2.tar.gz |
SERVER-33151 SERVER-33246 Refuse to start up mongod 4.0 unless all collections have UUIDs
Also assigns UUIDs to any non-replicated collection found to be missing its UUID.
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/repair_database_and_check_version.cpp | 124 |
1 files changed, 76 insertions, 48 deletions
diff --git a/src/mongo/db/repair_database_and_check_version.cpp b/src/mongo/db/repair_database_and_check_version.cpp index 0b627043dce..61799885d98 100644 --- a/src/mongo/db/repair_database_and_check_version.cpp +++ b/src/mongo/db/repair_database_and_check_version.cpp @@ -67,29 +67,6 @@ constexpr StringData mustDowngradeErrorMsg = Status restoreMissingFeatureCompatibilityVersionDocument(OperationContext* opCtx, const std::vector<std::string>& dbNames) { - // Check that all the collections have UUIDs. - bool isMmapV1 = opCtx->getServiceContext()->getGlobalStorageEngine()->isMmapV1(); - for (const auto& dbName : dbNames) { - Database* db = dbHolder().openDb(opCtx, dbName); - invariant(db); - for (auto collectionIt = db->begin(); collectionIt != db->end(); ++collectionIt) { - Collection* coll = *collectionIt; - if (!coll->uuid()) { - // system.indexes and system.namespaces don't currently have UUIDs in MMAP. - // SERVER-29926 and SERVER-30095 will address this problem. - if (isMmapV1 && (coll->ns().coll() == "system.indexes" || - coll->ns().coll() == "system.namespaces")) { - continue; - } - - // We expect all collections to have UUIDs starting in FCV 3.6, so if we are missing - // a UUID then the user never upgraded to FCV 3.6 and this startup attempt is - // illegal. - return {ErrorCodes::MustDowngrade, mustDowngradeErrorMsg}; - } - } - } - NamespaceString fcvNss(FeatureCompatibilityVersion::kCollection); // If the admin database does not exist, create it. @@ -140,6 +117,56 @@ Status restoreMissingFeatureCompatibilityVersionDocument(OperationContext* opCtx return Status::OK(); } +/** + * Checks that all replicated collections in the given list of 'dbNames' have UUIDs. Returns a + * MustDowngrade error status if any do not. + * + * Additionally assigns UUIDs to any non-replicated collections that are missing UUIDs. + */ +Status ensureAllCollectionsHaveUUIDs(OperationContext* opCtx, + const std::vector<std::string>& dbNames) { + bool isMmapV1 = opCtx->getServiceContext()->getGlobalStorageEngine()->isMmapV1(); + std::vector<NamespaceString> nonReplicatedCollNSSsWithoutUUIDs; + for (const auto& dbName : dbNames) { + Database* db = dbHolder().openDb(opCtx, dbName); + invariant(db); + for (auto collectionIt = db->begin(); collectionIt != db->end(); ++collectionIt) { + Collection* coll = *collectionIt; + if (!coll->uuid()) { + // system.indexes and system.namespaces don't currently have UUIDs in MMAP. + // SERVER-29926 and SERVER-30095 will address this problem. + if (isMmapV1 && (coll->ns().coll() == "system.indexes" || + coll->ns().coll() == "system.namespaces")) { + continue; + } + + if (!coll->ns().isReplicated()) { + nonReplicatedCollNSSsWithoutUUIDs.push_back(coll->ns()); + continue; + } + + // We expect all collections to have UUIDs starting in FCV 3.6, so if we are missing + // a UUID then the user never upgraded to FCV 3.6 and this startup attempt is + // illegal. + return {ErrorCodes::MustDowngrade, mustDowngradeErrorMsg}; + } + } + } + + // Non-replicated collections are very easy to fix since they don't require a replication or + // sharding solution. So, regardless of what the cause might have been, we go ahead and add + // UUIDs to them to ensure UUID dependent code works. + // + // Note: v3.6 arbiters do not have UUIDs, so this code is necessary to add them on upgrade to + // v4.0. + for (const auto& collNSS : nonReplicatedCollNSSsWithoutUUIDs) { + uassertStatusOK( + collModForUUIDUpgrade(opCtx, collNSS, BSON("collMod" << collNSS.coll()), UUID::gen())); + } + + return Status::OK(); +} + const NamespaceString startupLogCollectionName("local.startup_log"); const NamespaceString kSystemReplSetCollection("local.system.replset"); @@ -233,6 +260,8 @@ StatusWith<bool> repairDatabasesAndCheckVersion(OperationContext* opCtx) { std::vector<std::string> dbNames; storageEngine->listDatabases(&dbNames); + bool repairVerifiedAllCollectionsHaveUUIDs = false; + // Repair all databases first, so that we do not try to open them if they are in bad shape if (storageGlobalParams.repair) { invariant(!storageGlobalParams.readOnly); @@ -241,6 +270,14 @@ StatusWith<bool> repairDatabasesAndCheckVersion(OperationContext* opCtx) { fassert(18506, repairDatabase(opCtx, storageEngine, dbName)); } + // All collections must have UUIDs before restoring the FCV document to a version that + // requires UUIDs. + Status uuidsStatus = ensureAllCollectionsHaveUUIDs(opCtx, dbNames); + if (!uuidsStatus.isOK()) { + return uuidsStatus; + } + repairVerifiedAllCollectionsHaveUUIDs = true; + // Attempt to restore the featureCompatibilityVersion document if it is missing. NamespaceString nss(FeatureCompatibilityVersion::kCollection); @@ -259,6 +296,14 @@ StatusWith<bool> repairDatabasesAndCheckVersion(OperationContext* opCtx) { } } + // All collections must have UUIDs. + if (!repairVerifiedAllCollectionsHaveUUIDs) { + Status uuidsStatus = ensureAllCollectionsHaveUUIDs(opCtx, dbNames); + if (!uuidsStatus.isOK()) { + return uuidsStatus; + } + } + const repl::ReplSettings& replSettings = repl::ReplicationCoordinator::get(opCtx)->getSettings(); @@ -319,9 +364,6 @@ StatusWith<bool> repairDatabasesAndCheckVersion(OperationContext* opCtx) { !(checkIfReplMissingFromCommandLine(opCtx) || replSettings.usingReplSets() || replSettings.isSlave()); - // To check whether we are upgrading to 3.6 or have already upgraded to 3.6. - bool collsHaveUuids = false; - // To check whether a featureCompatibilityVersion document exists. bool fcvDocumentExists = false; @@ -417,15 +459,6 @@ StatusWith<bool> repairDatabasesAndCheckVersion(OperationContext* opCtx) { } } - // Iterate through collections and check for UUIDs. - for (auto collectionIt = db->begin(); !collsHaveUuids && collectionIt != db->end(); - ++collectionIt) { - Collection* coll = *collectionIt; - if (coll->uuid()) { - collsHaveUuids = true; - } - } - // Major versions match, check indexes const NamespaceString systemIndexes(db->name(), "system.indexes"); @@ -482,21 +515,16 @@ StatusWith<bool> repairDatabasesAndCheckVersion(OperationContext* opCtx) { // Fail to start up if there is no featureCompatibilityVersion document and there are non-local // databases present. if (!fcvDocumentExists && nonLocalDatabases) { - if (collsHaveUuids) { - severe() - << "Unable to start up mongod due to missing featureCompatibilityVersion document."; - if (opCtx->getServiceContext()->getGlobalStorageEngine()->isMmapV1()) { - severe() - << "Please run with --journalOptions " - << static_cast<int>(MMAPV1Options::JournalRecoverOnly) - << " to recover the journal. Then run with --repair to restore the document."; - } else { - severe() << "Please run with --repair to restore the document."; - } - fassertFailedNoTrace(40652); + severe() + << "Unable to start up mongod due to missing featureCompatibilityVersion document."; + if (opCtx->getServiceContext()->getGlobalStorageEngine()->isMmapV1()) { + severe() << "Please run with --journalOptions " + << static_cast<int>(MMAPV1Options::JournalRecoverOnly) + << " to recover the journal. Then run with --repair to restore the document."; } else { - return {ErrorCodes::MustDowngrade, mustDowngradeErrorMsg}; + severe() << "Please run with --repair to restore the document."; } + fassertFailedNoTrace(40652); } LOG(1) << "done repairDatabases"; |