summaryrefslogtreecommitdiff
path: root/src/mongo/db/startup_recovery.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/startup_recovery.cpp')
-rw-r--r--src/mongo/db/startup_recovery.cpp154
1 files changed, 33 insertions, 121 deletions
diff --git a/src/mongo/db/startup_recovery.cpp b/src/mongo/db/startup_recovery.cpp
index ee4ad04374e..ca1b6fb94e0 100644
--- a/src/mongo/db/startup_recovery.cpp
+++ b/src/mongo/db/startup_recovery.cpp
@@ -42,10 +42,9 @@
#include "mongo/db/commands/feature_compatibility_version_document_gen.h"
#include "mongo/db/commands/feature_compatibility_version_documentation.h"
#include "mongo/db/commands/feature_compatibility_version_parser.h"
-#include "mongo/db/concurrency/exception_util.h"
+#include "mongo/db/concurrency/write_conflict_exception.h"
#include "mongo/db/db_raii.h"
#include "mongo/db/dbhelpers.h"
-#include "mongo/db/exec/scoped_timer.h"
#include "mongo/db/index_builds_coordinator.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
@@ -55,7 +54,6 @@
#include "mongo/db/repl_set_member_in_standalone_mode.h"
#include "mongo/db/server_options.h"
#include "mongo/db/storage/storage_repair_observer.h"
-#include "mongo/db/timeseries/timeseries_extended_range.h"
#include "mongo/logv2/log.h"
#include "mongo/util/exit.h"
#include "mongo/util/fail_point.h"
@@ -80,11 +78,7 @@ bool isWriteableStorageEngine() {
}
// Attempt to restore the featureCompatibilityVersion document if it is missing.
-// The optional parameter `startupTimeElapsedBuilder` is for adding time elapsed of tasks done in
-// this function into one single builder that records the time elapsed during startup. Its default
-// value is nullptr because we only want to time this function when it is called during startup.
-Status restoreMissingFeatureCompatibilityVersionDocument(
- OperationContext* opCtx, BSONObjBuilder* startupTimeElapsedBuilder = nullptr) {
+Status restoreMissingFeatureCompatibilityVersionDocument(OperationContext* opCtx) {
NamespaceString fcvNss(NamespaceString::kServerConfigurationNamespace);
// If the admin database, which contains the server configuration collection with the
@@ -108,10 +102,6 @@ Status restoreMissingFeatureCompatibilityVersionDocument(
"Re-creating featureCompatibilityVersion document that was deleted. Creating new "
"document with last LTS version.",
"version"_attr = multiversion::toString(multiversion::GenericFCV::kLastLTS));
- auto scopedTimer =
- createTimeElapsedBuilderScopedTimer(opCtx->getServiceContext()->getFastClockSource(),
- "Create new fcv document",
- startupTimeElapsedBuilder);
uassertStatusOK(
createCollection(opCtx, fcvNss.db().toString(), BSON("create" << fcvNss.coll())));
}
@@ -126,10 +116,6 @@ Status restoreMissingFeatureCompatibilityVersionDocument(
fcvColl,
BSON("_id" << multiversion::kParameterName),
featureCompatibilityVersion)) {
- auto scopedTimer =
- createTimeElapsedBuilderScopedTimer(opCtx->getServiceContext()->getFastClockSource(),
- "Restore fcv document",
- startupTimeElapsedBuilder);
// (Generic FCV reference): This FCV reference should exist across LTS binary versions.
LOGV2(21000,
"Re-creating featureCompatibilityVersion document that was deleted. Creating new "
@@ -175,10 +161,6 @@ bool checkIdIndexExists(OperationContext* opCtx, const CollectionPtr& coll) {
Status buildMissingIdIndex(OperationContext* opCtx, Collection* collection) {
LOGV2(4805002, "Building missing _id index", logAttrs(*collection));
MultiIndexBlock indexer;
- // This method is called in startup recovery so we can safely build the id index in foreground
- // mode. This prevents us from yielding a MODE_X lock (which is disallowed).
- indexer.setIndexBuildMethod(IndexBuildMethod::kForeground);
-
ScopeGuard abortOnExit([&] {
CollectionWriter collWriter(collection);
indexer.abortIndexBuild(opCtx, collWriter, MultiIndexBlock::kNoopOnCleanUpFn);
@@ -231,7 +213,8 @@ Status ensureCollectionProperties(OperationContext* opCtx,
Database* db,
EnsureIndexPolicy ensureIndexPolicy) {
auto catalog = CollectionCatalog::get(opCtx);
- for (auto&& coll : catalog->range(db->name())) {
+ for (auto collIt = catalog->begin(opCtx, db->name()); collIt != catalog->end(opCtx); ++collIt) {
+ auto coll = *collIt;
if (!coll) {
break;
}
@@ -250,9 +233,7 @@ Status ensureCollectionProperties(OperationContext* opCtx,
"Collection is missing an _id index",
logAttrs(*coll.get()));
if (EnsureIndexPolicy::kBuildMissing == ensureIndexPolicy) {
- auto writableCollection =
- catalog->lookupCollectionByUUIDForMetadataWrite(opCtx, coll->uuid());
- auto status = buildMissingIdIndex(opCtx, writableCollection);
+ auto status = buildMissingIdIndex(opCtx, collIt.getWritableCollection(opCtx));
if (!status.isOK()) {
LOGV2_ERROR(21021,
"could not build an _id index on collection {coll_ns}: {error}",
@@ -265,11 +246,6 @@ Status ensureCollectionProperties(OperationContext* opCtx,
return downgradeError;
}
}
-
- if (coll->getTimeseriesOptions() &&
- timeseries::collectionMayRequireExtendedRangeSupport(opCtx, coll)) {
- coll->setRequiresTimeseriesExtendedRangeSupport(opCtx);
- }
}
return Status::OK();
}
@@ -358,25 +334,12 @@ void clearTempFilesExceptForResumableBuilds(const std::vector<ResumeIndexInfo>&
}
}
-// The optional parameter `startupTimeElapsedBuilder` is for adding time elapsed of tasks done in
-// this function into one single builder that records the time elapsed during startup. Its default
-// value is nullptr because we only want to time this function when it is called during startup.
void reconcileCatalogAndRebuildUnfinishedIndexes(
OperationContext* opCtx,
StorageEngine* storageEngine,
- StorageEngine::LastShutdownState lastShutdownState,
- BSONObjBuilder* startupTimeElapsedBuilder = nullptr) {
-
- StorageEngine::ReconcileResult reconcileResult;
- {
- auto scopedTimer = createTimeElapsedBuilderScopedTimer(
- opCtx->getServiceContext()->getFastClockSource(),
- "Drop abandoned idents and get back indexes that need to be rebuilt or builds that "
- "need to be restarted",
- startupTimeElapsedBuilder);
- reconcileResult =
- fassert(40593, storageEngine->reconcileCatalogAndIdents(opCtx, lastShutdownState));
- }
+ StorageEngine::LastShutdownState lastShutdownState) {
+ auto reconcileResult =
+ fassert(40593, storageEngine->reconcileCatalogAndIdents(opCtx, lastShutdownState));
auto tempDir = boost::filesystem::path(storageGlobalParams.dbpath).append("_tmp");
if (reconcileResult.indexBuildsToResume.empty() ||
@@ -424,27 +387,20 @@ void reconcileCatalogAndRebuildUnfinishedIndexes(
ino.second.emplace_back(std::move(indexesToRebuild.second.back()));
}
- {
- auto scopedTimer =
- createTimeElapsedBuilderScopedTimer(opCtx->getServiceContext()->getFastClockSource(),
- "Rebuild indexes for collections",
- startupTimeElapsedBuilder);
- for (const auto& entry : nsToIndexNameObjMap) {
- NamespaceString collNss(entry.first);
-
- auto collection = catalog->lookupCollectionByNamespace(opCtx, collNss);
- for (const auto& indexName : entry.second.first) {
- LOGV2(21004,
- "Rebuilding index. Collection: {collNss} Index: {indexName}",
- "Rebuilding index",
- "namespace"_attr = collNss,
- "index"_attr = indexName);
- }
+ for (const auto& entry : nsToIndexNameObjMap) {
+ NamespaceString collNss(entry.first);
- std::vector<BSONObj> indexSpecs = entry.second.second;
- fassert(40592,
- rebuildIndexesOnCollection(opCtx, collection, indexSpecs, RepairData::kNo));
+ auto collection = catalog->lookupCollectionByNamespace(opCtx, collNss);
+ for (const auto& indexName : entry.second.first) {
+ LOGV2(21004,
+ "Rebuilding index. Collection: {collNss} Index: {indexName}",
+ "Rebuilding index",
+ "namespace"_attr = collNss,
+ "index"_attr = indexName);
}
+
+ std::vector<BSONObj> indexSpecs = entry.second.second;
+ fassert(40592, rebuildIndexesOnCollection(opCtx, collection, indexSpecs, RepairData::kNo));
}
// Two-phase index builds depend on an eventually-replicated 'commitIndexBuild' oplog entry to
@@ -495,14 +451,8 @@ void setReplSetMemberInStandaloneMode(OperationContext* opCtx, StartupRecoveryMo
}
// Perform startup procedures for --repair mode.
-// The optional parameter `startupTimeElapsedBuilder` is for adding time elapsed of tasks done in
-// this function into one single builder that records the time elapsed during startup. Its default
-// value is nullptr because we only want to time this function when it is called during startup.
-void startupRepair(OperationContext* opCtx,
- StorageEngine* storageEngine,
- BSONObjBuilder* startupTimeElapsedBuilder = nullptr) {
+void startupRepair(OperationContext* opCtx, StorageEngine* storageEngine) {
invariant(!storageGlobalParams.readOnly);
- ServiceContext* svcCtx = opCtx->getServiceContext();
if (MONGO_unlikely(exitBeforeDataRepair.shouldFail())) {
LOGV2(21006, "Exiting because 'exitBeforeDataRepair' fail point was set.");
@@ -524,25 +474,15 @@ void startupRepair(OperationContext* opCtx,
opCtx, NamespaceString::kServerConfigurationNamespace)) {
auto databaseHolder = DatabaseHolder::get(opCtx);
- auto scopedTimer =
- createTimeElapsedBuilderScopedTimer(svcCtx->getFastClockSource(),
- "Repair server configuration namespace",
- startupTimeElapsedBuilder);
const TenantDatabaseName fcvTenantDbName(boost::none, fcvColl->ns().db());
databaseHolder->openDb(opCtx, fcvTenantDbName);
fassertNoTrace(4805000,
repair::repairCollection(
opCtx, storageEngine, NamespaceString::kServerConfigurationNamespace));
}
- uassertStatusOK(
- restoreMissingFeatureCompatibilityVersionDocument(opCtx, startupTimeElapsedBuilder));
-
- {
- auto scopedTimer = createTimeElapsedBuilderScopedTimer(
- svcCtx->getFastClockSource(), "Initialize FCV for startup", startupTimeElapsedBuilder);
- FeatureCompatibilityVersion::initializeForStartup(opCtx);
- abortRepairOnFCVErrors.dismiss();
- }
+ uassertStatusOK(restoreMissingFeatureCompatibilityVersionDocument(opCtx));
+ FeatureCompatibilityVersion::initializeForStartup(opCtx);
+ abortRepairOnFCVErrors.dismiss();
// The local database should be repaired before any other replicated collections so we know
// whether not to rebuild unfinished two-phase index builds if this is a replica set node
@@ -552,8 +492,6 @@ void startupRepair(OperationContext* opCtx,
tenantDbNames.end(),
TenantDatabaseName(boost::none, NamespaceString::kLocalDb));
it != tenantDbNames.end()) {
- auto scopedTimer = createTimeElapsedBuilderScopedTimer(
- svcCtx->getFastClockSource(), "Repair the local database", startupTimeElapsedBuilder);
fassertNoTrace(4805001, repair::repairDatabase(opCtx, storageEngine, *it));
// This must be set before rebuilding index builds on replicated collections.
@@ -561,14 +499,9 @@ void startupRepair(OperationContext* opCtx,
tenantDbNames.erase(it);
}
- {
- // Repair the remaining databases.
- auto scopedTimer = createTimeElapsedBuilderScopedTimer(svcCtx->getFastClockSource(),
- "Repair the remaining databases",
- startupTimeElapsedBuilder);
- for (const auto& tenantDbName : tenantDbNames) {
- fassertNoTrace(18506, repair::repairDatabase(opCtx, storageEngine, tenantDbName));
- }
+ // Repair the remaining databases.
+ for (const auto& tenantDbName : tenantDbNames) {
+ fassertNoTrace(18506, repair::repairDatabase(opCtx, storageEngine, tenantDbName));
}
openDatabases(opCtx, storageEngine, [&](auto db) {
@@ -621,35 +554,22 @@ void startupRecoveryReadOnly(OperationContext* opCtx, StorageEngine* storageEngi
}
// Perform routine startup recovery procedure.
-// The optional parameter `startupTimeElapsedBuilder` is for adding time elapsed of tasks done in
-// this function into one single builder that records the time elapsed during startup. Its default
-// value is nullptr because we only want to time this function when it is called during startup.
void startupRecovery(OperationContext* opCtx,
StorageEngine* storageEngine,
StorageEngine::LastShutdownState lastShutdownState,
- StartupRecoveryMode mode,
- BSONObjBuilder* startupTimeElapsedBuilder = nullptr) {
+ StartupRecoveryMode mode) {
invariant(!storageGlobalParams.readOnly && !storageGlobalParams.repair);
- ServiceContext* svcCtx = opCtx->getServiceContext();
-
// Determine whether this is a replica set node running in standalone mode. This must be set
// before determining whether to restart index builds.
setReplSetMemberInStandaloneMode(opCtx, mode);
// Initialize FCV before rebuilding indexes that may have features dependent on FCV.
- {
- auto scopedTimer =
- createTimeElapsedBuilderScopedTimer(svcCtx->getFastClockSource(),
- "Initialize FCV before rebuilding indexes",
- startupTimeElapsedBuilder);
- FeatureCompatibilityVersion::initializeForStartup(opCtx);
- }
+ FeatureCompatibilityVersion::initializeForStartup(opCtx);
// Drops abandoned idents. Rebuilds unfinished indexes and restarts incomplete two-phase
// index builds.
- reconcileCatalogAndRebuildUnfinishedIndexes(
- opCtx, storageEngine, lastShutdownState, startupTimeElapsedBuilder);
+ reconcileCatalogAndRebuildUnfinishedIndexes(opCtx, storageEngine, lastShutdownState);
const bool usingReplication = repl::ReplicationCoordinator::get(opCtx)->isReplEnabled();
@@ -689,13 +609,9 @@ namespace startup_recovery {
/**
* Recovers or repairs all databases from a previous shutdown. May throw a MustDowngrade error
* if data files are incompatible with the current binary version.
- * The optional parameter `startupTimeElapsedBuilder` is for adding time elapsed of tasks done in
- * this function into one single builder that records the time elapsed during startup. Its default
- * value is nullptr because we only want to time this function when it is called during startup.
*/
void repairAndRecoverDatabases(OperationContext* opCtx,
- StorageEngine::LastShutdownState lastShutdownState,
- BSONObjBuilder* startupTimeElapsedBuilder) {
+ StorageEngine::LastShutdownState lastShutdownState) {
auto const storageEngine = opCtx->getServiceContext()->getStorageEngine();
Lock::GlobalWrite lk(opCtx);
@@ -713,15 +629,11 @@ void repairAndRecoverDatabases(OperationContext* opCtx,
}
if (storageGlobalParams.repair) {
- startupRepair(opCtx, storageEngine, startupTimeElapsedBuilder);
+ startupRepair(opCtx, storageEngine);
} else if (storageGlobalParams.readOnly) {
startupRecoveryReadOnly(opCtx, storageEngine);
} else {
- startupRecovery(opCtx,
- storageEngine,
- lastShutdownState,
- StartupRecoveryMode::kAuto,
- startupTimeElapsedBuilder);
+ startupRecovery(opCtx, storageEngine, lastShutdownState, StartupRecoveryMode::kAuto);
}
}