summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorDianna Hohensee <dianna.hohensee@10gen.com>2018-02-09 17:07:01 -0500
committerDianna Hohensee <dianna.hohensee@10gen.com>2018-02-26 10:08:11 -0500
commitbebdcf721eaa24fa589977bf48459a8cdd0fb2a2 (patch)
tree2ad878b058af53ab5f6c796787af9fe2f28b94fd /src/mongo
parent67d04f1a286b23ea824bdfb7042462d7da1b515d (diff)
downloadmongo-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.cpp124
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";