summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLingzhi Deng <lingzhi.deng@mongodb.com>2021-09-22 13:33:07 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-10-12 14:04:56 +0000
commit6427bb01da49015bbac8e6774aea4e90993053ae (patch)
tree8e144cbd81a5d122a2ac4f800cac1f153f7c4728
parent4da49024045ef47a6958157b64e73511c4865b49 (diff)
downloadmongo-6427bb01da49015bbac8e6774aea4e90993053ae.tar.gz
SERVER-58780: Ensure that _shouldSetStableTimestamp restores to true if replSetInitiate fails
(cherry picked from commit 75e59101ebc9d8a4633b270a3fd44d6e2058a1b9)
-rw-r--r--jstests/replsets/initiate_emrc_false.js65
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp8
2 files changed, 73 insertions, 0 deletions
diff --git a/jstests/replsets/initiate_emrc_false.js b/jstests/replsets/initiate_emrc_false.js
new file mode 100644
index 00000000000..6843c805405
--- /dev/null
+++ b/jstests/replsets/initiate_emrc_false.js
@@ -0,0 +1,65 @@
+/*
+ * Test that there is no side effects of failing replSetInitiate with eMRC=false, SERVER-58780.
+ * @tags: [requires_persistence, multiversion_incompatible]
+ */
+
+(function() {
+"use strict";
+
+function runTest({cleanShutdown}) {
+ const rst = new ReplSetTest({
+ name: jsTestName(),
+ nodes: 2,
+ nodeOptions: {
+ enableMajorityReadConcern: "false",
+ }
+ });
+ const nodes = rst.startSet();
+
+ // Run replSetInitiate with an invalid config and expect it to fail.
+ jsTestLog("Running invalid replSetInitiate");
+ assert.commandFailedWithCode(nodes[0].adminCommand({replSetInitiate: {foo: "bar"}}),
+ ErrorCodes.InvalidReplicaSetConfig);
+ assert.commandFailedWithCode(nodes[1].adminCommand({replSetInitiate: {foo: "bar"}}),
+ ErrorCodes.InvalidReplicaSetConfig);
+
+ rst.initiateWithHighElectionTimeout();
+
+ // Do some dummy writes.
+ const primary = rst.getPrimary();
+ const testDB = primary.getDB("test");
+ assert.commandWorked(testDB.runCommand({
+ insert: "coll",
+ documents: [...Array(100).keys()].map(x => ({_id: x})),
+ writeConcern: {w: "majority"}
+ }));
+ rst.awaitSecondaryNodes();
+
+ let secondary = rst.getSecondary();
+ if (cleanShutdown) {
+ jsTestLog("Restarting secondary node from clean shutdown");
+ rst.stop(secondary, 0, undefined, {forRestart: true});
+ } else {
+ jsTestLog("Restarting secondary node from unclean shutdown");
+ rst.stop(secondary, 9, {allowedExitCode: MongoRunner.EXIT_SIGKILL}, {forRestart: true});
+ }
+
+ // Restarting from shutdown shouldn't need to go through initial sync again. Set a failpoint to
+ // hang initial sync so that if the node decides to do initial sync again, the test will fail.
+ secondary = rst.start(secondary,
+ {
+ setParameter: {
+ 'failpoint.initialSyncHangAfterGettingBeginFetchingTimestamp':
+ tojson({mode: 'alwaysOn'}),
+ }
+ },
+ true /* restart */);
+
+ rst.awaitSecondaryNodes();
+
+ rst.stopSet();
+}
+
+runTest({cleanShutdown: true});
+runTest({cleanShutdown: false});
+})();
diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp
index 9c61b67b0dc..1cad14b0682 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -2864,6 +2864,13 @@ Status ReplicationCoordinatorImpl::processReplSetInitiate(OperationContext* opCt
if (!serverGlobalParams.enableMajorityReadConcern) {
_shouldSetStableTimestamp = false;
}
+ auto setStableTimestampGuard = makeGuard([&] {
+ lockAndCall(&lk, [=] {
+ if (!serverGlobalParams.enableMajorityReadConcern) {
+ _shouldSetStableTimestamp = true;
+ }
+ });
+ });
lk.unlock();
@@ -2924,6 +2931,7 @@ Status ReplicationCoordinatorImpl::processReplSetInitiate(OperationContext* opCt
// Set our stable timestamp for storage and re-enable stable timestamp advancement after we have
// set our initial data timestamp.
+ setStableTimestampGuard.dismiss();
if (!serverGlobalParams.enableMajorityReadConcern) {
stdx::unique_lock<Latch> lk(_mutex);
_shouldSetStableTimestamp = true;