diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/commands/shutdown.h | 3 | ||||
-rw-r--r-- | src/mongo/db/commands/shutdown_d.cpp | 38 | ||||
-rw-r--r-- | src/mongo/db/db.cpp | 27 |
3 files changed, 40 insertions, 28 deletions
diff --git a/src/mongo/db/commands/shutdown.h b/src/mongo/db/commands/shutdown.h index c8686afc99e..e3725619f96 100644 --- a/src/mongo/db/commands/shutdown.h +++ b/src/mongo/db/commands/shutdown.h @@ -35,6 +35,9 @@ #include "mongo/db/jsobj.h" namespace mongo { +Status stepDownForShutdown(OperationContext* opCtx, + const Milliseconds& waitTime, + bool forceShutdown) noexcept; class CmdShutdown : public BasicCommand { public: diff --git a/src/mongo/db/commands/shutdown_d.cpp b/src/mongo/db/commands/shutdown_d.cpp index b6d8154c999..5bf404f682e 100644 --- a/src/mongo/db/commands/shutdown_d.cpp +++ b/src/mongo/db/commands/shutdown_d.cpp @@ -35,8 +35,37 @@ #include "mongo/db/commands/shutdown.h" #include "mongo/db/repl/replication_coordinator.h" +#include "mongo/db/s/transaction_coordinator_service.h" +#include "mongo/util/log.h" namespace mongo { + +Status stepDownForShutdown(OperationContext* opCtx, + const Milliseconds& waitTime, + bool forceShutdown) noexcept { + auto replCoord = repl::ReplicationCoordinator::get(opCtx); + // If this is a single node replica set, then we don't have to wait + // for any secondaries. Ignore stepdown. + if (replCoord->getConfig().getNumMembers() != 1) { + try { + replCoord->stepDown(opCtx, false /* force */, waitTime, Seconds(120)); + } catch (const ExceptionFor<ErrorCodes::NotMaster>&) { + // Ignore not master errors. + } catch (const DBException& e) { + if (!forceShutdown) { + return e.toStatus(); + } + // Ignore stepDown errors on force shutdown. + log() << "Error stepping down during force shutdown " << e.toStatus(); + } + + // Even if the ReplicationCoordinator failed to step down, ensure we still shut down the + // TransactionCoordinatorService (see SERVER-45009) + TransactionCoordinatorService::get(opCtx)->onStepDown(); + } + return Status::OK(); +} + namespace { class CmdShutdownMongoD : public CmdShutdown { @@ -61,14 +90,7 @@ public: timeoutSecs = cmdObj["timeoutSecs"].numberLong(); } - try { - repl::ReplicationCoordinator::get(opCtx)->stepDown( - opCtx, force, Seconds(timeoutSecs), Seconds(120)); - } catch (const DBException& e) { - if (e.code() != ErrorCodes::NotMaster) { // ignore not master - throw; - } - } + uassertStatusOK(stepDownForShutdown(opCtx, Seconds(timeoutSecs), force)); // Never returns shutdownHelper(cmdObj); diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index 4d20f50a16f..4cbafa15ee9 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -62,6 +62,7 @@ #include "mongo/db/clientcursor.h" #include "mongo/db/commands/feature_compatibility_version.h" #include "mongo/db/commands/feature_compatibility_version_gen.h" +#include "mongo/db/commands/shutdown.h" #include "mongo/db/concurrency/d_concurrency.h" #include "mongo/db/concurrency/flow_control_ticketholder.h" #include "mongo/db/concurrency/lock_state.h" @@ -928,26 +929,12 @@ void shutdownTask(const ShutdownTaskArgs& shutdownArgs) { opCtx = uniqueOpCtx.get(); } - // If this is a single node replica set, then we don't have to wait - // for any secondaries. Ignore stepdown. - if (repl::ReplicationCoordinator::get(serviceContext)->getConfig().getNumMembers() != 1) { - try { - // For faster tests, we allow a short wait time with setParameter. - auto waitTime = repl::waitForStepDownOnNonCommandShutdown.load() - ? Milliseconds(Seconds(10)) - : Milliseconds(100); - replCoord->stepDown(opCtx, false /* force */, waitTime, Seconds(120)); - } catch (const ExceptionFor<ErrorCodes::NotMaster>&) { - // ignore not master errors - } catch (const DBException& e) { - log() << "Failed to stepDown in non-command initiated shutdown path " - << e.toString(); - } - - // Even if the replCoordinator failed to step down, ensure we still shut down the - // TransactionCoordinatorService (see SERVER-45009) - TransactionCoordinatorService::get(serviceContext)->onStepDown(); - } + // For faster tests, we allow a short wait time with setParameter. + auto waitTime = repl::waitForStepDownOnNonCommandShutdown.load() ? Milliseconds(Seconds(10)) + : Milliseconds(100); + const auto forceShutdown = true; + // stepDown should never return an error during force shutdown. + invariant(stepDownForShutdown(opCtx, waitTime, forceShutdown).isOK()); } WaitForMajorityService::get(serviceContext).shutDown(); |