summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/topology_coordinator_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/repl/topology_coordinator_impl.cpp')
-rw-r--r--src/mongo/db/repl/topology_coordinator_impl.cpp41
1 files changed, 27 insertions, 14 deletions
diff --git a/src/mongo/db/repl/topology_coordinator_impl.cpp b/src/mongo/db/repl/topology_coordinator_impl.cpp
index e245ddb3276..afd720d7869 100644
--- a/src/mongo/db/repl/topology_coordinator_impl.cpp
+++ b/src/mongo/db/repl/topology_coordinator_impl.cpp
@@ -2228,24 +2228,37 @@ void TopologyCoordinatorImpl::processLoseElection() {
}
}
-bool TopologyCoordinatorImpl::stepDown(Date_t until, bool force, const OpTime& lastOpApplied) {
- bool canStepDown = force;
- for (int i = 0; !canStepDown && i < _rsConfig.getNumMembers(); ++i) {
- if (i == _selfIndex) {
- continue;
- }
- UnelectableReasonMask reason = _getUnelectableReason(i, lastOpApplied);
- if (!reason && _hbdata[i].getAppliedOpTime() >= lastOpApplied) {
- canStepDown = true;
- }
+bool TopologyCoordinatorImpl::stepDown(Date_t until,
+ bool force,
+ const OpTime& lastOpApplied,
+ const OpTime& lastOpCommitted) {
+ // force==true overrides all other checks.
+ if (force) {
+ _stepDownUntil = until;
+ _stepDownSelfAndReplaceWith(-1);
+ return true;
}
- if (!canStepDown) {
+ // Ensure a majority of caught up nodes.
+ if (lastOpCommitted < lastOpApplied) {
return false;
}
- _stepDownUntil = until;
- _stepDownSelfAndReplaceWith(-1);
- return true;
+
+ // Now make sure we also have at least one caught up node that is also electable.
+ for (int memberIndex = 0; memberIndex < _rsConfig.getNumMembers(); memberIndex++) {
+ // ignore your self
+ if (memberIndex == _selfIndex) {
+ continue;
+ }
+ UnelectableReasonMask reason = _getUnelectableReason(memberIndex, lastOpApplied);
+ if (!reason && _hbdata.at(memberIndex).getAppliedOpTime() >= lastOpApplied) {
+ // Found a caught up and electable node, succeed with step down.
+ _stepDownUntil = until;
+ _stepDownSelfAndReplaceWith(-1);
+ return true;
+ }
+ }
+ return false;
}
void TopologyCoordinatorImpl::setFollowerMode(MemberState::MS newMode) {