@@ -405,6 +405,7 @@ void ReplicationCoordinatorImpl::_finishLoadLocalConfig(
405405        _setCurrentRSConfig_inlock (cbData, localConfig, myIndex.getValue ());
406406    _setMyLastOptimeAndReport_inlock (&lk, lastOpTime, false );
407407    _externalState->setGlobalTimestamp (lastOpTime.getTimestamp ());
408+     //  Step down is impossible, so we don't need to wait for the returned event.
408409    _updateTerm_incallback (term);
409410    LOG (1 ) << " Current term is now "   << term;
410411    if  (lk.owns_lock ()) {
@@ -1724,22 +1725,27 @@ void ReplicationCoordinatorImpl::processReplSetGetConfig(BSONObjBuilder* result)
17241725}
17251726
17261727void  ReplicationCoordinatorImpl::processReplSetMetadata (const  rpc::ReplSetMetadata& replMetadata) {
1727-     _scheduleWorkAndWaitForCompletion (stdx::bind (
1728-         &ReplicationCoordinatorImpl::_processReplSetMetadata_incallback, this , replMetadata));
1728+     EventHandle evh;
1729+     _scheduleWorkAndWaitForCompletion ([this , &evh, &replMetadata](const  CallbackArgs& args) {
1730+         evh = _processReplSetMetadata_incallback (replMetadata);
1731+     });
1732+     if  (evh.isValid ()) {
1733+         _replExecutor.waitForEvent (evh);
1734+     }
17291735}
17301736
17311737void  ReplicationCoordinatorImpl::cancelAndRescheduleElectionTimeout () {
17321738    stdx::lock_guard<stdx::mutex> lock (_mutex);
17331739    _cancelAndRescheduleElectionTimeout_inlock ();
17341740}
17351741
1736- void  ReplicationCoordinatorImpl::_processReplSetMetadata_incallback (
1742+ EventHandle  ReplicationCoordinatorImpl::_processReplSetMetadata_incallback (
17371743    const  rpc::ReplSetMetadata& replMetadata) {
17381744    if  (replMetadata.getConfigVersion () != _rsConfig.getConfigVersion ()) {
1739-         return ;
1745+         return   EventHandle () ;
17401746    }
17411747    _setLastCommittedOpTime (replMetadata.getLastOpCommitted ());
1742-     _updateTerm_incallback (replMetadata.getTerm ());
1748+     return   _updateTerm_incallback (replMetadata.getTerm ());
17431749}
17441750
17451751bool  ReplicationCoordinatorImpl::getMaintenanceMode () {
@@ -1908,11 +1914,6 @@ Status ReplicationCoordinatorImpl::processHeartbeat(const ReplSetHeartbeatArgs&
19081914    }
19091915    fassert (18508 , cbh.getStatus ());
19101916    _replExecutor.wait (cbh.getValue ());
1911- 
1912-     //  Wait if heartbeat causes stepdown.
1913-     if  (_stepDownFinishedEvent.isValid ()) {
1914-         _replExecutor.waitForEvent (_stepDownFinishedEvent);
1915-     }
19161917    return  result;
19171918}
19181919
@@ -2849,12 +2850,6 @@ Status ReplicationCoordinatorImpl::processReplSetRequestVotes(
28492850    if  (!termStatus.isOK () && termStatus.code () != ErrorCodes::StaleTerm)
28502851        return  termStatus;
28512852
2852-     //  Term update may cause current primary step down, we need to wait until it
2853-     //  finishes so that it won't close our connection.
2854-     if  (_stepDownFinishedEvent.isValid ()) {
2855-         _replExecutor.waitForEvent (_stepDownFinishedEvent);
2856-     }
2857- 
28582853    Status result{ErrorCodes::InternalError, " didn't set status in processReplSetRequestVotes"  };
28592854    CBHStatus cbh = _replExecutor.scheduleWork (
28602855        stdx::bind (&ReplicationCoordinatorImpl::_processReplSetRequestVotes_finish,
@@ -2993,10 +2988,6 @@ Status ReplicationCoordinatorImpl::processHeartbeatV1(const ReplSetHeartbeatArgs
29932988    fassert (28645 , cbh.getStatus ());
29942989    _replExecutor.wait (cbh.getValue ());
29952990
2996-     //  Wait if heartbeat causes stepdown.
2997-     if  (_stepDownFinishedEvent.isValid ()) {
2998-         _replExecutor.waitForEvent (_stepDownFinishedEvent);
2999-     }
30002991    return  result;
30012992}
30022993
@@ -3084,65 +3075,80 @@ void ReplicationCoordinatorImpl::_getTerm_helper(const ReplicationExecutor::Call
30843075    *term = _topCoord->getTerm ();
30853076}
30863077
3087- StatusWith<ReplicationExecutor::CallbackHandle> ReplicationCoordinatorImpl::updateTerm_nonBlocking (
3088-     long  long  term, bool * updated) {
3078+ EventHandle ReplicationCoordinatorImpl::updateTerm_forTest (long  long  term, bool * updated) {
3079+     auto  finishEvhStatus = _replExecutor.makeEvent ();
3080+     invariantOK (finishEvhStatus.getStatus ());
3081+     EventHandle finishEvh = finishEvhStatus.getValue ();
3082+     auto  signalFinishEvent =
3083+         [this , finishEvh](const  CallbackArgs&) { this ->_replExecutor .signalEvent (finishEvh); };
3084+     auto  work = [this , term, updated, signalFinishEvent](const  CallbackArgs& args) {
3085+         auto  evh = _updateTerm_incallback (term, updated);
3086+         if  (evh.isValid ()) {
3087+             _replExecutor.onEvent (evh, signalFinishEvent);
3088+         } else  {
3089+             signalFinishEvent (args);
3090+         }
3091+     };
3092+     _scheduleWork (work);
3093+     return  finishEvh;
3094+ }
3095+ 
3096+ Status ReplicationCoordinatorImpl::updateTerm (long  long  term) {
30893097    //  Term is only valid if we are replicating.
30903098    if  (getReplicationMode () != modeReplSet) {
30913099        return  {ErrorCodes::BadValue, " cannot supply 'term' without active replication"  };
30923100    }
30933101
30943102    if  (!isV1ElectionProtocol ()) {
30953103        //  Do not update if not in V1 protocol.
3096-         return  ReplicationExecutor::CallbackHandle ();
3104+         return  Status::OK ();
30973105    }
30983106
3099-     auto  work =
3100-         [this , term, updated](const  CallbackArgs&) { *updated = _updateTerm_incallback (term); };
3101-     return  _scheduleWork (work);
3102- }
3103- 
3104- Status ReplicationCoordinatorImpl::updateTerm (long  long  term) {
31053107    bool  updated = false ;
3106-     auto  result = updateTerm_nonBlocking (term, &updated);
3107-     if  (!result.isOK ()) {
3108-         return  result.getStatus ();
3109-     }
3110-     auto  handle = result.getValue ();
3111-     if  (handle.isValid ()) {
3112-         _replExecutor.wait (handle);
3108+     EventHandle finishEvh;
3109+     auto  work = [this , term, &updated, &finishEvh](const  CallbackArgs&) {
3110+         finishEvh = _updateTerm_incallback (term, &updated);
3111+     };
3112+     _scheduleWorkAndWaitForCompletion (work);
3113+     //  Wait for potential stepdown to finish.
3114+     if  (finishEvh.isValid ()) {
3115+         _replExecutor.waitForEvent (finishEvh);
31133116    }
3114- 
31153117    if  (updated) {
31163118        return  {ErrorCodes::StaleTerm, " Replication term of this node was stale; retry query"  };
31173119    }
31183120
31193121    return  Status::OK ();
31203122}
31213123
3122- bool  ReplicationCoordinatorImpl::_updateTerm_incallback (long  long  term) {
3124+ EventHandle  ReplicationCoordinatorImpl::_updateTerm_incallback (long  long  term,  bool * updated ) {
31233125    if  (!isV1ElectionProtocol ()) {
31243126        LOG (3 ) << " Cannot update term in election protocol version 0"  ;
3125-         return  false ;
3127+         return  EventHandle () ;
31263128    }
31273129
31283130    auto  now = _replExecutor.now ();
3129-     bool  updated  = _topCoord->updateTerm (term, now);
3131+     bool  termUpdated  = _topCoord->updateTerm (term, now);
31303132    {
31313133        stdx::lock_guard<stdx::mutex> lock (_mutex);
31323134        _cachedTerm = _topCoord->getTerm ();
31333135
3134-         if  (updated ) {
3136+         if  (termUpdated ) {
31353137            _cancelPriorityTakeover_inlock ();
31363138            _cancelAndRescheduleElectionTimeout_inlock ();
31373139        }
31383140    }
31393141
3140-     if  (updated && getMemberState ().primary ()) {
3142+     if  (updated) {
3143+         *updated = termUpdated;
3144+     }
3145+ 
3146+     if  (termUpdated && getMemberState ().primary ()) {
31413147        log () << " stepping down from primary, because a new term has begun: "   << term;
31423148        _topCoord->prepareForStepDown ();
3143-         _stepDownStart ();
3149+         return   _stepDownStart ();
31443150    }
3145-     return  updated ;
3151+     return  EventHandle () ;
31463152}
31473153
31483154SnapshotName ReplicationCoordinatorImpl::reserveSnapshotName (OperationContext* txn) {
@@ -3246,12 +3252,6 @@ void ReplicationCoordinatorImpl::waitForElectionDryRunFinish_forTest() {
32463252    }
32473253}
32483254
3249- void  ReplicationCoordinatorImpl::waitForStepDownFinish_forTest () {
3250-     if  (_stepDownFinishedEvent.isValid ()) {
3251-         _replExecutor.waitForEvent (_stepDownFinishedEvent);
3252-     }
3253- }
3254- 
32553255void  ReplicationCoordinatorImpl::_resetElectionInfoOnProtocolVersionUpgrade (
32563256    const  ReplicaSetConfig& newConfig) {
32573257    //  On protocol version upgrade, reset last vote as if I just learned the term 0 from other
0 commit comments