summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Milkie <milkie@10gen.com>2017-11-10 11:12:23 -0500
committerEric Milkie <milkie@10gen.com>2017-11-13 12:54:15 -0500
commit9fbb130337619500dfe153bf3fc856d1852cc0ce (patch)
treeff3506b210c54eb455da08f794e38b2b3b3bdbe8
parent9a1f209aa8e47587af6ad81e991b101abea1f677 (diff)
downloadmongo-9fbb130337619500dfe153bf3fc856d1852cc0ce.tar.gz
SERVER-31899 make getTerm() use an Atomic rather than lock the replcoord mutex
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp11
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.h6
2 files changed, 15 insertions, 2 deletions
diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp
index 27a8a17e028..27a10f50e1b 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -354,6 +354,8 @@ ReplicationCoordinatorImpl::ReplicationCoordinatorImpl(
_storage(storage),
_random(prngSeed) {
+ _termShadow.store(OpTime::kUninitializedTerm);
+
invariant(_service);
if (!isReplEnabled()) {
@@ -2825,6 +2827,10 @@ ReplicationCoordinatorImpl::_setCurrentRSConfig_inlock(OperationContext* opCtx,
_setConfigState_inlock(kConfigSteady);
_topCoord->updateConfig(newConfig, myIndex, _replExecutor->now());
+
+ // updateConfig() can change terms, so update our term shadow to match.
+ _termShadow.store(_topCoord->getTerm());
+
const ReplSetConfig oldConfig = _rsConfig;
_rsConfig = newConfig;
_protVersion.store(_rsConfig.getProtocolVersion());
@@ -3384,8 +3390,8 @@ void ReplicationCoordinatorImpl::summarizeAsHtml(ReplSetHtmlSummary* output) {
}
long long ReplicationCoordinatorImpl::getTerm() {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
- return _topCoord->getTerm();
+ // Note: no mutex acquisition here, as we are reading an Atomic variable.
+ return _termShadow.load();
}
EventHandle ReplicationCoordinatorImpl::updateTerm_forTest(
@@ -3447,6 +3453,7 @@ EventHandle ReplicationCoordinatorImpl::_updateTerm_inlock(
TopologyCoordinator::UpdateTermResult localUpdateTermResult = _topCoord->updateTerm(term, now);
{
if (localUpdateTermResult == TopologyCoordinator::UpdateTermResult::kUpdatedTerm) {
+ _termShadow.store(term);
_cancelPriorityTakeover_inlock();
_cancelAndRescheduleElectionTimeout_inlock();
}
diff --git a/src/mongo/db/repl/replication_coordinator_impl.h b/src/mongo/db/repl/replication_coordinator_impl.h
index bacbfda9fe3..69b57830d69 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.h
+++ b/src/mongo/db/repl/replication_coordinator_impl.h
@@ -1341,6 +1341,12 @@ private:
// The catchup state including all catchup logic. The presence of a non-null pointer indicates
// that the node is currently in catchup mode.
std::unique_ptr<CatchupState> _catchupState; // (X)
+
+ // Atomic-synchronized copy of Topology Coordinator's _term, for use by the public getTerm()
+ // function.
+ // This variable must be written immediately after _term, and thus its value can lag.
+ // Reading this value does not require the replication coordinator mutex to be locked.
+ AtomicInt64 _termShadow; // (S)
};
} // namespace repl