summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHuayu Ouyang <huayu.ouyang@mongodb.com>2021-05-11 19:30:03 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-13 20:21:50 +0000
commit28206ffd75e912d28e80ebd4470ad73087c8afa1 (patch)
tree3321101d1518a204ce1565725dc70a51667587e0
parent065762a395d434a061341c05a96575525324b73b (diff)
downloadmongo-28206ffd75e912d28e80ebd4470ad73087c8afa1.tar.gz
SERVER-55702 Update 'defaultRWConcern' section of serverStatus
-rw-r--r--jstests/noPassthrough/read_write_concern_defaults_metrics.js58
-rw-r--r--jstests/sharding/read_write_concern_defaults_commands_api.js210
-rw-r--r--src/mongo/db/read_write_concern_defaults.cpp27
-rw-r--r--src/mongo/db/read_write_concern_defaults.idl14
4 files changed, 249 insertions, 60 deletions
diff --git a/jstests/noPassthrough/read_write_concern_defaults_metrics.js b/jstests/noPassthrough/read_write_concern_defaults_metrics.js
index 4efb31c265a..1b62840d6f9 100644
--- a/jstests/noPassthrough/read_write_concern_defaults_metrics.js
+++ b/jstests/noPassthrough/read_write_concern_defaults_metrics.js
@@ -12,12 +12,9 @@ load("jstests/libs/write_concern_util.js"); // For isDefaultWriteConcernMajorit
// Verifies the transaction server status response has the fields that we expect.
function verifyServerStatus(conn,
- {expectedRC, expectedWC, expectNoDefaultsDocument, expectNothing}) {
+ {expectedRC, expectedWC, expectNoDefaultsDocument, expectNothing},
+ isImplicitDefaultWCMajority) {
const res = assert.commandWorked(conn.adminCommand({serverStatus: 1}));
- if (isDefaultWriteConcernMajorityFlagEnabled(conn) && !expectedWC) {
- expectedWC = {w: "majority", wtimeout: 0};
- }
-
if (expectNothing) {
assert.eq(undefined, res.defaultRWConcern, tojson(res.defaultRWConcern));
return;
@@ -26,6 +23,20 @@ function verifyServerStatus(conn,
assert.hasFields(res, ["defaultRWConcern"]);
const defaultsRes = res.defaultRWConcern;
+ if (isDefaultWriteConcernMajorityFlagEnabled(conn)) {
+ assert.hasFields(defaultsRes, ["defaultWriteConcernSource"]);
+ if (!expectedWC) {
+ assert.eq("implicit", defaultsRes.defaultWriteConcernSource, tojson(defaultsRes));
+ if (isImplicitDefaultWCMajority) {
+ expectedWC = {w: "majority", wtimeout: 0};
+ }
+ } else {
+ assert.eq("global", defaultsRes.defaultWriteConcernSource, tojson(defaultsRes));
+ }
+ } else {
+ assert.eq(undefined, defaultsRes.defaultWriteConcernSource);
+ }
+
if (expectedRC) {
assert.eq(expectedRC, defaultsRes.defaultReadConcern, tojson(defaultsRes));
} else {
@@ -52,24 +63,25 @@ function verifyServerStatus(conn,
}
}
-function testServerStatus(conn) {
+function testServerStatus(conn, isImplicitDefaultWCMajority) {
// When no defaults have been set.
- verifyServerStatus(conn, {expectNoDefaultsDocument: true});
+ verifyServerStatus(conn, {expectNoDefaultsDocument: true}, isImplicitDefaultWCMajority);
// When only read concern is set.
assert.commandWorked(
conn.adminCommand({setDefaultRWConcern: 1, defaultReadConcern: {level: "majority"}}));
- verifyServerStatus(conn, {expectedRC: {level: "majority"}});
+ verifyServerStatus(conn, {expectedRC: {level: "majority"}}, isImplicitDefaultWCMajority);
// When read concern is explicitly unset and write concern is unset.
assert.commandWorked(conn.adminCommand(
{setDefaultRWConcern: 1, defaultReadConcern: {}, defaultWriteConcern: {}}));
- verifyServerStatus(conn, {});
+ verifyServerStatus(conn, {}, isImplicitDefaultWCMajority);
// When only write concern is set.
assert.commandWorked(conn.adminCommand(
{setDefaultRWConcern: 1, defaultReadConcern: {}, defaultWriteConcern: {w: "majority"}}));
- verifyServerStatus(conn, {expectedWC: {w: "majority", wtimeout: 0}});
+ verifyServerStatus(
+ conn, {expectedWC: {w: "majority", wtimeout: 0}}, isImplicitDefaultWCMajority);
// When both read and write concern are set.
assert.commandWorked(conn.adminCommand({
@@ -78,7 +90,8 @@ function testServerStatus(conn) {
defaultWriteConcern: {w: "majority"}
}));
verifyServerStatus(conn,
- {expectedRC: {level: "majority"}, expectedWC: {w: "majority", wtimeout: 0}});
+ {expectedRC: {level: "majority"}, expectedWC: {w: "majority", wtimeout: 0}},
+ isImplicitDefaultWCMajority);
// When the defaults document has been deleted.
assert.commandWorked(conn.getDB("config").settings.remove({_id: "ReadWriteConcernDefaults"}));
@@ -88,7 +101,7 @@ function testServerStatus(conn) {
const res = conn.adminCommand({getDefaultRWConcern: 1, inMemory: true});
return !res.hasOwnProperty("updateOpTime");
}, "mongos failed to pick up deleted default rwc", undefined, 1000, {runHangAnalyzer: false});
- verifyServerStatus(conn, {expectNoDefaultsDocument: true});
+ verifyServerStatus(conn, {expectNoDefaultsDocument: true}, isImplicitDefaultWCMajority);
}
function testFTDC(conn, ftdcDirPath, expectNothingOnRotation = false) {
@@ -140,16 +153,17 @@ jsTestLog("Testing sharded cluster...");
configOptions: {setParameter: {diagnosticDataCollectionDirectoryPath: testPathConfig}}
});
- testServerStatus(st.s);
+ testServerStatus(st.s, true /* isImplicitDefaultWCMajority */);
testFTDC(st.s, testPathMongos);
- testServerStatus(st.configRS.getPrimary());
+ testServerStatus(st.configRS.getPrimary(), true /* isImplicitDefaultWCMajority */);
testFTDC(st.configRS.getPrimary(), testPathConfig);
// Set a default before verifying it isn't included by shards.
assert.commandWorked(
st.s.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {w: "majority"}}));
- verifyServerStatus(st.rs0.getPrimary(), {expectNothing: true});
+ verifyServerStatus(
+ st.rs0.getPrimary(), {expectNothing: true}, true /* isImplicitDefaultWCMajority */);
testFTDC(st.rs0.getPrimary(), testPathShard, true /* expectNothingOnRotation */);
st.stop();
@@ -163,19 +177,29 @@ jsTestLog("Testing plain replica set...");
rst.startSet();
rst.initiate();
- testServerStatus(rst.getPrimary());
+ testServerStatus(rst.getPrimary(), true /* isImplicitDefaultWCMajority */);
testFTDC(rst.getPrimary(), testPath);
rst.stopSet();
}
+jsTestLog("Testing server status for plain replica set with implicit default WC {w:1}");
+{
+ const rst = new ReplSetTest({nodes: [{}, {}, {arbiter: true}]});
+ rst.startSet();
+ rst.initiate();
+
+ testServerStatus(rst.getPrimary(), false /* isImplicitDefaultWCMajority */);
+ rst.stopSet();
+}
+
jsTestLog("Testing standalone server...");
{
const testPath = MongoRunner.toRealPath("ftdc_dir_standalone");
const standalone =
MongoRunner.runMongod({setParameter: {diagnosticDataCollectionDirectoryPath: testPath}});
- verifyServerStatus(standalone, {expectNothing: true});
+ verifyServerStatus(standalone, {expectNothing: true}, true /* isImplicitDefaultWCMajority */);
testFTDC(standalone, testPath, true /* expectNothingOnRotation */);
MongoRunner.stopMongod(standalone);
diff --git a/jstests/sharding/read_write_concern_defaults_commands_api.js b/jstests/sharding/read_write_concern_defaults_commands_api.js
index b011b20d8f7..960073060ef 100644
--- a/jstests/sharding/read_write_concern_defaults_commands_api.js
+++ b/jstests/sharding/read_write_concern_defaults_commands_api.js
@@ -9,7 +9,10 @@ load("jstests/libs/write_concern_util.js"); // For isDefaultWriteConcernMajorit
// Asserts a set/get default RWC command response or persisted document contains the expected
// fields. Assumes a default read or write concern has been set previously and the response was not
// generated by a getDefaultRWConcern command with inMemory=true.
-function verifyFields(res, {expectRC, expectWC, isPersistedDocument}) {
+function verifyFields(res,
+ {expectRC, expectWC, isPersistedDocument},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority) {
// These fields are always set once a read or write concern has been set at least once.
let expectedFields = ["updateOpTime", "updateWallClockTime", "localUpdateWallClockTime"];
let unexpectedFields = ["inMemory"];
@@ -20,12 +23,18 @@ function verifyFields(res, {expectRC, expectWC, isPersistedDocument}) {
unexpectedFields.push("defaultReadConcern");
}
- if (expectWC) {
+ if (expectWC || (isImplicitDefaultWCMajority && !isPersistedDocument)) {
expectedFields.push("defaultWriteConcern");
} else {
unexpectedFields.push("defaultWriteConcern");
}
+ if (isDefaultWCMajorityFlagEnabled) {
+ expectedFields.push("defaultWriteConcernSource");
+ } else {
+ unexpectedFields.push("defaultWriteConcernSource");
+ }
+
// localUpdateWallClockTime is generated by the in-memory cache and is not stored in the
// persisted document.
if (isPersistedDocument) {
@@ -38,6 +47,13 @@ function verifyFields(res, {expectRC, expectWC, isPersistedDocument}) {
assert(!res.hasOwnProperty(field),
`response unexpectedly had field '${field}', res: ${tojson(res)}`);
});
+ if (isDefaultWCMajorityFlagEnabled) {
+ if (expectWC) {
+ assert.eq(res.defaultWriteConcernSource, "global", tojson(res));
+ } else {
+ assert.eq(res.defaultWriteConcernSource, "implicit", tojson(res));
+ }
+ }
}
function verifyDefaultRWCommandsInvalidInput(conn) {
@@ -115,13 +131,20 @@ function verifyDefaultRWCommandsInvalidInput(conn) {
}
// Verifies the default responses for the default RWC commands and the default persisted state.
-function verifyDefaultState(conn) {
+function verifyDefaultState(conn, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority) {
const res = assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1}));
const inMemoryRes =
assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1, inMemory: true}));
// localUpdateWallClockTime is set when a node refreshes its defaults, even if none are found.
const expectedFields = ["localUpdateWallClockTime"];
+ if (isImplicitDefaultWCMajority) {
+ expectedFields.push("defaultWriteConcern");
+ }
+ if (isDefaultWCMajorityFlagEnabled) {
+ expectedFields.push("defaultWriteConcernSource");
+ }
+
expectedFields.forEach(field => {
assert(res.hasOwnProperty(field),
`response did not have field '${field}', res: ${tojson(res)}`);
@@ -130,9 +153,19 @@ function verifyDefaultState(conn) {
});
assert.eq(inMemoryRes.inMemory, true, tojson(inMemoryRes));
+ if (isDefaultWCMajorityFlagEnabled) {
+ assert.eq(res.defaultWriteConcernSource, "implicit", tojson(res));
+ assert.eq(inMemoryRes.defaultWriteConcernSource, "implicit", tojson(inMemoryRes));
+ }
+
// No other fields should be returned if neither a default read nor write concern has been set.
- const unexpectedFields =
- ["defaultReadConcern", "defaultWriteConcern", "updateOpTime", "updateWallClockTime"];
+ const unexpectedFields = ["defaultReadConcern", "updateOpTime", "updateWallClockTime"];
+ if (!isImplicitDefaultWCMajority) {
+ unexpectedFields.push("defaultWriteConcern");
+ }
+ if (!isDefaultWCMajorityFlagEnabled) {
+ unexpectedFields.push("defaultWriteConcernSource");
+ }
unexpectedFields.forEach(field => {
assert(!res.hasOwnProperty(field),
`response unexpectedly had field '${field}', res: ${tojson(res)}`);
@@ -146,7 +179,8 @@ function verifyDefaultState(conn) {
assert.eq(null, getPersistedRWCDocument(conn));
}
-function verifyDefaultRWCommandsValidInputOnSuccess(conn) {
+function verifyDefaultRWCommandsValidInputOnSuccess(
+ conn, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority) {
//
// Test getDefaultRWConcern when neither read nor write concern are set.
//
@@ -170,22 +204,34 @@ function verifyDefaultRWCommandsValidInputOnSuccess(conn) {
// Test setDefaultRWConcern when only read concern is set.
verifyFields(assert.commandWorked(conn.adminCommand(
{setDefaultRWConcern: 1, defaultReadConcern: {level: "local"}})),
- {expectRC: true, expectWC: false});
+ {expectRC: true, expectWC: false},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
verifyFields(getPersistedRWCDocument(conn),
- {expectRC: true, expectWC: false, isPersistedDocument: true});
+ {expectRC: true, expectWC: false, isPersistedDocument: true},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
// Test getDefaultRWConcern when only read concern is set.
verifyFields(assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1})),
- {expectRC: true, expectWC: false});
+ {expectRC: true, expectWC: false},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
// Test unsetting read concern.
verifyFields(
assert.commandWorked(conn.adminCommand({setDefaultRWConcern: 1, defaultReadConcern: {}})),
- {expectRC: false, expectWC: false});
+ {expectRC: false, expectWC: false},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
verifyFields(getPersistedRWCDocument(conn),
- {expectRC: false, expectWC: false, isPersistedDocument: true});
+ {expectRC: false, expectWC: false, isPersistedDocument: true},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
verifyFields(assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1})),
- {expectRC: false, expectWC: false});
+ {expectRC: false, expectWC: false},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
//
// Test getting and setting write concern.
@@ -194,9 +240,13 @@ function verifyDefaultRWCommandsValidInputOnSuccess(conn) {
// Empty write concern is allowed if write concern has not already been set.
verifyFields(
assert.commandWorked(conn.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {}})),
- {expectRC: false, expectWC: false});
+ {expectRC: false, expectWC: false},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
verifyFields(getPersistedRWCDocument(conn),
- {expectRC: false, expectWC: false, isPersistedDocument: true});
+ {expectRC: false, expectWC: false, isPersistedDocument: true},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
// Test setRWConcern when only write concern is set.
assert.commandWorked(conn.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}}));
@@ -207,13 +257,19 @@ function verifyDefaultRWCommandsValidInputOnSuccess(conn) {
verifyFields(assert.commandWorked(
conn.adminCommand({setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}})),
- {expectRC: false, expectWC: true});
+ {expectRC: false, expectWC: true},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
verifyFields(getPersistedRWCDocument(conn),
- {expectRC: false, expectWC: true, isPersistedDocument: true});
+ {expectRC: false, expectWC: true, isPersistedDocument: true},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
// Test getRWConcern when only write concern is set.
verifyFields(assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1})),
- {expectRC: false, expectWC: true});
+ {expectRC: false, expectWC: true},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
//
// Test getting and setting both read and write concern.
@@ -223,13 +279,19 @@ function verifyDefaultRWCommandsValidInputOnSuccess(conn) {
defaultReadConcern: {level: "local"},
defaultWriteConcern: {w: 1}
})),
- {expectRC: true, expectWC: true});
+ {expectRC: true, expectWC: true},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
verifyFields(getPersistedRWCDocument(conn),
- {expectRC: true, expectWC: true, isPersistedDocument: true});
+ {expectRC: true, expectWC: true, isPersistedDocument: true},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
// Test getRWConcern when both read and write concern are set.
verifyFields(assert.commandWorked(conn.adminCommand({getDefaultRWConcern: 1})),
- {expectRC: true, expectWC: true});
+ {expectRC: true, expectWC: true},
+ isDefaultWCMajorityFlagEnabled,
+ isImplicitDefaultWCMajority);
}
function getPersistedRWCDocument(conn) {
@@ -255,22 +317,45 @@ jsTestLog("Testing standalone mongod...");
MongoRunner.stopMongod(standalone);
}
-jsTestLog("Testing standalone replica set...");
+jsTestLog("Testing standalone replica set with implicit default write concern majority...");
{
const rst = new ReplSetTest({nodes: 2});
rst.startSet();
rst.initiate();
- // TODO (SERVER-56643): Fix the test to work with the new default write concern.
- if (isDefaultWriteConcernMajorityFlagEnabled(rst.getPrimary())) {
- jsTestLog("Skipping test because the default WC majority feature flag is enabled.");
- rst.stopSet();
- return;
- }
+ // Primary succeeds.
+ const isDefaultWCMajorityFlagEnabled =
+ isDefaultWriteConcernMajorityFlagEnabled(rst.getPrimary());
+ const isImplicitDefaultWCMajority = isDefaultWCMajorityFlagEnabled;
+ verifyDefaultState(
+ rst.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
+ verifyDefaultRWCommandsValidInputOnSuccess(
+ rst.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
+ verifyDefaultRWCommandsInvalidInput(rst.getPrimary());
+
+ // Secondary can run getDefaultRWConcern, but not setDefaultRWConcern.
+ assert.commandWorked(rst.getSecondary().adminCommand({getDefaultRWConcern: 1}));
+ assert.commandFailedWithCode(
+ rst.getSecondary().adminCommand(
+ {setDefaultRWConcern: 1, defaultReadConcern: {level: "local"}}),
+ ErrorCodes.NotWritablePrimary);
+
+ rst.stopSet();
+}
+
+jsTestLog("Testing standalone replica set with implicit default write concern {w:1}...");
+{
+ const rst = new ReplSetTest({nodes: [{}, {}, {arbiter: true}]});
+ rst.startSet();
+ rst.initiate();
// Primary succeeds.
- verifyDefaultState(rst.getPrimary());
- verifyDefaultRWCommandsValidInputOnSuccess(rst.getPrimary());
+ const isDefaultWCMajorityFlagEnabled =
+ isDefaultWriteConcernMajorityFlagEnabled(rst.getPrimary());
+ verifyDefaultState(
+ rst.getPrimary(), isDefaultWCMajorityFlagEnabled, false /* isImplicitDefaultWCMajority */);
+ verifyDefaultRWCommandsValidInputOnSuccess(
+ rst.getPrimary(), isDefaultWCMajorityFlagEnabled, false /* isImplicitDefaultWCMajority */);
verifyDefaultRWCommandsInvalidInput(rst.getPrimary());
// Secondary can run getDefaultRWConcern, but not setDefaultRWConcern.
@@ -283,18 +368,60 @@ jsTestLog("Testing standalone replica set...");
rst.stopSet();
}
-jsTestLog("Testing sharded cluster...");
+jsTestLog("Testing sharded cluster with implicit default write concern majority...");
{
let st = new ShardingTest({shards: 1, rs: {nodes: 2}});
- if (isDefaultWriteConcernMajorityFlagEnabled(st.s)) {
- jsTestLog("Skipping test because the default WC majority feature flag is enabled.");
- st.stop();
- return;
- }
// Mongos succeeds.
- verifyDefaultState(st.s);
- verifyDefaultRWCommandsValidInputOnSuccess(st.s);
+ let isDefaultWCMajorityFlagEnabled = isDefaultWriteConcernMajorityFlagEnabled(st.s);
+ let isImplicitDefaultWCMajority = isDefaultWCMajorityFlagEnabled;
+ verifyDefaultState(st.s, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
+ verifyDefaultRWCommandsValidInputOnSuccess(
+ st.s, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
+ verifyDefaultRWCommandsInvalidInput(st.s);
+
+ // Shard node fails.
+ verifyDefaultRWCommandsFailWithCode(st.rs0.getPrimary(), {failureCode: 51301});
+ assert.commandFailedWithCode(st.rs0.getSecondary().adminCommand({getDefaultRWConcern: 1}),
+ 51301);
+ // Secondaries fail setDefaultRWConcern before executing the command.
+ assert.commandFailedWithCode(
+ st.rs0.getSecondary().adminCommand(
+ {setDefaultRWConcern: 1, defaultReadConcern: {level: "local"}}),
+ ErrorCodes.NotWritablePrimary);
+
+ st.stop();
+ st = new ShardingTest({shards: 1, rs: {nodes: 2}});
+ // Config server primary succeeds.
+ isDefaultWCMajorityFlagEnabled =
+ isDefaultWriteConcernMajorityFlagEnabled(st.configRS.getPrimary());
+ isImplicitDefaultWCMajority = isDefaultWCMajorityFlagEnabled;
+ verifyDefaultState(
+ st.configRS.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
+ verifyDefaultRWCommandsValidInputOnSuccess(
+ st.configRS.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
+ verifyDefaultRWCommandsInvalidInput(st.configRS.getPrimary());
+
+ // Config server secondary can run getDefaultRWConcern, but not setDefaultRWConcern.
+ assert.commandWorked(st.configRS.getSecondary().adminCommand({getDefaultRWConcern: 1}));
+ assert.commandFailedWithCode(
+ st.configRS.getSecondary().adminCommand(
+ {setDefaultRWConcern: 1, defaultReadConcern: {level: "local"}}),
+ ErrorCodes.NotWritablePrimary);
+
+ st.stop();
+}
+
+jsTestLog("Testing sharded cluster with a PSA replica set...");
+{
+ let st = new ShardingTest({shards: 1, rs: {nodes: [{}, {}, {arbiter: true}]}});
+
+ // Mongos succeeds.
+ let isDefaultWCMajorityFlagEnabled = isDefaultWriteConcernMajorityFlagEnabled(st.s);
+ let isImplicitDefaultWCMajority = isDefaultWCMajorityFlagEnabled;
+ verifyDefaultState(st.s, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
+ verifyDefaultRWCommandsValidInputOnSuccess(
+ st.s, isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
verifyDefaultRWCommandsInvalidInput(st.s);
// Shard node fails.
@@ -310,8 +437,13 @@ jsTestLog("Testing sharded cluster...");
st.stop();
st = new ShardingTest({shards: 1, rs: {nodes: 2}});
// Config server primary succeeds.
- verifyDefaultState(st.configRS.getPrimary());
- verifyDefaultRWCommandsValidInputOnSuccess(st.configRS.getPrimary());
+ isDefaultWCMajorityFlagEnabled =
+ isDefaultWriteConcernMajorityFlagEnabled(st.configRS.getPrimary());
+ isImplicitDefaultWCMajority = isDefaultWCMajorityFlagEnabled;
+ verifyDefaultState(
+ st.configRS.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
+ verifyDefaultRWCommandsValidInputOnSuccess(
+ st.configRS.getPrimary(), isDefaultWCMajorityFlagEnabled, isImplicitDefaultWCMajority);
verifyDefaultRWCommandsInvalidInput(st.configRS.getPrimary());
// Config server secondary can run getDefaultRWConcern, but not setDefaultRWConcern.
diff --git a/src/mongo/db/read_write_concern_defaults.cpp b/src/mongo/db/read_write_concern_defaults.cpp
index 056da76470f..183805cf64d 100644
--- a/src/mongo/db/read_write_concern_defaults.cpp
+++ b/src/mongo/db/read_write_concern_defaults.cpp
@@ -110,6 +110,12 @@ RWConcernDefault ReadWriteConcernDefaults::generateNewCWRWCToBeSavedOnDisk(
rc || wc);
RWConcernDefault rwc;
+ const bool isDefaultWCMajorityFeatureFlagEnabled =
+ repl::feature_flags::gDefaultWCMajority.isEnabled(serverGlobalParams.featureCompatibility);
+ if (isDefaultWCMajorityFeatureFlagEnabled) {
+ rwc.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kImplicit);
+ }
+
if (rc && !rc->isEmpty()) {
checkSuitabilityAsDefault(*rc);
rwc.setDefaultReadConcern(rc);
@@ -117,6 +123,9 @@ RWConcernDefault ReadWriteConcernDefaults::generateNewCWRWCToBeSavedOnDisk(
if (wc && !wc->usedDefault) {
checkSuitabilityAsDefault(*wc);
rwc.setDefaultWriteConcern(wc);
+ if (isDefaultWCMajorityFeatureFlagEnabled) {
+ rwc.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kGlobal);
+ }
}
auto* const serviceContext = opCtx->getServiceContext();
@@ -130,6 +139,10 @@ RWConcernDefault ReadWriteConcernDefaults::generateNewCWRWCToBeSavedOnDisk(
}
if (!wc && current) {
rwc.setDefaultWriteConcern(current->getDefaultWriteConcern());
+ if (isDefaultWCMajorityFeatureFlagEnabled && current->getDefaultWriteConcern() &&
+ !current->getDefaultWriteConcern().get().usedDefault) {
+ rwc.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kGlobal);
+ }
}
// If the setDefaultRWConcern command tries to unset the global default write concern when it
// has already been set, throw an error.
@@ -213,6 +226,12 @@ ReadWriteConcernDefaults::_getDefaultCWRWCFromDisk(OperationContext* opCtx) {
ReadWriteConcernDefaults::RWConcernDefaultAndTime ReadWriteConcernDefaults::getDefault(
OperationContext* opCtx) {
auto cached = _getDefaultCWRWCFromDisk(opCtx).value_or(RWConcernDefaultAndTime());
+ const bool isDefaultWCMajorityFeatureFlagEnabled =
+ serverGlobalParams.featureCompatibility.isVersionInitialized() &&
+ repl::feature_flags::gDefaultWCMajority.isEnabled(serverGlobalParams.featureCompatibility);
+ if (isDefaultWCMajorityFeatureFlagEnabled && !cached.getDefaultWriteConcernSource()) {
+ cached.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kImplicit);
+ }
// The implicit default write concern will be w:1 if the feature compatibility version is not
// yet initialized. Similarly, if the config hasn't yet been loaded on the node, the default
@@ -220,10 +239,7 @@ ReadWriteConcernDefaults::RWConcernDefaultAndTime ReadWriteConcernDefaults::getD
// we have loaded our config, nodes could change their implicit write concern default. This is
// safe since we shouldn't be accepting writes that need a write concern before we have loaded
// our config.
- if (!serverGlobalParams.featureCompatibility.isVersionInitialized() ||
- !repl::feature_flags::gDefaultWCMajority.isEnabled(
- serverGlobalParams.featureCompatibility) ||
- !_implicitDefaultWriteConcernMajority) {
+ if (!isDefaultWCMajorityFeatureFlagEnabled || !_implicitDefaultWriteConcernMajority) {
return cached;
}
@@ -232,6 +248,9 @@ ReadWriteConcernDefaults::RWConcernDefaultAndTime ReadWriteConcernDefaults::getD
cached.setDefaultWriteConcern(WriteConcernOptions(WriteConcernOptions::kMajority,
WriteConcernOptions::SyncMode::UNSET,
WriteConcernOptions::kNoTimeout));
+ if (isDefaultWCMajorityFeatureFlagEnabled) {
+ cached.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kImplicit);
+ }
}
return cached;
diff --git a/src/mongo/db/read_write_concern_defaults.idl b/src/mongo/db/read_write_concern_defaults.idl
index bdf67c6fca5..c280d1bb0b8 100644
--- a/src/mongo/db/read_write_concern_defaults.idl
+++ b/src/mongo/db/read_write_concern_defaults.idl
@@ -33,6 +33,16 @@ imports:
- "mongo/db/repl/read_concern_args.idl"
- "mongo/db/write_concern_options.idl"
+enums:
+ DefaultWriteConcernSource:
+ description: "The source of the default write concern"
+ type: string
+ values:
+ # The default write concern was set implicitly by the server
+ kImplicit: "implicit"
+ # The default write concern was set globally through setDefaultRWConcern
+ kGlobal: "global"
+
structs:
RWConcernDefault:
description: "Represents a set of read/write concern defaults, and associated metadata"
@@ -58,3 +68,7 @@ structs:
used for any recency comparisons."
type: date
optional: true
+ defaultWriteConcernSource:
+ description: "The source of the default write concern."
+ type: DefaultWriteConcernSource
+ optional: true