From 9f52be8cf511d4fe0b2aa8eb20e18c47a5bf097d Mon Sep 17 00:00:00 2001 From: Lingzhi Deng Date: Tue, 13 Oct 2020 15:08:52 -0400 Subject: SERVER-50949: Return empty JournalListener token during rollback --- src/mongo/db/repl/replication_coordinator.h | 7 ++++++- .../repl/replication_coordinator_external_state_impl.cpp | 15 +++++++++++++-- src/mongo/db/repl/replication_coordinator_impl.cpp | 6 +++++- src/mongo/db/repl/replication_coordinator_impl.h | 3 ++- src/mongo/db/repl/replication_coordinator_mock.cpp | 7 +++++-- src/mongo/db/repl/replication_coordinator_mock.h | 2 +- src/mongo/db/repl/replication_coordinator_noop.cpp | 3 ++- src/mongo/db/repl/replication_coordinator_noop.h | 2 +- src/mongo/embedded/replication_coordinator_embedded.cpp | 3 ++- src/mongo/embedded/replication_coordinator_embedded.h | 3 ++- 10 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/mongo/db/repl/replication_coordinator.h b/src/mongo/db/repl/replication_coordinator.h index e4f9db71181..5338ab09abd 100644 --- a/src/mongo/db/repl/replication_coordinator.h +++ b/src/mongo/db/repl/replication_coordinator.h @@ -408,8 +408,13 @@ public: /* * Returns the same as getMyLastAppliedOpTime() and additionally returns the wall clock time * corresponding to that OpTime. + * + * When rollbackSafe is true, this returns an empty OpTimeAndWallTime if the node is in ROLLBACK + * state. The lastAppliedOpTime during ROLLBACK might be temporarily pointing to an oplog entry + * in the divergent branch of history which would become invalid after the rollback finishes. */ - virtual OpTimeAndWallTime getMyLastAppliedOpTimeAndWallTime() const = 0; + virtual OpTimeAndWallTime getMyLastAppliedOpTimeAndWallTime( + bool rollbackSafe = false) const = 0; /** * Returns the last optime recorded by setMyLastDurableOpTime. diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp index feef90d04e8..5ecb4f7297b 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp @@ -1079,8 +1079,19 @@ JournalListener::Token ReplicationCoordinatorExternalStateImpl::getToken(Operati } } - // All other repl states use the last applied. - return repl::ReplicationCoordinator::get(_service)->getMyLastAppliedOpTimeAndWallTime(); + // All other repl states use the 'lastApplied'. + // + // Setting 'rollbackSafe' will ensure that a safe lastApplied value is returned if we're in + // ROLLBACK state. 'lastApplied' may be momentarily set to an opTime from a divergent branch of + // history during rollback, so a benign default value will be returned instead to prevent a + // divergent 'lastApplied' from being used to forward the 'lastDurable' after rollback. + // + // No concurrency control is necessary and it is still safe if the node goes into ROLLBACK after + // getting the token because the JournalFlusher is shut down during rollback, before a divergent + // 'lastApplied' value is present. The JournalFlusher will start up again in ROLLBACK and never + // transition from non-ROLLBACK to ROLLBACK with a divergent 'lastApplied' value. + return repl::ReplicationCoordinator::get(_service)->getMyLastAppliedOpTimeAndWallTime( + /*rollbackSafe=*/true); } void ReplicationCoordinatorExternalStateImpl::onDurable(const JournalListener::Token& token) { diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index 564744ca4dd..8db38fa5803 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -1413,8 +1413,12 @@ OpTime ReplicationCoordinatorImpl::getMyLastAppliedOpTime() const { return _getMyLastAppliedOpTime_inlock(); } -OpTimeAndWallTime ReplicationCoordinatorImpl::getMyLastAppliedOpTimeAndWallTime() const { +OpTimeAndWallTime ReplicationCoordinatorImpl::getMyLastAppliedOpTimeAndWallTime( + bool rollbackSafe) const { stdx::lock_guard lock(_mutex); + if (rollbackSafe && _getMemberState_inlock().rollback()) { + return {}; + } return _getMyLastAppliedOpTimeAndWallTime_inlock(); } diff --git a/src/mongo/db/repl/replication_coordinator_impl.h b/src/mongo/db/repl/replication_coordinator_impl.h index dac623362a5..10437a4467f 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.h +++ b/src/mongo/db/repl/replication_coordinator_impl.h @@ -184,7 +184,8 @@ public: virtual void setMyHeartbeatMessage(const std::string& msg); virtual OpTime getMyLastAppliedOpTime() const override; - virtual OpTimeAndWallTime getMyLastAppliedOpTimeAndWallTime() const override; + virtual OpTimeAndWallTime getMyLastAppliedOpTimeAndWallTime( + bool rollbackSafe = false) const override; virtual OpTime getMyLastDurableOpTime() const override; virtual OpTimeAndWallTime getMyLastDurableOpTimeAndWallTime() const override; diff --git a/src/mongo/db/repl/replication_coordinator_mock.cpp b/src/mongo/db/repl/replication_coordinator_mock.cpp index d55e79b67b5..c77cfbe570e 100644 --- a/src/mongo/db/repl/replication_coordinator_mock.cpp +++ b/src/mongo/db/repl/replication_coordinator_mock.cpp @@ -274,9 +274,12 @@ void ReplicationCoordinatorMock::resetMyLastOpTimes() { _myLastDurableWallTime = Date_t(); } -OpTimeAndWallTime ReplicationCoordinatorMock::getMyLastAppliedOpTimeAndWallTime() const { +OpTimeAndWallTime ReplicationCoordinatorMock::getMyLastAppliedOpTimeAndWallTime( + bool rollbackSafe) const { stdx::lock_guard lk(_mutex); - + if (rollbackSafe && _memberState.rollback()) { + return {}; + } return {_myLastAppliedOpTime, _myLastAppliedWallTime}; } diff --git a/src/mongo/db/repl/replication_coordinator_mock.h b/src/mongo/db/repl/replication_coordinator_mock.h index 13d85b97ed1..d7d74471e45 100644 --- a/src/mongo/db/repl/replication_coordinator_mock.h +++ b/src/mongo/db/repl/replication_coordinator_mock.h @@ -149,7 +149,7 @@ public: virtual void setMyHeartbeatMessage(const std::string& msg); - virtual OpTimeAndWallTime getMyLastAppliedOpTimeAndWallTime() const; + virtual OpTimeAndWallTime getMyLastAppliedOpTimeAndWallTime(bool rollbackSafe) const; virtual OpTime getMyLastAppliedOpTime() const; virtual OpTimeAndWallTime getMyLastDurableOpTimeAndWallTime() const; diff --git a/src/mongo/db/repl/replication_coordinator_noop.cpp b/src/mongo/db/repl/replication_coordinator_noop.cpp index ac3433eff02..e23efe39bd9 100644 --- a/src/mongo/db/repl/replication_coordinator_noop.cpp +++ b/src/mongo/db/repl/replication_coordinator_noop.cpp @@ -135,7 +135,8 @@ bool ReplicationCoordinatorNoOp::buildsIndexes() { MONGO_UNREACHABLE; } -OpTimeAndWallTime ReplicationCoordinatorNoOp::getMyLastAppliedOpTimeAndWallTime() const { +OpTimeAndWallTime ReplicationCoordinatorNoOp::getMyLastAppliedOpTimeAndWallTime( + bool rollbackSafe) const { MONGO_UNREACHABLE; } diff --git a/src/mongo/db/repl/replication_coordinator_noop.h b/src/mongo/db/repl/replication_coordinator_noop.h index 6cc54cb6664..22a91e840e9 100644 --- a/src/mongo/db/repl/replication_coordinator_noop.h +++ b/src/mongo/db/repl/replication_coordinator_noop.h @@ -131,7 +131,7 @@ public: void setMyHeartbeatMessage(const std::string&) final; OpTime getMyLastAppliedOpTime() const final; - OpTimeAndWallTime getMyLastAppliedOpTimeAndWallTime() const final; + OpTimeAndWallTime getMyLastAppliedOpTimeAndWallTime(bool rollbackSafe = false) const final; OpTime getMyLastDurableOpTime() const final; OpTimeAndWallTime getMyLastDurableOpTimeAndWallTime() const final; diff --git a/src/mongo/embedded/replication_coordinator_embedded.cpp b/src/mongo/embedded/replication_coordinator_embedded.cpp index 72b956887ca..b92deb55c45 100644 --- a/src/mongo/embedded/replication_coordinator_embedded.cpp +++ b/src/mongo/embedded/replication_coordinator_embedded.cpp @@ -228,7 +228,8 @@ void ReplicationCoordinatorEmbedded::resetMyLastOpTimes() { UASSERT_NOT_IMPLEMENTED; } -OpTimeAndWallTime ReplicationCoordinatorEmbedded::getMyLastAppliedOpTimeAndWallTime() const { +OpTimeAndWallTime ReplicationCoordinatorEmbedded::getMyLastAppliedOpTimeAndWallTime( + bool rollbackSafe) const { UASSERT_NOT_IMPLEMENTED; } diff --git a/src/mongo/embedded/replication_coordinator_embedded.h b/src/mongo/embedded/replication_coordinator_embedded.h index 502333a0b6b..15ab7521b1b 100644 --- a/src/mongo/embedded/replication_coordinator_embedded.h +++ b/src/mongo/embedded/replication_coordinator_embedded.h @@ -139,7 +139,8 @@ public: void setMyHeartbeatMessage(const std::string&) override; repl::OpTime getMyLastAppliedOpTime() const override; - repl::OpTimeAndWallTime getMyLastAppliedOpTimeAndWallTime() const override; + repl::OpTimeAndWallTime getMyLastAppliedOpTimeAndWallTime( + bool rollbackSafe = false) const override; repl::OpTime getMyLastDurableOpTime() const override; repl::OpTimeAndWallTime getMyLastDurableOpTimeAndWallTime() const override; -- cgit v1.2.1