summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarolyn Duan <carolyn.duan@mongodb.com>2021-06-17 20:20:02 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-08-12 19:38:29 +0000
commitba9b762447e745e7b3ec32692b618ffed1a48e14 (patch)
tree6e31faf64e46a63e1a3bffb34337755d94c4560d
parent5e173fac938ea4e4f834d66b562d49a97c0b8eaa (diff)
downloadmongo-ba9b762447e745e7b3ec32692b618ffed1a48e14.tar.gz
SERVER-37904 Add enableOverrideClusterChainingSetting server parameter
(cherry picked from commit 7422c1b638d2e4b200e7b72041d76f5702364d2b)
-rw-r--r--etc/backports_required_for_multiversion_tests.yml2
-rw-r--r--jstests/replsets/cluster_chaining_override.js40
-rw-r--r--src/mongo/db/repl/SConscript1
-rw-r--r--src/mongo/db/repl/repl_server_parameters.idl10
-rw-r--r--src/mongo/db/repl/topology_coordinator.cpp6
5 files changed, 57 insertions, 2 deletions
diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml
index c6c639e4e76..568adaaa903 100644
--- a/etc/backports_required_for_multiversion_tests.yml
+++ b/etc/backports_required_for_multiversion_tests.yml
@@ -116,6 +116,8 @@ all:
test_file: jstests/replsets/dont_refresh_session_prepare_secondary.js
- ticket: SERVER-59197
test_file: jstests/replsets/sessions_collection_reaping.js
+ - ticket: SERVER-37904
+ test_file: jstests/replsets/cluster_chaining_override.js
# Tests that should only be excluded from particular suites should be listed under that suite.
suites:
diff --git a/jstests/replsets/cluster_chaining_override.js b/jstests/replsets/cluster_chaining_override.js
new file mode 100644
index 00000000000..5a913c3096e
--- /dev/null
+++ b/jstests/replsets/cluster_chaining_override.js
@@ -0,0 +1,40 @@
+/**
+ * Tests that if chaining is disabled, enabling the server parameter
+ * 'enableOverrideClusterChainingSetting' will allow the node to chain anyway.
+ */
+
+(function() {
+"use strict";
+load("jstests/replsets/rslib.js");
+
+let rst = new ReplSetTest({
+ nodes: {
+ n0: {},
+ n1: {rsConfig: {priority: 0}},
+ n2: {rsConfig: {priority: 0}, setParameter: {enableOverrideClusterChainingSetting: true}}
+ },
+ // Enable the periodic noop writer to aid sync source selection.
+ nodeOptions: {setParameter: {writePeriodicNoops: true}},
+ settings: {chainingAllowed: false},
+ useBridge: true
+});
+rst.startSet();
+rst.initiate();
+
+const primary = rst.getPrimary();
+rst.awaitSecondaryNodes();
+const [n1, n2] = rst.getSecondaries();
+
+// Create a network partition between n2 and the primary.
+n2.disconnect(primary);
+
+// Since n2 has enabled the parameter 'enableOverrideClusterChainingSetting', n2 should eventually
+// chain from n1.
+rst.awaitSyncSource(n2, n1);
+
+// A write with write concern {w:3} should still reach n2.
+var options = {writeConcern: {w: 3, wtimeout: ReplSetTest.kDefaultTimeoutMS}};
+assert.commandWorked(primary.getDB("admin").foo.insert({x: 1}, options));
+
+rst.stopSet();
+}()); \ No newline at end of file
diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript
index b7c03be5476..39ecc27ce01 100644
--- a/src/mongo/db/repl/SConscript
+++ b/src/mongo/db/repl/SConscript
@@ -877,6 +877,7 @@ env.Library('topology_coordinator',
'$BUILD_DIR/mongo/db/catalog/commit_quorum_options',
'$BUILD_DIR/mongo/idl/server_parameter',
'split_horizon',
+ 'repl_server_parameters'
])
env.CppUnitTest('repl_set_heartbeat_response_test',
diff --git a/src/mongo/db/repl/repl_server_parameters.idl b/src/mongo/db/repl/repl_server_parameters.idl
index c97babde6ae..d636303206e 100644
--- a/src/mongo/db/repl/repl_server_parameters.idl
+++ b/src/mongo/db/repl/repl_server_parameters.idl
@@ -277,6 +277,16 @@ server_parameters:
default: ""
validator: { callback: 'validateReadPreferenceMode' }
+ enableOverrideClusterChainingSetting:
+ description: >-
+ When enabled, allows a node to override the cluster-wide chainingAllowed setting.
+ If chaining is disabled in the replica set, enabling this parameter allows the node
+ to chain regardless.
+ set_at: [ startup ]
+ cpp_vartype: AtomicWord<bool>
+ cpp_varname: enableOverrideClusterChainingSetting
+ default: false
+
startupRecoveryForRestore:
description: >-
When set, do startup recovery in such a way that the history of the recovered
diff --git a/src/mongo/db/repl/topology_coordinator.cpp b/src/mongo/db/repl/topology_coordinator.cpp
index 6a02ad97fd1..4ac2eeda7bf 100644
--- a/src/mongo/db/repl/topology_coordinator.cpp
+++ b/src/mongo/db/repl/topology_coordinator.cpp
@@ -52,6 +52,7 @@
#include "mongo/db/repl/heartbeat_response_action.h"
#include "mongo/db/repl/isself.h"
#include "mongo/db/repl/member_data.h"
+#include "mongo/db/repl/repl_server_parameters_gen.h"
#include "mongo/db/repl/rslog.h"
#include "mongo/rpc/metadata/oplog_query_metadata.h"
#include "mongo/rpc/metadata/repl_set_metadata.h"
@@ -206,7 +207,7 @@ HostAndPort TopologyCoordinator::chooseNewSyncSource(Date_t now,
// If we are only allowed to sync from the primary, use it as the sync source if possible.
if (readPreference == ReadPreference::PrimaryOnly ||
(chainingPreference == ChainingPreference::kUseConfiguration &&
- !_rsConfig.isChainingAllowed())) {
+ !_rsConfig.isChainingAllowed() && !enableOverrideClusterChainingSetting.load())) {
if (readPreference == ReadPreference::SecondaryOnly) {
severe() << "Sync source read preference 'secondaryOnly' with chaining disabled is not "
"valid.";
@@ -2686,7 +2687,8 @@ bool TopologyCoordinator::shouldChangeSyncSource(
// Change sync source if chaining is disabled, we are not syncing from the primary, and we know
// who the new primary is. We do not consider chaining disabled if we are the primary, since
// we are in catchup mode.
- auto chainingDisabled = !_rsConfig.isChainingAllowed() && _currentPrimaryIndex != _selfIndex;
+ auto chainingDisabled = !_rsConfig.isChainingAllowed() &&
+ !enableOverrideClusterChainingSetting.load() && _currentPrimaryIndex != _selfIndex;
auto foundNewPrimary = _currentPrimaryIndex != -1 && _currentPrimaryIndex != currentSourceIndex;
if (primaryIndex != currentSourceIndex && chainingDisabled && foundNewPrimary) {
auto newPrimary = _rsConfig.getMemberAt(_currentPrimaryIndex).getHostAndPort();