diff options
-rw-r--r-- | jstests/noPassthrough/minvalid.js | 4 | ||||
-rw-r--r-- | jstests/noPassthrough/minvalid2.js | 8 | ||||
-rw-r--r-- | jstests/replsets/apply_batch_only_goes_forward.js | 5 | ||||
-rw-r--r-- | src/mongo/db/repl/SConscript | 13 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_consistency_markers.h | 6 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_consistency_markers.idl | 65 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_consistency_markers_impl.cpp | 133 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_consistency_markers_impl.h | 10 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_consistency_markers_impl_test.cpp | 21 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_consistency_markers_mock.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_consistency_markers_mock.h | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl.cpp | 2 |
12 files changed, 208 insertions, 75 deletions
diff --git a/jstests/noPassthrough/minvalid.js b/jstests/noPassthrough/minvalid.js index d31f6d58da7..c39b51aa1be 100644 --- a/jstests/noPassthrough/minvalid.js +++ b/jstests/noPassthrough/minvalid.js @@ -22,9 +22,7 @@ printjson(lastOp); print("3: change minvalid"); assert.writeOK(local.replset.minvalid.update( - {}, - {$set: {ts: new Timestamp(lastOp.ts.t, lastOp.ts.i + 1), h: new NumberLong("1234567890")}}, - {upsert: true})); + {}, {$set: {ts: new Timestamp(lastOp.ts.t, lastOp.ts.i + 1)}}, {upsert: true})); printjson(local.replset.minvalid.findOne()); print("4: restart"); diff --git a/jstests/noPassthrough/minvalid2.js b/jstests/noPassthrough/minvalid2.js index f51a1430490..12f5f9f4046 100644 --- a/jstests/noPassthrough/minvalid2.js +++ b/jstests/noPassthrough/minvalid2.js @@ -60,8 +60,12 @@ printjson(lastOp); // Overwrite minvalid document to simulate an inconsistent state (as might result from a server // crash. -local.replset.minvalid.update( - {}, {ts: new Timestamp(lastOp.ts.t, lastOp.ts.i + 1)}, {upsert: true}); +local.replset.minvalid.update({}, + { + ts: new Timestamp(lastOp.ts.t, lastOp.ts.i + 1), + t: NumberLong(-1), + }, + {upsert: true}); printjson(local.replset.minvalid.findOne()); print("5: shut down master"); diff --git a/jstests/replsets/apply_batch_only_goes_forward.js b/jstests/replsets/apply_batch_only_goes_forward.js index 509d91d1f12..4db9c825565 100644 --- a/jstests/replsets/apply_batch_only_goes_forward.js +++ b/jstests/replsets/apply_batch_only_goes_forward.js @@ -55,6 +55,11 @@ return member.self; })[0] .optime; + // Fix OpTime formatting for pv0. + if (primaryOpTime.ts === undefined) { + primaryOpTime = {ts: primaryOpTime, t: -1}; + } + jsTest.log("future TS: " + tojson(farFutureTS) + ", date:" + tsToDate(farFutureTS)); // We do an update in case there is a minvalid document on the primary already. // If the doc doesn't exist then upsert:true will create it, and the writeConcern ensures diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index 2bef90998b4..e96e12ed3fc 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -185,6 +185,18 @@ env.CppUnitTest( ) env.Library( + target='replication_consistency_markers_idl', + source=[ + env.Idlc('replication_consistency_markers.idl')[0], + ], + LIBDEPS=[ + 'optime', + '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/idl/idl_parser', + ], +) + +env.Library( target='replication_consistency_markers_impl', source=[ 'replication_consistency_markers_impl.cpp', @@ -192,6 +204,7 @@ env.Library( LIBDEPS=[ 'optime', 'repl_coordinator_impl', + 'replication_consistency_markers_idl', ], ) diff --git a/src/mongo/db/repl/replication_consistency_markers.h b/src/mongo/db/repl/replication_consistency_markers.h index d57f54960c6..d6cb43126cb 100644 --- a/src/mongo/db/repl/replication_consistency_markers.h +++ b/src/mongo/db/repl/replication_consistency_markers.h @@ -72,6 +72,12 @@ public: ReplicationConsistencyMarkers(); virtual ~ReplicationConsistencyMarkers(); + /** + * Initializes the minValid document with the required fields. This is safe to call on an + * already initialized minValid document and will add any required fields that do not exist. + */ + virtual void initializeMinValidDocument(OperationContext* opCtx) = 0; + // -------- Initial Sync Flag ---------- /** diff --git a/src/mongo/db/repl/replication_consistency_markers.idl b/src/mongo/db/repl/replication_consistency_markers.idl new file mode 100644 index 00000000000..770b950ab33 --- /dev/null +++ b/src/mongo/db/repl/replication_consistency_markers.idl @@ -0,0 +1,65 @@ +# Copyright (C) 2017 MongoDB Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License, version 3, +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# As a special exception, the copyright holders give permission to link the +# code of portions of this program with the OpenSSL library under certain +# conditions as described in each individual source file and distribute +# linked combinations including the program with the OpenSSL library. You +# must comply with the GNU Affero General Public License in all respects for +# all of the code used other than as permitted herein. If you modify file(s) +# with this exception, you may extend this exception to your version of the +# file(s), but you are not obligated to do so. If you do not wish to do so, +# delete this exception statement from your version. If you delete this +# exception statement from all source files in the program, then also delete +# it in the license file. + +# Replication Consistency Markers IDL File + +global: + cpp_namespace: "mongo::repl" + +imports: + - "mongo/idl/basic_types.idl" + - "mongo/db/repl/replication_types.idl" + +structs: + MinValidDocument: + description: A document in which the server stores its minValid and appliedThrough information. + fields: + ts: + cpp_name: minValidTimestamp + type: timestamp + description: "The timestamp for the OpTime at which the data on disk will be consistent" + t: + cpp_name: minValidTerm + type: safeInt64 + description: "The term for the OpTime at which the data on disk will be consistent; -1 for PV0." + oplogDeleteFromPoint: + type: timestamp + optional: true + description: "The timestamp of the first oplog entry in a batch when we are writing oplog entries to the oplog after which the oplog may be inconsistent." + begin: + cpp_name: appliedThrough + type: optime + optional: true # This field is unset when we want to mark that we are consistent at the top of the oplog + description: "The OpTime of the last oplog entry we applied" + doingInitialSync: + cpp_name: initialSyncFlag + type: bool + optional: true # This field is unset when we are not doing initial sync + description: "A flag for if we are in the middle of initial sync" + _id: + type: objectid + optional: true # This is automatically created when the document is upserted + description: "An objectid that is not used but is automatically generated" diff --git a/src/mongo/db/repl/replication_consistency_markers_impl.cpp b/src/mongo/db/repl/replication_consistency_markers_impl.cpp index ec157379a74..6e262aa7b4a 100644 --- a/src/mongo/db/repl/replication_consistency_markers_impl.cpp +++ b/src/mongo/db/repl/replication_consistency_markers_impl.cpp @@ -44,13 +44,9 @@ namespace mongo { namespace repl { constexpr StringData ReplicationConsistencyMarkersImpl::kDefaultMinValidNamespace; -constexpr StringData ReplicationConsistencyMarkersImpl::kInitialSyncFlagFieldName; -constexpr StringData ReplicationConsistencyMarkersImpl::kBeginFieldName; -constexpr StringData ReplicationConsistencyMarkersImpl::kOplogDeleteFromPointFieldName; namespace { -const BSONObj kInitialSyncFlag(BSON(ReplicationConsistencyMarkersImpl::kInitialSyncFlagFieldName - << true)); +const BSONObj kInitialSyncFlag(BSON(MinValidDocument::kInitialSyncFlagFieldName << true)); } // namespace ReplicationConsistencyMarkersImpl::ReplicationConsistencyMarkersImpl( @@ -63,17 +59,21 @@ ReplicationConsistencyMarkersImpl::ReplicationConsistencyMarkersImpl( StorageInterface* storageInterface, NamespaceString minValidNss) : _storageInterface(storageInterface), _minValidNss(minValidNss) {} -BSONObj ReplicationConsistencyMarkersImpl::_getMinValidDocument(OperationContext* opCtx) const { +boost::optional<MinValidDocument> ReplicationConsistencyMarkersImpl::_getMinValidDocument( + OperationContext* opCtx) const { auto result = _storageInterface->findSingleton(opCtx, _minValidNss); if (!result.isOK()) { if (result.getStatus() == ErrorCodes::NamespaceNotFound || result.getStatus() == ErrorCodes::CollectionIsEmpty) { - return BSONObj(); + return boost::none; } // Fail if there is an error other than the collection being missing or being empty. fassertFailedWithStatus(40466, result.getStatus()); } - return result.getValue(); + + auto minValid = + MinValidDocument::parse(IDLParserErrorContext("MinValidDocument"), result.getValue()); + return minValid; } void ReplicationConsistencyMarkersImpl::_updateMinValidDocument(OperationContext* opCtx, @@ -91,11 +91,33 @@ void ReplicationConsistencyMarkersImpl::_updateMinValidDocument(OperationContext fassertStatusOK(40467, status); } +void ReplicationConsistencyMarkersImpl::initializeMinValidDocument(OperationContext* opCtx) { + LOG(3) << "Initializing minValid document"; + + // This initializes the values of the required fields if they are not already set. + // If one of the fields is already set, the $max will prefer the existing value since it + // will always be greater than the provided ones. + _updateMinValidDocument(opCtx, + BSON("$max" << BSON(MinValidDocument::kMinValidTimestampFieldName + << Timestamp() + << MinValidDocument::kMinValidTermFieldName + << OpTime::kUninitializedTerm + << MinValidDocument::kOplogDeleteFromPointFieldName + << Timestamp()))); +} + bool ReplicationConsistencyMarkersImpl::getInitialSyncFlag(OperationContext* opCtx) const { - const BSONObj doc = _getMinValidDocument(opCtx); - const auto flag = doc[kInitialSyncFlagFieldName].trueValue(); - LOG(3) << "returning initial sync flag value of " << flag; - return flag; + auto doc = _getMinValidDocument(opCtx); + invariant(doc); // Initialized at startup so it should never be missing. + + boost::optional<bool> flag = doc->getInitialSyncFlag(); + if (!flag) { + LOG(3) << "No initial sync flag set, returning initial sync flag value of false."; + return false; + } + + LOG(3) << "returning initial sync flag value of " << flag.get(); + return flag.get(); } void ReplicationConsistencyMarkersImpl::setInitialSyncFlag(OperationContext* opCtx) { @@ -109,12 +131,14 @@ void ReplicationConsistencyMarkersImpl::clearInitialSyncFlag(OperationContext* o auto replCoord = repl::ReplicationCoordinator::get(opCtx); OpTime time = replCoord->getMyLastAppliedOpTime(); - _updateMinValidDocument( - opCtx, - BSON("$unset" << kInitialSyncFlag << "$set" - << BSON("ts" << time.getTimestamp() << "t" << time.getTerm() - << kBeginFieldName - << time))); + _updateMinValidDocument(opCtx, + BSON("$unset" << kInitialSyncFlag << "$set" + << BSON(MinValidDocument::kMinValidTimestampFieldName + << time.getTimestamp() + << MinValidDocument::kMinValidTermFieldName + << time.getTerm() + << MinValidDocument::kAppliedThroughFieldName + << time))); if (getGlobalServiceContext()->getGlobalStorageEngine()->isDurable()) { opCtx->recoveryUnit()->waitUntilDurable(); @@ -123,21 +147,11 @@ void ReplicationConsistencyMarkersImpl::clearInitialSyncFlag(OperationContext* o } OpTime ReplicationConsistencyMarkersImpl::getMinValid(OperationContext* opCtx) const { - const BSONObj doc = _getMinValidDocument(opCtx); - const auto opTimeStatus = OpTime::parseFromOplogEntry(doc); - // If any of the keys (fields) are missing from the minvalid document, we return - // a null OpTime. - if (opTimeStatus == ErrorCodes::NoSuchKey) { - return {}; - } + auto doc = _getMinValidDocument(opCtx); + invariant(doc); // Initialized at startup so it should never be missing. - if (!opTimeStatus.isOK()) { - severe() << "Error parsing minvalid entry: " << redact(doc) - << ", with status:" << opTimeStatus.getStatus(); - fassertFailedNoTrace(40052); - } + auto minValid = OpTime(doc->getMinValidTimestamp(), doc->getMinValidTerm()); - OpTime minValid = opTimeStatus.getValue(); LOG(3) << "returning minvalid: " << minValid.toString() << "(" << minValid.toBSON() << ")"; return minValid; @@ -147,60 +161,71 @@ void ReplicationConsistencyMarkersImpl::setMinValid(OperationContext* opCtx, const OpTime& minValid) { LOG(3) << "setting minvalid to exactly: " << minValid.toString() << "(" << minValid.toBSON() << ")"; - _updateMinValidDocument( - opCtx, BSON("$set" << BSON("ts" << minValid.getTimestamp() << "t" << minValid.getTerm()))); + _updateMinValidDocument(opCtx, + BSON("$set" << BSON(MinValidDocument::kMinValidTimestampFieldName + << minValid.getTimestamp() + << MinValidDocument::kMinValidTermFieldName + << minValid.getTerm()))); } void ReplicationConsistencyMarkersImpl::setMinValidToAtLeast(OperationContext* opCtx, const OpTime& minValid) { LOG(3) << "setting minvalid to at least: " << minValid.toString() << "(" << minValid.toBSON() << ")"; - _updateMinValidDocument( - opCtx, BSON("$max" << BSON("ts" << minValid.getTimestamp() << "t" << minValid.getTerm()))); + _updateMinValidDocument(opCtx, + BSON("$max" << BSON(MinValidDocument::kMinValidTimestampFieldName + << minValid.getTimestamp() + << MinValidDocument::kMinValidTermFieldName + << minValid.getTerm()))); } void ReplicationConsistencyMarkersImpl::setOplogDeleteFromPoint(OperationContext* opCtx, const Timestamp& timestamp) { LOG(3) << "setting oplog delete from point to: " << timestamp.toStringPretty(); - _updateMinValidDocument(opCtx, - BSON("$set" << BSON(kOplogDeleteFromPointFieldName << timestamp))); + _updateMinValidDocument( + opCtx, BSON("$set" << BSON(MinValidDocument::kOplogDeleteFromPointFieldName << timestamp))); } Timestamp ReplicationConsistencyMarkersImpl::getOplogDeleteFromPoint( OperationContext* opCtx) const { - const BSONObj doc = _getMinValidDocument(opCtx); - Timestamp out = {}; - if (auto field = doc[kOplogDeleteFromPointFieldName]) { - out = field.timestamp(); + auto doc = _getMinValidDocument(opCtx); + invariant(doc); // Initialized at startup so it should never be missing. + + auto oplogDeleteFromPoint = doc->getOplogDeleteFromPoint(); + if (!oplogDeleteFromPoint) { + LOG(3) << "No oplogDeleteFromPoint timestamp set, returning empty timestamp."; + return Timestamp(); } - LOG(3) << "returning oplog delete from point: " << out; - return out; + LOG(3) << "returning oplog delete from point: " << oplogDeleteFromPoint.get(); + return oplogDeleteFromPoint.get(); } void ReplicationConsistencyMarkersImpl::setAppliedThrough(OperationContext* opCtx, const OpTime& optime) { LOG(3) << "setting appliedThrough to: " << optime.toString() << "(" << optime.toBSON() << ")"; if (optime.isNull()) { - _updateMinValidDocument(opCtx, BSON("$unset" << BSON(kBeginFieldName << 1))); + _updateMinValidDocument( + opCtx, BSON("$unset" << BSON(MinValidDocument::kAppliedThroughFieldName << 1))); } else { - _updateMinValidDocument(opCtx, BSON("$set" << BSON(kBeginFieldName << optime))); + _updateMinValidDocument( + opCtx, BSON("$set" << BSON(MinValidDocument::kAppliedThroughFieldName << optime))); } } OpTime ReplicationConsistencyMarkersImpl::getAppliedThrough(OperationContext* opCtx) const { - const BSONObj doc = _getMinValidDocument(opCtx); - const auto opTimeStatus = OpTime::parseFromOplogEntry(doc.getObjectField(kBeginFieldName)); - if (!opTimeStatus.isOK()) { - // Return null OpTime on any parse failure, including if "begin" is missing. + auto doc = _getMinValidDocument(opCtx); + invariant(doc); // Initialized at startup so it should never be missing. + + auto appliedThrough = doc->getAppliedThrough(); + if (!appliedThrough) { + LOG(3) << "No appliedThrough OpTime set, returning empty appliedThrough OpTime."; return {}; } + LOG(3) << "returning appliedThrough: " << appliedThrough->toString() << "(" + << appliedThrough->toBSON() << ")"; - OpTime appliedThrough = opTimeStatus.getValue(); - LOG(3) << "returning appliedThrough: " << appliedThrough.toString() << "(" - << appliedThrough.toBSON() << ")"; - - return appliedThrough; + return appliedThrough.get(); } } // namespace repl diff --git a/src/mongo/db/repl/replication_consistency_markers_impl.h b/src/mongo/db/repl/replication_consistency_markers_impl.h index fd8a6dc9d26..6ca4a315f5c 100644 --- a/src/mongo/db/repl/replication_consistency_markers_impl.h +++ b/src/mongo/db/repl/replication_consistency_markers_impl.h @@ -31,6 +31,7 @@ #include "mongo/base/disallow_copying.h" #include "mongo/db/namespace_string.h" #include "mongo/db/repl/replication_consistency_markers.h" +#include "mongo/db/repl/replication_consistency_markers_gen.h" namespace mongo { @@ -48,14 +49,13 @@ class ReplicationConsistencyMarkersImpl : public ReplicationConsistencyMarkers { public: static constexpr StringData kDefaultMinValidNamespace = "local.replset.minvalid"_sd; - static constexpr StringData kInitialSyncFlagFieldName = "doingInitialSync"_sd; - static constexpr StringData kBeginFieldName = "begin"_sd; - static constexpr StringData kOplogDeleteFromPointFieldName = "oplogDeleteFromPoint"_sd; explicit ReplicationConsistencyMarkersImpl(StorageInterface* storageInterface); ReplicationConsistencyMarkersImpl(StorageInterface* storageInterface, NamespaceString minValidNss); + void initializeMinValidDocument(OperationContext* opCtx) override; + bool getInitialSyncFlag(OperationContext* opCtx) const override; void setInitialSyncFlag(OperationContext* opCtx) override; void clearInitialSyncFlag(OperationContext* opCtx) override; @@ -73,9 +73,9 @@ public: private: /** * Reads the MinValid document from disk. - * Returns an empty document if not present. + * Returns boost::none if not present. */ - BSONObj _getMinValidDocument(OperationContext* opCtx) const; + boost::optional<MinValidDocument> _getMinValidDocument(OperationContext* opCtx) const; /** * Updates the MinValid document according to the provided update spec. If the collection does diff --git a/src/mongo/db/repl/replication_consistency_markers_impl_test.cpp b/src/mongo/db/repl/replication_consistency_markers_impl_test.cpp index 4762913ed41..179a792dd60 100644 --- a/src/mongo/db/repl/replication_consistency_markers_impl_test.cpp +++ b/src/mongo/db/repl/replication_consistency_markers_impl_test.cpp @@ -130,6 +130,7 @@ TEST_F(ReplicationConsistencyMarkersTest, InitialSyncFlag) { ReplicationConsistencyMarkersImpl minValid(getStorageInterface(), nss); auto opCtx = getOperationContext(); + minValid.initializeMinValidDocument(opCtx); // Initial sync flag should be unset after initializing a new storage engine. ASSERT_FALSE(minValid.getInitialSyncFlag(opCtx)); @@ -140,10 +141,8 @@ TEST_F(ReplicationConsistencyMarkersTest, InitialSyncFlag) { // Check min valid document using storage engine interface. auto minValidDocument = getMinValidDocument(opCtx, nss); - ASSERT_TRUE( - minValidDocument.hasField(ReplicationConsistencyMarkersImpl::kInitialSyncFlagFieldName)); - ASSERT_TRUE(minValidDocument.getBoolField( - ReplicationConsistencyMarkersImpl::kInitialSyncFlagFieldName)); + ASSERT_TRUE(minValidDocument.hasField(MinValidDocument::kInitialSyncFlagFieldName)); + ASSERT_TRUE(minValidDocument.getBoolField(MinValidDocument::kInitialSyncFlagFieldName)); // Clearing initial sync flag should affect getInitialSyncFlag() result. minValid.clearInitialSyncFlag(opCtx); @@ -155,6 +154,7 @@ TEST_F(ReplicationConsistencyMarkersTest, GetMinValidAfterSettingInitialSyncFlag ReplicationConsistencyMarkersImpl minValid(getStorageInterface(), nss); auto opCtx = getOperationContext(); + minValid.initializeMinValidDocument(opCtx); // Initial sync flag should be unset after initializing a new storage engine. ASSERT_FALSE(minValid.getInitialSyncFlag(opCtx)); @@ -173,6 +173,7 @@ TEST_F(ReplicationConsistencyMarkersTest, ReplicationConsistencyMarkers) { ReplicationConsistencyMarkersImpl minValid(getStorageInterface(), nss); auto opCtx = getOperationContext(); + minValid.initializeMinValidDocument(opCtx); // MinValid boundaries should all be null after initializing a new storage engine. ASSERT(minValid.getMinValid(opCtx).isNull()); @@ -200,16 +201,14 @@ TEST_F(ReplicationConsistencyMarkersTest, ReplicationConsistencyMarkers) { // Check min valid document using storage engine interface. auto minValidDocument = getMinValidDocument(opCtx, nss); - ASSERT_TRUE(minValidDocument.hasField(ReplicationConsistencyMarkersImpl::kBeginFieldName)); - ASSERT_TRUE(minValidDocument[ReplicationConsistencyMarkersImpl::kBeginFieldName].isABSONObj()); + ASSERT_TRUE(minValidDocument.hasField(MinValidDocument::kAppliedThroughFieldName)); + ASSERT_TRUE(minValidDocument[MinValidDocument::kAppliedThroughFieldName].isABSONObj()); ASSERT_EQUALS(startOpTime, unittest::assertGet(OpTime::parseFromOplogEntry( - minValidDocument[ReplicationConsistencyMarkersImpl::kBeginFieldName].Obj()))); + minValidDocument[MinValidDocument::kAppliedThroughFieldName].Obj()))); ASSERT_EQUALS(endOpTime, unittest::assertGet(OpTime::parseFromOplogEntry(minValidDocument))); - ASSERT_EQUALS( - endOpTime.getTimestamp(), - minValidDocument[ReplicationConsistencyMarkersImpl::kOplogDeleteFromPointFieldName] - .timestamp()); + ASSERT_EQUALS(endOpTime.getTimestamp(), + minValidDocument[MinValidDocument::kOplogDeleteFromPointFieldName].timestamp()); // Recovery unit will be owned by "opCtx". RecoveryUnitWithDurabilityTracking* recoveryUnit = new RecoveryUnitWithDurabilityTracking(); diff --git a/src/mongo/db/repl/replication_consistency_markers_mock.cpp b/src/mongo/db/repl/replication_consistency_markers_mock.cpp index 5fdd402d33b..e1c7afc0794 100644 --- a/src/mongo/db/repl/replication_consistency_markers_mock.cpp +++ b/src/mongo/db/repl/replication_consistency_markers_mock.cpp @@ -33,6 +33,20 @@ namespace mongo { namespace repl { +void ReplicationConsistencyMarkersMock::initializeMinValidDocument(OperationContext* opCtx) { + { + stdx::lock_guard<stdx::mutex> lock(_initialSyncFlagMutex); + _initialSyncFlag = false; + } + + { + stdx::lock_guard<stdx::mutex> lock(_minValidBoundariesMutex); + _minValid = {}; + _oplogDeleteFromPoint = {}; + _appliedThrough = {}; + } +} + bool ReplicationConsistencyMarkersMock::getInitialSyncFlag(OperationContext* opCtx) const { stdx::lock_guard<stdx::mutex> lock(_initialSyncFlagMutex); return _initialSyncFlag; diff --git a/src/mongo/db/repl/replication_consistency_markers_mock.h b/src/mongo/db/repl/replication_consistency_markers_mock.h index 82269f6a60b..b66bc03589c 100644 --- a/src/mongo/db/repl/replication_consistency_markers_mock.h +++ b/src/mongo/db/repl/replication_consistency_markers_mock.h @@ -50,6 +50,8 @@ class ReplicationConsistencyMarkersMock : public ReplicationConsistencyMarkers { public: ReplicationConsistencyMarkersMock() = default; + void initializeMinValidDocument(OperationContext* opCtx) override; + bool getInitialSyncFlag(OperationContext* opCtx) const override; void setInitialSyncFlag(OperationContext* opCtx) override; void clearInitialSyncFlag(OperationContext* opCtx) override; diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index ee6b8c3cf5f..3f3ab0700db 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -388,6 +388,8 @@ void ReplicationCoordinatorImpl::appendConnectionStats(executor::ConnectionPoolS } bool ReplicationCoordinatorImpl::_startLoadLocalConfig(OperationContext* opCtx) { + _replicationProcess->getConsistencyMarkers()->initializeMinValidDocument(opCtx); + StatusWith<LastVote> lastVote = _externalState->loadLocalLastVoteDocument(opCtx); if (!lastVote.isOK()) { if (lastVote.getStatus() == ErrorCodes::NoMatchingDocument) { |