summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/noPassthrough/minvalid.js4
-rw-r--r--jstests/noPassthrough/minvalid2.js8
-rw-r--r--jstests/replsets/apply_batch_only_goes_forward.js5
-rw-r--r--src/mongo/db/repl/SConscript13
-rw-r--r--src/mongo/db/repl/replication_consistency_markers.h6
-rw-r--r--src/mongo/db/repl/replication_consistency_markers.idl65
-rw-r--r--src/mongo/db/repl/replication_consistency_markers_impl.cpp133
-rw-r--r--src/mongo/db/repl/replication_consistency_markers_impl.h10
-rw-r--r--src/mongo/db/repl/replication_consistency_markers_impl_test.cpp21
-rw-r--r--src/mongo/db/repl/replication_consistency_markers_mock.cpp14
-rw-r--r--src/mongo/db/repl/replication_consistency_markers_mock.h2
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp2
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) {