From 0dae18bfa7ecba8820f032a0a53efa6cc02e4b0c Mon Sep 17 00:00:00 2001 From: Matthew Russotto Date: Wed, 18 May 2022 14:36:27 -0400 Subject: SERVER-65671 Use _termShadow in updateTerm and processReplSetMetadata --- src/mongo/db/repl/replication_coordinator_impl.cpp | 26 +++++++++++++++++----- src/mongo/db/repl/replication_coordinator_impl.h | 7 ++++++ 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'src/mongo/db/repl') diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index ca7b9e692c7..5c1e3eb8778 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -3369,13 +3369,15 @@ void ReplicationCoordinatorImpl::processReplSetGetConfig(BSONObjBuilder* result, void ReplicationCoordinatorImpl::processReplSetMetadata(const rpc::ReplSetMetadata& replMetadata) { EventHandle evh; - { - stdx::lock_guard lock(_mutex); - evh = _processReplSetMetadata_inlock(replMetadata); - } + if (_needToUpdateTerm(replMetadata.getTerm())) { + { + stdx::lock_guard lock(_mutex); + evh = _processReplSetMetadata_inlock(replMetadata); + } - if (evh) { - _replExecutor->waitForEvent(evh); + if (evh) { + _replExecutor->waitForEvent(evh); + } } } @@ -3386,6 +3388,9 @@ void ReplicationCoordinatorImpl::cancelAndRescheduleElectionTimeout() { EventHandle ReplicationCoordinatorImpl::_processReplSetMetadata_inlock( const rpc::ReplSetMetadata& replMetadata) { + // Note that public method processReplSetMetadata() above depends on this method not needing + // to do anything when the term is up to date. If that changes, be sure to update that + // method as well. return _updateTerm_inlock(replMetadata.getTerm()); } @@ -5902,6 +5907,11 @@ Status ReplicationCoordinatorImpl::updateTerm(OperationContext* opCtx, long long // Check we haven't acquired any lock, because potential stepdown needs global lock. dassert(!opCtx->lockState()->isLocked() || opCtx->lockState()->isNoop()); + + // If the term is already up to date, we can skip the update and the mutex acquisition. + if (!_needToUpdateTerm(term)) + return Status::OK(); + TopologyCoordinator::UpdateTermResult updateTermResult; EventHandle finishEvh; @@ -5923,6 +5933,10 @@ Status ReplicationCoordinatorImpl::updateTerm(OperationContext* opCtx, long long return Status::OK(); } +bool ReplicationCoordinatorImpl::_needToUpdateTerm(long long term) { + return term > _termShadow.load(); +} + EventHandle ReplicationCoordinatorImpl::_updateTerm_inlock( long long term, TopologyCoordinator::UpdateTermResult* updateTermResult) { diff --git a/src/mongo/db/repl/replication_coordinator_impl.h b/src/mongo/db/repl/replication_coordinator_impl.h index 7c6a70868e0..a6dc8fe9066 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.h +++ b/src/mongo/db/repl/replication_coordinator_impl.h @@ -1434,6 +1434,13 @@ private: */ void _updateLastCommittedOpTimeAndWallTime(WithLock lk); + /** Terms only increase, so if an incoming term is less than or equal to our + * current term (_termShadow), there is no need to take the mutex and call _updateTerm_inlock. + * Since _termShadow may be lagged, this may return true when the term does not need to be + * updated, which is harmless because _updateTerm_inlock will do nothing in that case. + */ + bool _needToUpdateTerm(long long term); + /** * Callback that attempts to set the current term in topology coordinator and * relinquishes primary if the term actually changes and we are primary. -- cgit v1.2.1