diff options
author | Huayu Ouyang <huayu.ouyang@mongodb.com> | 2021-05-11 19:30:03 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-05-13 20:21:50 +0000 |
commit | 28206ffd75e912d28e80ebd4470ad73087c8afa1 (patch) | |
tree | 3321101d1518a204ce1565725dc70a51667587e0 | |
parent | 065762a395d434a061341c05a96575525324b73b (diff) | |
download | mongo-28206ffd75e912d28e80ebd4470ad73087c8afa1.tar.gz |
SERVER-55702 Update 'defaultRWConcern' section of serverStatus
-rw-r--r-- | jstests/noPassthrough/read_write_concern_defaults_metrics.js | 58 | ||||
-rw-r--r-- | jstests/sharding/read_write_concern_defaults_commands_api.js | 210 | ||||
-rw-r--r-- | src/mongo/db/read_write_concern_defaults.cpp | 27 | ||||
-rw-r--r-- | src/mongo/db/read_write_concern_defaults.idl | 14 |
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 |