summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/bson/bsonobjbuilder.h25
-rw-r--r--src/mongo/db/commands.cpp30
-rw-r--r--src/mongo/db/commands.h6
-rw-r--r--src/mongo/db/commands/getmore_cmd.cpp2
-rw-r--r--src/mongo/db/commands/set_feature_compatibility_version_command.cpp12
-rw-r--r--src/mongo/db/commands/write_commands.cpp2
-rw-r--r--src/mongo/db/read_concern.cpp2
-rw-r--r--src/mongo/db/read_concern.h4
-rw-r--r--src/mongo/db/read_concern_mongod.cpp8
-rw-r--r--src/mongo/db/read_write_concern_defaults.cpp2
-rw-r--r--src/mongo/db/read_write_concern_defaults_test.cpp111
-rw-r--r--src/mongo/db/repl/repl_set_config.cpp101
-rw-r--r--src/mongo/db/repl/repl_set_config.h2
-rw-r--r--src/mongo/db/repl/repl_set_config_test.cpp30
-rw-r--r--src/mongo/db/repl/repl_set_config_validators.h3
-rw-r--r--src/mongo/db/repl/replication_coordinator.h2
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp18
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp18
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl_test.cpp89
-rw-r--r--src/mongo/db/repl/replication_coordinator_mock.cpp2
-rw-r--r--src/mongo/db/s/chunk_move_write_concern_options.cpp2
-rw-r--r--src/mongo/db/s/clone_catalog_data_command.cpp6
-rw-r--r--src/mongo/db/s/config/configsvr_abort_reshard_collection_command.cpp5
-rw-r--r--src/mongo/db/s/config/configsvr_add_shard_command.cpp6
-rw-r--r--src/mongo/db/s/config/configsvr_clear_jumbo_flag_command.cpp5
-rw-r--r--src/mongo/db/s/config/configsvr_commit_reshard_collection_command.cpp6
-rw-r--r--src/mongo/db/s/config/configsvr_create_database_command.cpp6
-rw-r--r--src/mongo/db/s/config/configsvr_ensure_chunk_version_is_greater_than_command.cpp6
-rw-r--r--src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp5
-rw-r--r--src/mongo/db/s/config/configsvr_remove_chunks_command.cpp5
-rw-r--r--src/mongo/db/s/config/configsvr_remove_shard_command.cpp6
-rw-r--r--src/mongo/db/s/config/configsvr_remove_tags_command.cpp5
-rw-r--r--src/mongo/db/s/config/configsvr_rename_collection_metadata_command.cpp5
-rw-r--r--src/mongo/db/s/config/configsvr_repair_sharded_collection_chunks_history_command.cpp6
-rw-r--r--src/mongo/db/s/config/configsvr_reshard_collection_cmd.cpp5
-rw-r--r--src/mongo/db/s/config/configsvr_set_allow_migrations_command.cpp5
-rw-r--r--src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp5
-rw-r--r--src/mongo/db/s/migration_chunk_cloner_source_legacy_commands.cpp5
-rw-r--r--src/mongo/db/s/migration_destination_manager.cpp4
-rw-r--r--src/mongo/db/s/migration_destination_manager_legacy_commands.cpp6
-rw-r--r--src/mongo/db/s/migration_util.cpp2
-rw-r--r--src/mongo/db/s/resharding/resharding_txn_cloner.cpp2
-rw-r--r--src/mongo/db/s/session_catalog_migration_source.cpp5
-rw-r--r--src/mongo/db/s/sharding_logging.cpp2
-rw-r--r--src/mongo/db/s/shardsvr_abort_reshard_collection_command.cpp5
-rw-r--r--src/mongo/db/s/shardsvr_collmod_command.cpp7
-rw-r--r--src/mongo/db/s/shardsvr_collmod_participant_command.cpp7
-rw-r--r--src/mongo/db/s/shardsvr_commit_reshard_collection_command.cpp5
-rw-r--r--src/mongo/db/s/shardsvr_create_collection_command.cpp8
-rw-r--r--src/mongo/db/s/shardsvr_create_collection_participant_command.cpp7
-rw-r--r--src/mongo/db/s/shardsvr_drop_collection_command.cpp7
-rw-r--r--src/mongo/db/s/shardsvr_drop_collection_participant_command.cpp7
-rw-r--r--src/mongo/db/s/shardsvr_drop_database_command.cpp7
-rw-r--r--src/mongo/db/s/shardsvr_drop_database_participant_command.cpp7
-rw-r--r--src/mongo/db/s/shardsvr_move_primary_command.cpp6
-rw-r--r--src/mongo/db/s/shardsvr_rename_collection_command.cpp7
-rw-r--r--src/mongo/db/s/shardsvr_rename_collection_participant_command.cpp14
-rw-r--r--src/mongo/db/s/shardsvr_reshard_collection_command.cpp7
-rw-r--r--src/mongo/db/s/shardsvr_set_allow_migrations_command.cpp7
-rw-r--r--src/mongo/db/service_entry_point_mongod.cpp2
-rw-r--r--src/mongo/db/stats/server_write_concern_metrics.cpp13
-rw-r--r--src/mongo/db/transaction_api_test.cpp16
-rw-r--r--src/mongo/db/write_concern.cpp17
-rw-r--r--src/mongo/db/write_concern_options.cpp76
-rw-r--r--src/mongo/db/write_concern_options.h64
-rw-r--r--src/mongo/db/write_concern_options_test.cpp63
-rw-r--r--src/mongo/embedded/read_concern_embedded.cpp3
-rw-r--r--src/mongo/embedded/service_entry_point_embedded.cpp2
-rw-r--r--src/mongo/idl/basic_types.h92
-rw-r--r--src/mongo/idl/basic_types.idl6
-rw-r--r--src/mongo/s/catalog/sharding_catalog_client_impl.cpp23
-rw-r--r--src/mongo/s/commands/cluster_rwc_defaults_commands.cpp2
-rw-r--r--src/mongo/s/request_types/balance_chunk_request_test.cpp4
-rw-r--r--src/mongo/s/request_types/migration_secondary_throttle_options.cpp3
-rw-r--r--src/mongo/s/request_types/migration_secondary_throttle_options_test.cpp28
-rw-r--r--src/mongo/s/transaction_router_test.cpp21
76 files changed, 521 insertions, 606 deletions
diff --git a/src/mongo/bson/bsonobjbuilder.h b/src/mongo/bson/bsonobjbuilder.h
index c4b578e5f35..be826d5a824 100644
--- a/src/mongo/bson/bsonobjbuilder.h
+++ b/src/mongo/bson/bsonobjbuilder.h
@@ -539,9 +539,17 @@ public:
* Append a map of values as a sub-object.
* Note: the keys of the map should be StringData-compatible (i.e. strings).
*/
- template <class K, class T>
- Derived& append(StringData fieldName, const std::map<K, T>& vals);
+ TEMPLATE(typename Map)
+ REQUIRES(std::is_convertible_v<decltype(std::declval<Map>().begin()->first), StringData>)
+ Derived& append(StringData fieldName, const Map& map) {
+ typename std::remove_reference<Derived>::type bob;
+ for (auto&& [k, v] : map) {
+ bob.append(k, v);
+ }
+ append(fieldName, bob.obj());
+ return static_cast<Derived&>(*this);
+ }
/** Append a range of values between two iterators. */
template <class It>
@@ -859,7 +867,6 @@ public:
UniqueBSONObjBuilder(UniqueBSONObjBuilder&&) = default;
UniqueBSONObjBuilder(const UniqueBSONObjBuilder&) = delete;
- UniqueBSONObjBuilder& operator=(UniqueBSONObjBuilder&&) = default;
UniqueBSONObjBuilder& operator=(const UniqueBSONObjBuilder&) = delete;
~UniqueBSONObjBuilder() {
@@ -1117,18 +1124,6 @@ inline Derived& BSONObjBuilderBase<Derived, B>::append(StringData fieldName,
return append(fieldName, vals.begin(), vals.end());
}
-template <class Derived, class BufBuilderType>
-template <class K, class T>
-inline Derived& BSONObjBuilderBase<Derived, BufBuilderType>::append(StringData fieldName,
- const std::map<K, T>& vals) {
- typename std::remove_reference<Derived>::type bob;
- for (typename std::map<K, T>::const_iterator i = vals.begin(); i != vals.end(); ++i) {
- bob.append(i->first, i->second);
- }
- append(fieldName, bob.obj());
- return static_cast<Derived&>(*this);
-}
-
template <class Derived, class B>
template <class It>
inline Derived& BSONObjBuilderBase<Derived, B>::append(StringData fieldName, It begin, It end) {
diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp
index 23967c70d60..3533eb35173 100644
--- a/src/mongo/db/commands.cpp
+++ b/src/mongo/db/commands.cpp
@@ -67,6 +67,8 @@
#include "mongo/util/invariant.h"
#include "mongo/util/str.h"
+using namespace fmt::literals;
+
namespace mongo {
using logv2::LogComponent;
@@ -456,26 +458,21 @@ BSONObj CommandHelpers::appendGenericReplyFields(const BSONObj& replyObjWithGene
BSONObj CommandHelpers::appendMajorityWriteConcern(const BSONObj& cmdObj,
WriteConcernOptions defaultWC) {
WriteConcernOptions newWC = kMajorityWriteConcern;
-
if (cmdObj.hasField(kWriteConcernField)) {
- auto wc = cmdObj.getField(kWriteConcernField);
- // The command has a writeConcern field and it's majority, so we can
- // return it as-is.
- if (wc["w"].ok() && wc["w"].str() == "majority") {
+ auto wc = uassertStatusOK(WriteConcernOptions::extractWCFromCommand(cmdObj));
+
+ // The command has a writeConcern field and it's majority, so we can return it as-is.
+ if (wc.isMajority()) {
return cmdObj;
}
- if (wc["wtimeout"].ok()) {
- // They set a timeout, but aren't using majority WC. We want to use their
- // timeout along with majority WC.
- newWC = WriteConcernOptions(WriteConcernOptions::kMajority,
- WriteConcernOptions::SyncMode::UNSET,
- wc["wtimeout"].Number());
- }
+ newWC = WriteConcernOptions{
+ WriteConcernOptions::kMajority, WriteConcernOptions::SyncMode::UNSET, wc.wTimeout};
} else if (!defaultWC.usedDefaultConstructedWC) {
auto minimumAcceptableWTimeout = newWC.wTimeout;
newWC = defaultWC;
- newWC.wMode = "majority";
+ newWC.w = "majority";
+
if (defaultWC.wTimeout < minimumAcceptableWTimeout) {
newWC.wTimeout = minimumAcceptableWTimeout;
}
@@ -550,6 +547,13 @@ bool CommandHelpers::uassertShouldAttemptParse(OperationContext* opCtx,
}
}
+void CommandHelpers::uassertCommandRunWithMajority(StringData commandName,
+ const WriteConcernOptions& writeConcern) {
+ uassert(ErrorCodes::InvalidOptions,
+ "\"{}\" must be called with majority writeConcern, got: {} "_format(
+ commandName, writeConcern.toBSON().toString()),
+ writeConcern.isMajority());
+}
void CommandHelpers::canUseTransactions(const NamespaceString& nss,
StringData cmdName,
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index 778c62cb2b6..cd7ff64b371 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -307,6 +307,12 @@ struct CommandHelpers {
const OpMsgRequest& request);
/**
+ * Asserts that a majority write concern was used for a command.
+ */
+ static void uassertCommandRunWithMajority(StringData commandName,
+ const WriteConcernOptions& wc);
+
+ /**
* Verifies that command is allowed to run under a transaction in the given database or
* namespace, and throws if that verification doesn't pass.
*/
diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp
index 8bef7d417fe..58c37b80edf 100644
--- a/src/mongo/db/commands/getmore_cmd.cpp
+++ b/src/mongo/db/commands/getmore_cmd.cpp
@@ -82,7 +82,7 @@ MONGO_FAIL_POINT_DEFINE(rsStopGetMoreCmd);
MONGO_FAIL_POINT_DEFINE(getMoreHangAfterPinCursor);
// The timeout when waiting for linearizable read concern on a getMore command.
-static constexpr int kLinearizableReadConcernTimeout = 15000;
+static constexpr Milliseconds kLinearizableReadConcernTimeout{15000};
// getMore can run with any readConcern, because cursor-creating commands like find can run with any
// readConcern. However, since getMore automatically uses the readConcern of the command that
diff --git a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
index 540d8657f6f..207ddd86709 100644
--- a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
+++ b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
@@ -242,17 +242,15 @@ public:
// TODO SERVER-25778: replace this with the general mechanism for specifying a default
// writeConcern.
ON_BLOCK_EXIT([&] {
- // Propagate the user's wTimeout if one was given.
- auto timeout = opCtx->getWriteConcern().isImplicitDefaultWriteConcern()
- ? INT_MAX
- : opCtx->getWriteConcern().wTimeout;
WriteConcernResult res;
auto waitForWCStatus = waitForWriteConcern(
opCtx,
repl::ReplClientInfo::forClient(opCtx->getClient()).getLastOp(),
- WriteConcernOptions(repl::ReplSetConfig::kMajorityWriteConcernModeName,
- WriteConcernOptions::SyncMode::UNSET,
- timeout),
+ WriteConcernOptions(
+ repl::ReplSetConfig::kMajorityWriteConcernModeName,
+ WriteConcernOptions::SyncMode::UNSET,
+ // Propagate the user's wTimeout if one was given. Default is kNoTimeout.
+ opCtx->getWriteConcern().wTimeout),
&res);
CommandHelpers::appendCommandWCStatus(result, waitForWCStatus, res);
});
diff --git a/src/mongo/db/commands/write_commands.cpp b/src/mongo/db/commands/write_commands.cpp
index 6eb1009bc86..e90d4ac25ce 100644
--- a/src/mongo/db/commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands.cpp
@@ -105,7 +105,7 @@ void redactTooLongLog(mutablebson::Document* cmdObj, StringData fieldName) {
bool shouldSkipOutput(OperationContext* opCtx) {
const WriteConcernOptions& writeConcern = opCtx->getWriteConcern();
- return writeConcern.wMode.empty() && writeConcern.wNumNodes == 0 &&
+ return writeConcern.isUnacknowledged() &&
(writeConcern.syncMode == WriteConcernOptions::SyncMode::NONE ||
writeConcern.syncMode == WriteConcernOptions::SyncMode::UNSET);
}
diff --git a/src/mongo/db/read_concern.cpp b/src/mongo/db/read_concern.cpp
index fe9fd208c04..85f33dd149e 100644
--- a/src/mongo/db/read_concern.cpp
+++ b/src/mongo/db/read_concern.cpp
@@ -48,7 +48,7 @@ Status waitForReadConcern(OperationContext* opCtx,
return w(opCtx, readConcernArgs, dbName, allowAfterClusterTime);
}
-Status waitForLinearizableReadConcern(OperationContext* opCtx, int readConcernTimeout) {
+Status waitForLinearizableReadConcern(OperationContext* opCtx, Milliseconds readConcernTimeout) {
static auto w = MONGO_WEAK_FUNCTION_DEFINITION(waitForLinearizableReadConcern);
return w(opCtx, readConcernTimeout);
}
diff --git a/src/mongo/db/read_concern.h b/src/mongo/db/read_concern.h
index e12915870cf..5767631864e 100644
--- a/src/mongo/db/read_concern.h
+++ b/src/mongo/db/read_concern.h
@@ -29,6 +29,8 @@
#pragma once
+#include "mongo/util/duration.h"
+
namespace mongo {
class BSONObj;
@@ -75,7 +77,7 @@ Status waitForReadConcern(OperationContext* opCtx,
* A readConcernTimeout of 0 indicates that the operation will block indefinitely waiting for read
* concern.
*/
-Status waitForLinearizableReadConcern(OperationContext* opCtx, int readConcernTimeout);
+Status waitForLinearizableReadConcern(OperationContext* opCtx, Milliseconds readConcernTimeout);
/**
* Waits to satisfy a "speculative" majority read.
diff --git a/src/mongo/db/read_concern_mongod.cpp b/src/mongo/db/read_concern_mongod.cpp
index 055b2378e4c..ea339471f8e 100644
--- a/src/mongo/db/read_concern_mongod.cpp
+++ b/src/mongo/db/read_concern_mongod.cpp
@@ -452,7 +452,8 @@ Status waitForReadConcernImpl(OperationContext* opCtx,
return Status::OK();
}
-Status waitForLinearizableReadConcernImpl(OperationContext* opCtx, const int readConcernTimeout) {
+Status waitForLinearizableReadConcernImpl(OperationContext* opCtx,
+ const Milliseconds readConcernTimeout) {
CurOpFailpointHelpers::waitWhileFailPointEnabled(
&hangBeforeLinearizableReadConcern, opCtx, "hangBeforeLinearizableReadConcern", [opCtx]() {
LOGV2(20994,
@@ -493,9 +494,8 @@ Status waitForLinearizableReadConcernImpl(OperationContext* opCtx, const int rea
uow.commit();
});
}
- WriteConcernOptions wc = WriteConcernOptions(
- WriteConcernOptions::kMajority, WriteConcernOptions::SyncMode::UNSET, readConcernTimeout);
-
+ WriteConcernOptions wc = WriteConcernOptions{
+ WriteConcernOptions::kMajority, WriteConcernOptions::SyncMode::UNSET, readConcernTimeout};
repl::OpTime lastOpApplied = repl::ReplClientInfo::forClient(opCtx->getClient()).getLastOp();
auto awaitReplResult = replCoord->awaitReplication(opCtx, lastOpApplied, wc);
diff --git a/src/mongo/db/read_write_concern_defaults.cpp b/src/mongo/db/read_write_concern_defaults.cpp
index 50e6ada1832..68dd5fb9477 100644
--- a/src/mongo/db/read_write_concern_defaults.cpp
+++ b/src/mongo/db/read_write_concern_defaults.cpp
@@ -91,7 +91,7 @@ void ReadWriteConcernDefaults::checkSuitabilityAsDefault(const ReadConcern& rc)
void ReadWriteConcernDefaults::checkSuitabilityAsDefault(const WriteConcern& wc) {
uassert(ErrorCodes::BadValue,
"Unacknowledged write concern is not suitable for the default write concern",
- !(wc.wMode.empty() && wc.wNumNodes < 1));
+ !wc.isUnacknowledged());
uassert(ErrorCodes::BadValue,
str::stream() << "'" << ReadWriteConcernProvenance::kSourceFieldName
<< "' must be unset in default write concern",
diff --git a/src/mongo/db/read_write_concern_defaults_test.cpp b/src/mongo/db/read_write_concern_defaults_test.cpp
index cde73217abd..9ff5cb9b9cb 100644
--- a/src/mongo/db/read_write_concern_defaults_test.cpp
+++ b/src/mongo/db/read_write_concern_defaults_test.cpp
@@ -100,7 +100,9 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithAbsentCWRWCWithImplicitWC
ASSERT(defaults.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kImplicit);
ASSERT(defaults.getDefaultWriteConcern());
- ASSERT_EQ(WriteConcernOptions::kMajority, defaults.getDefaultWriteConcern().get().wMode);
+ ASSERT(stdx::holds_alternative<std::string>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(WriteConcernOptions::kMajority,
+ stdx::get<std::string>(defaults.getDefaultWriteConcern()->w));
ASSERT(!defaults.getUpdateOpTime());
ASSERT(!defaults.getUpdateWallClockTime());
ASSERT_EQ(Date_t(), defaults.localUpdateWallClockTime());
@@ -144,7 +146,9 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithCWRWCNeverSetWithImplicit
ASSERT(defaults.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kImplicit);
ASSERT(defaults.getDefaultWriteConcern());
- ASSERT_EQ(WriteConcernOptions::kMajority, defaults.getDefaultWriteConcern().get().wMode);
+ ASSERT(stdx::holds_alternative<std::string>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(WriteConcernOptions::kMajority,
+ stdx::get<std::string>(defaults.getDefaultWriteConcern()->w));
ASSERT(!defaults.getUpdateOpTime());
ASSERT(!defaults.getUpdateWallClockTime());
ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
@@ -193,7 +197,9 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithUnsetCWRWCWithImplicitWCM
ASSERT(defaults.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kImplicit);
ASSERT(defaults.getDefaultWriteConcern());
- ASSERT_EQ(WriteConcernOptions::kMajority, defaults.getDefaultWriteConcern().get().wMode);
+ ASSERT(stdx::holds_alternative<std::string>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(WriteConcernOptions::kMajority,
+ stdx::get<std::string>(defaults.getDefaultWriteConcern()->w));
ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
@@ -222,10 +228,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithCWRWCNotSetThenSetWithImp
RWConcernDefault newDefaults;
newDefaults.setDefaultReadConcern(
repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern));
- WriteConcernOptions wc;
- wc.wNumNodes = 4;
- wc.usedDefaultConstructedWC = false;
- wc.notExplicitWValue = false;
+ WriteConcernOptions wc(
+ 4, WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoTimeout);
newDefaults.setDefaultWriteConcern(wc);
newDefaults.setUpdateOpTime(Timestamp(1, 2));
newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
@@ -239,7 +243,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithCWRWCNotSetThenSetWithImp
ASSERT(defaults.getDefaultReadConcernSource());
ASSERT(defaults.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kGlobal);
- ASSERT_EQ(4, defaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(4, stdx::get<int64_t>(defaults.getDefaultWriteConcern()->w));
ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
@@ -260,7 +265,9 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithCWRWCNotSetThenSetWithImp
ASSERT(oldDefaults.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kImplicit);
ASSERT(oldDefaults.getDefaultWriteConcern());
- ASSERT_EQ(WriteConcernOptions::kMajority, oldDefaults.getDefaultWriteConcern().get().wMode);
+ ASSERT(stdx::holds_alternative<std::string>(oldDefaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(WriteConcernOptions::kMajority,
+ stdx::get<std::string>(oldDefaults.getDefaultWriteConcern()->w));
ASSERT(!oldDefaults.getUpdateOpTime());
ASSERT(!oldDefaults.getUpdateWallClockTime());
ASSERT_GT(oldDefaults.localUpdateWallClockTime(), Date_t());
@@ -269,10 +276,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithCWRWCNotSetThenSetWithImp
RWConcernDefault newDefaults;
newDefaults.setDefaultReadConcern(
repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern));
- WriteConcernOptions wc;
- wc.wNumNodes = 4;
- wc.usedDefaultConstructedWC = false;
- wc.notExplicitWValue = false;
+ WriteConcernOptions wc(
+ 4, WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoTimeout);
newDefaults.setDefaultWriteConcern(wc);
newDefaults.setUpdateOpTime(Timestamp(1, 2));
newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
@@ -286,7 +291,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithCWRWCNotSetThenSetWithImp
ASSERT(defaults.getDefaultReadConcernSource());
ASSERT(defaults.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kGlobal);
- ASSERT_EQ(4, defaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(4, stdx::get<int64_t>(defaults.getDefaultWriteConcern()->w));
ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
@@ -300,10 +306,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetCWRWCWithImplicitWCW1)
RWConcernDefault newDefaults;
newDefaults.setDefaultReadConcern(
repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern));
- WriteConcernOptions wc;
- wc.wNumNodes = 4;
- wc.usedDefaultConstructedWC = false;
- wc.notExplicitWValue = false;
+ WriteConcernOptions wc(
+ 4, WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoTimeout);
newDefaults.setDefaultWriteConcern(wc);
newDefaults.setUpdateOpTime(Timestamp(1, 2));
newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
@@ -315,7 +319,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetCWRWCWithImplicitWCW1)
ASSERT(defaults.getDefaultReadConcernSource());
ASSERT(defaults.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kGlobal);
- ASSERT_EQ(4, defaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(4, stdx::get<int64_t>(defaults.getDefaultWriteConcern()->w));
ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
@@ -328,10 +333,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetCWRWCWithImplicitWCMaj
RWConcernDefault newDefaults;
newDefaults.setDefaultReadConcern(
repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern));
- WriteConcernOptions wc;
- wc.wNumNodes = 4;
- wc.usedDefaultConstructedWC = false;
- wc.notExplicitWValue = false;
+ WriteConcernOptions wc(
+ 4, WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoTimeout);
newDefaults.setDefaultWriteConcern(wc);
newDefaults.setUpdateOpTime(Timestamp(1, 2));
newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234));
@@ -344,7 +347,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetCWRWCWithImplicitWCMaj
ASSERT(defaults.getDefaultReadConcernSource());
ASSERT(defaults.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kGlobal);
- ASSERT_EQ(4, defaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(4, stdx::get<int64_t>(defaults.getDefaultWriteConcern()->w));
ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
@@ -372,8 +376,9 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWriteConcernSourceImplicitWit
// The default write concern source should be set to implicit if wc.usedDefaultConstructedWC is
// true
- ASSERT_EQ(0, defaults.getDefaultWriteConcern()->wNumNodes);
- ASSERT_EQ(WriteConcernOptions::kMajority, defaults.getDefaultWriteConcern().get().wMode);
+ ASSERT(stdx::holds_alternative<std::string>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(WriteConcernOptions::kMajority,
+ stdx::get<std::string>(defaults.getDefaultWriteConcern()->w));
ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
@@ -447,7 +452,9 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetAndUnSetCWRCWithImplic
ASSERT(defaults.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kGlobal);
ASSERT(defaults.getDefaultWriteConcern());
- ASSERT_EQ(WriteConcernOptions::kMajority, defaults.getDefaultWriteConcern().get().wMode);
+ ASSERT(stdx::holds_alternative<std::string>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(WriteConcernOptions::kMajority,
+ stdx::get<std::string>(defaults.getDefaultWriteConcern()->w));
ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime());
ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
@@ -470,7 +477,9 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetAndUnSetCWRCWithImplic
ASSERT(defaults.getDefaultReadConcernSource());
ASSERT(defaults.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kImplicit);
- ASSERT_EQ(WriteConcernOptions::kMajority, defaults.getDefaultWriteConcern().get().wMode);
+ ASSERT(stdx::holds_alternative<std::string>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(WriteConcernOptions::kMajority,
+ stdx::get<std::string>(defaults.getDefaultWriteConcern()->w));
ASSERT_EQ(Timestamp(1, 3), *defaults.getUpdateOpTime());
ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch());
ASSERT_GT(defaults.localUpdateWallClockTime(), Date_t());
@@ -511,10 +520,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithoutInvalidateDoesNotCallL
RWConcernDefault newDefaults2;
newDefaults2.setDefaultReadConcern(
repl::ReadConcernArgs(repl::ReadConcernLevel::kAvailableReadConcern));
- WriteConcernOptions wc;
- wc.wNumNodes = 4;
- wc.usedDefaultConstructedWC = false;
- wc.notExplicitWValue = false;
+ WriteConcernOptions wc(
+ 4, WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoTimeout);
newDefaults2.setDefaultWriteConcern(wc);
newDefaults2.setUpdateOpTime(Timestamp(3, 4));
newDefaults2.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(5678));
@@ -563,10 +570,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestInvalidate) {
RWConcernDefault newDefaults2;
newDefaults2.setDefaultReadConcern(
repl::ReadConcernArgs(repl::ReadConcernLevel::kAvailableReadConcern));
- WriteConcernOptions wc;
- wc.wNumNodes = 4;
- wc.usedDefaultConstructedWC = false;
- wc.notExplicitWValue = false;
+ WriteConcernOptions wc(
+ 4, WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoTimeout);
newDefaults2.setDefaultWriteConcern(wc);
newDefaults2.setUpdateOpTime(Timestamp(3, 4));
newDefaults2.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(5678));
@@ -580,7 +585,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestInvalidate) {
ASSERT(defaults2.getDefaultReadConcernSource());
ASSERT(defaults2.getDefaultReadConcernSource() == DefaultReadConcernSourceEnum::kGlobal);
- ASSERT_EQ(4, defaults2.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults2.getDefaultWriteConcern()->w));
+ ASSERT_EQ(4, stdx::get<int64_t>(defaults2.getDefaultWriteConcern()->w));
ASSERT_EQ(Timestamp(3, 4), *defaults2.getUpdateOpTime());
ASSERT_EQ(5678, defaults2.getUpdateWallClockTime()->toMillisSinceEpoch());
ASSERT_GT(defaults2.localUpdateWallClockTime(), Date_t());
@@ -734,7 +740,8 @@ protected:
// default read concern source is not saved on disk.
ASSERT(!defaults.getDefaultReadConcernSource());
- ASSERT_EQ(4, defaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(4, stdx::get<int64_t>(defaults.getDefaultWriteConcern()->w));
ASSERT(defaults.getUpdateOpTime());
ASSERT(defaults.getUpdateWallClockTime());
// Default write concern source is not saved on disk.
@@ -833,7 +840,8 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
repl::ReadConcernLevel::kMajorityReadConcern);
ASSERT(!defaults.getDefaultReadConcernSource());
- ASSERT_EQ(5, defaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(5, stdx::get<int64_t>(defaults.getDefaultWriteConcern()->w));
ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
// Default write concern source is not saved on disk.
@@ -858,8 +866,7 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
repl::ReadConcernLevel::kMajorityReadConcern);
ASSERT(!defaults.getDefaultReadConcernSource());
- ASSERT_EQ(oldDefaults.getDefaultWriteConcern()->wNumNodes,
- defaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(oldDefaults.getDefaultWriteConcern()->w == defaults.getDefaultWriteConcern()->w);
ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
// Default write concern source is not saved on disk.
@@ -903,7 +910,8 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
defaults.getDefaultReadConcern()->getLevel());
ASSERT(!defaults.getDefaultReadConcernSource());
- ASSERT_EQ(5, defaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(5, stdx::get<int64_t>(defaults.getDefaultWriteConcern()->w));
ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
// Default write concern source is not saved on disk.
@@ -944,7 +952,8 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
uassertStatusOK(WriteConcernOptions::parse(BSON("w" << 5))));
ASSERT(newDefaults.getDefaultReadConcern()->getLevel() ==
defaults.getDefaultReadConcern()->getLevel());
- ASSERT_EQ(5, defaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(5, stdx::get<int64_t>(defaults.getDefaultWriteConcern()->w));
// Default write concern source is not saved on disk.
ASSERT(!defaults.getDefaultWriteConcernSource());
@@ -952,7 +961,8 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
_rwcd.refreshIfNecessary(operationContext());
newDefaults = _rwcd.getDefault(operationContext());
ASSERT(newDefaults.getDefaultWriteConcern());
- ASSERT_EQ(5, newDefaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(newDefaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(5, stdx::get<int64_t>(newDefaults.getDefaultWriteConcern()->w));
// Default write concern source is calculated through 'getDefault'.
ASSERT(newDefaults.getDefaultWriteConcernSource() == DefaultWriteConcernSourceEnum::kGlobal);
}
@@ -967,8 +977,7 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
ASSERT(!defaults.getDefaultReadConcernSource());
ASSERT(defaults.getDefaultWriteConcern());
- ASSERT_EQ(oldDefaults.getDefaultWriteConcern()->wNumNodes,
- defaults.getDefaultWriteConcern()->wNumNodes);
+ ASSERT(oldDefaults.getDefaultWriteConcern()->w == defaults.getDefaultWriteConcern()->w);
ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
// Default write concern source is not saved on disk.
@@ -1033,8 +1042,9 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
ASSERT(oldDefaults.getDefaultReadConcern()->getLevel() ==
defaults.getDefaultReadConcern()->getLevel());
ASSERT(!defaults.getDefaultReadConcernSource());
- ASSERT_EQ(1, defaults.getDefaultWriteConcern()->wNumNodes);
- ASSERT_EQ(0, defaults.getDefaultWriteConcern()->wTimeout);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(1, stdx::get<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(WriteConcernOptions::kNoTimeout, defaults.getDefaultWriteConcern()->wTimeout);
ASSERT(WriteConcernOptions::SyncMode::JOURNAL == defaults.getDefaultWriteConcern()->syncMode);
ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
@@ -1059,8 +1069,9 @@ TEST_F(ReadWriteConcernDefaultsTestWithClusterTime,
ASSERT(oldDefaults.getDefaultReadConcern()->getLevel() ==
defaults.getDefaultReadConcern()->getLevel());
ASSERT(!defaults.getDefaultReadConcernSource());
- ASSERT_EQ(1, defaults.getDefaultWriteConcern()->wNumNodes);
- ASSERT_EQ(12345, defaults.getDefaultWriteConcern()->wTimeout);
+ ASSERT(stdx::holds_alternative<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(1, stdx::get<int64_t>(defaults.getDefaultWriteConcern()->w));
+ ASSERT_EQ(Milliseconds(12345), defaults.getDefaultWriteConcern()->wTimeout);
ASSERT(WriteConcernOptions::SyncMode::UNSET == defaults.getDefaultWriteConcern()->syncMode);
ASSERT_LT(*oldDefaults.getUpdateOpTime(), *defaults.getUpdateOpTime());
ASSERT_LT(*oldDefaults.getUpdateWallClockTime(), *defaults.getUpdateWallClockTime());
diff --git a/src/mongo/db/repl/repl_set_config.cpp b/src/mongo/db/repl/repl_set_config.cpp
index c2d355833de..9ed67568c77 100644
--- a/src/mongo/db/repl/repl_set_config.cpp
+++ b/src/mongo/db/repl/repl_set_config.cpp
@@ -35,6 +35,7 @@
#include <algorithm>
#include <fmt/format.h>
+#include <fmt/ranges.h>
#include <functional>
#include "mongo/bson/util/bson_check.h"
@@ -427,40 +428,46 @@ Status ReplSetConfig::_validate(bool allowSplitHorizonIP) const {
Status ReplSetConfig::checkIfWriteConcernCanBeSatisfied(
const WriteConcernOptions& writeConcern) const {
- if (writeConcern.hasCustomWriteMode()) {
- StatusWith<ReplSetTagPattern> tagPatternStatus = findCustomWriteMode(writeConcern.wMode);
- if (!tagPatternStatus.isOK()) {
- return tagPatternStatus.getStatus();
+ if (auto wNumNodes = stdx::get_if<int64_t>(&writeConcern.w)) {
+ if (*wNumNodes > getNumDataBearingMembers()) {
+ return Status(ErrorCodes::UnsatisfiableWriteConcern, "Not enough data-bearing nodes");
}
- ReplSetTagMatch matcher(tagPatternStatus.getValue());
- for (size_t j = 0; j < getMembers().size(); ++j) {
- const MemberConfig& memberConfig = getMembers()[j];
- for (MemberConfig::TagIterator it = memberConfig.tagsBegin();
- it != memberConfig.tagsEnd();
- ++it) {
- if (matcher.update(*it)) {
- return Status::OK();
- }
- }
- }
- // Even if all the nodes in the set had a given write it still would not satisfy this
- // write concern mode.
- return Status(ErrorCodes::UnsatisfiableWriteConcern,
- str::stream() << "Not enough nodes match write concern mode \""
- << writeConcern.wMode << "\"");
- } else {
- int nodesRemaining = writeConcern.wNumNodes;
- for (size_t j = 0; j < getMembers().size(); ++j) {
- if (!getMembers()[j].isArbiter()) { // Only count data-bearing nodes
- --nodesRemaining;
- if (nodesRemaining <= 0) {
- return Status::OK();
- }
+ return Status::OK();
+ }
+
+ StatusWith<ReplSetTagPattern> tagPatternStatus = [&]() {
+ auto wMode = stdx::get_if<std::string>(&writeConcern.w);
+ return wMode ? findCustomWriteMode(*wMode)
+ : makeCustomWriteMode(stdx::get<WTags>(writeConcern.w));
+ }();
+
+ if (!tagPatternStatus.isOK()) {
+ return tagPatternStatus.getStatus();
+ }
+
+ ReplSetTagMatch matcher(tagPatternStatus.getValue());
+ for (size_t j = 0; j < getMembers().size(); ++j) {
+ const MemberConfig& memberConfig = getMembers()[j];
+ for (MemberConfig::TagIterator it = memberConfig.tagsBegin(); it != memberConfig.tagsEnd();
+ ++it) {
+ if (matcher.update(*it)) {
+ return Status::OK();
}
}
- return Status(ErrorCodes::UnsatisfiableWriteConcern, "Not enough data-bearing nodes");
}
+
+ // Even if all the nodes in the set had a given write it still would not satisfy this
+ // write concern mode.
+ auto wModeForError = [&]() {
+ auto wMode = stdx::get_if<std::string>(&writeConcern.w);
+ return wMode ? fmt::format("\"{}\"", *wMode)
+ : fmt::format("{}", stdx::get<WTags>(writeConcern.w));
+ }();
+
+ return Status(ErrorCodes::UnsatisfiableWriteConcern,
+ str::stream() << "Not enough nodes match write concern mode \"" << wModeForError
+ << "\"");
}
int ReplSetConfig::getNumDataBearingMembers() const {
@@ -534,31 +541,25 @@ ReplSetTag ReplSetConfig::findTag(StringData key, StringData value) const {
}
StatusWith<ReplSetTagPattern> ReplSetConfig::findCustomWriteMode(StringData patternName) const {
+ // The string "majority" corresponds to the internal "$majority" custom write mode
+ if (patternName == WriteConcernOptions::kMajority) {
+ patternName = kMajorityWriteConcernModeName;
+ }
+
const StringMap<ReplSetTagPattern>::const_iterator iter =
_customWriteConcernModes.find(patternName);
if (iter == _customWriteConcernModes.end()) {
return StatusWith<ReplSetTagPattern>(
ErrorCodes::UnknownReplWriteConcern,
- str::stream() << "No write concern mode named '" << str::escape(patternName.toString())
- << "' found in replica set configuration");
+ "No write concern mode named '{}' found in replica set configuration"_format(
+ str::escape(patternName.toString())));
}
return StatusWith<ReplSetTagPattern>(iter->second);
}
-StatusWith<ReplSetTagPattern> ReplSetConfig::makeCustomWriteMode(const BSONObj& wTags) const {
+StatusWith<ReplSetTagPattern> ReplSetConfig::makeCustomWriteMode(const WTags& wTags) const {
ReplSetTagPattern pattern = _tagConfig.makePattern();
- for (auto e : wTags) {
- const auto tagName = e.fieldNameStringData();
- if (!e.isNumber()) {
- return {
- ErrorCodes::BadValue,
- fmt::format(
- "Custom write mode only supports integer values, found: \"{}\" for tag: \"{}\"",
- e.toString(),
- tagName)};
- }
-
- const auto minNodesWithTag = e.safeNumberInt();
+ for (const auto& [tagName, minNodesWithTag] : wTags) {
auto status = _tagConfig.addTagCountConstraintToPattern(&pattern, tagName, minNodesWithTag);
if (!status.isOK()) {
return status;
@@ -734,13 +735,19 @@ bool ReplSetConfig::containsCustomizedGetLastErrorDefaults() const {
// Since the ReplSetConfig always has a WriteConcernOptions, the only way to know if it has been
// customized through getLastErrorDefaults is if it's different from { w: 1, wtimeout: 0 }.
const auto& getLastErrorDefaults = getDefaultWriteConcern();
- return !(getLastErrorDefaults.wNumNodes == 1 && getLastErrorDefaults.wTimeout == 0 &&
- getLastErrorDefaults.syncMode == WriteConcernOptions::SyncMode::UNSET);
+ if (auto wNumNodes = stdx::get_if<int64_t>(&getLastErrorDefaults.w);
+ !wNumNodes || *wNumNodes != 1)
+ return true;
+ if (getLastErrorDefaults.wTimeout != Milliseconds::zero())
+ return true;
+ if (getLastErrorDefaults.syncMode != WriteConcernOptions::SyncMode::UNSET)
+ return true;
+ return false;
}
Status ReplSetConfig::validateWriteConcern(const WriteConcernOptions& writeConcern) const {
if (writeConcern.hasCustomWriteMode()) {
- return findCustomWriteMode(writeConcern.wMode).getStatus();
+ return findCustomWriteMode(stdx::get<std::string>(writeConcern.w)).getStatus();
}
return Status::OK();
}
diff --git a/src/mongo/db/repl/repl_set_config.h b/src/mongo/db/repl/repl_set_config.h
index 0ff4711f14d..5e410b65963 100644
--- a/src/mongo/db/repl/repl_set_config.h
+++ b/src/mongo/db/repl/repl_set_config.h
@@ -436,7 +436,7 @@ public:
* @returns `ErrorCodes::NoSuchKey` if a tag was provided which is not found in
* the local tag config.
*/
- StatusWith<ReplSetTagPattern> makeCustomWriteMode(const BSONObj& wTags) const;
+ StatusWith<ReplSetTagPattern> makeCustomWriteMode(const WTags& wTags) const;
/**
* Returns the "tags configuration" for this replicaset.
diff --git a/src/mongo/db/repl/repl_set_config_test.cpp b/src/mongo/db/repl/repl_set_config_test.cpp
index 5ebf3e6ac69..f93aa2e962a 100644
--- a/src/mongo/db/repl/repl_set_config_test.cpp
+++ b/src/mongo/db/repl/repl_set_config_test.cpp
@@ -93,8 +93,8 @@ TEST(ReplSetConfig, ParseMinimalConfigAndCheckDefaults) {
ASSERT_EQUALS(1, config.getConfigTerm());
ASSERT_EQUALS(1, config.getNumMembers());
ASSERT_EQUALS(MemberId(0), config.membersBegin()->getId());
- ASSERT_EQUALS(1, config.getDefaultWriteConcern().wNumNodes);
- ASSERT_EQUALS("", config.getDefaultWriteConcern().wMode);
+ ASSERT(stdx::holds_alternative<int64_t>(config.getDefaultWriteConcern().w));
+ ASSERT_EQUALS(1, stdx::get<int64_t>(config.getDefaultWriteConcern().w));
ASSERT_EQUALS(ReplSetConfig::kDefaultHeartbeatInterval, config.getHeartbeatInterval());
ASSERT_EQUALS(ReplSetConfig::kDefaultHeartbeatTimeoutPeriod,
config.getHeartbeatTimeoutPeriod());
@@ -1272,8 +1272,7 @@ bool operator==(const ReplSetConfig& a, const ReplSetConfig& b) {
a.getElectionTimeoutPeriod() == b.getElectionTimeoutPeriod() &&
a.isChainingAllowed() == b.isChainingAllowed() &&
a.getConfigServer() == b.getConfigServer() &&
- a.getDefaultWriteConcern().wNumNodes == b.getDefaultWriteConcern().wNumNodes &&
- a.getDefaultWriteConcern().wMode == b.getDefaultWriteConcern().wMode &&
+ a.getDefaultWriteConcern().w == b.getDefaultWriteConcern().w &&
a.getProtocolVersion() == b.getProtocolVersion() &&
a.getReplicaSetId() == b.getReplicaSetId();
}
@@ -1476,34 +1475,34 @@ TEST(ReplSetConfig, CheckIfWriteConcernCanBeSatisfied) {
<< BSON("dc" << 3) << "invalidNotEnoughNodes" << BSON("rack" << 6)))));
WriteConcernOptions validNumberWC;
- validNumberWC.wNumNodes = 5;
+ validNumberWC.w = 5;
ASSERT_OK(configA.checkIfWriteConcernCanBeSatisfied(validNumberWC));
WriteConcernOptions invalidNumberWC;
- invalidNumberWC.wNumNodes = 6;
+ invalidNumberWC.w = 6;
ASSERT_EQUALS(ErrorCodes::UnsatisfiableWriteConcern,
configA.checkIfWriteConcernCanBeSatisfied(invalidNumberWC));
WriteConcernOptions majorityWC;
- majorityWC.wMode = "majority";
+ majorityWC.w = "majority";
ASSERT_OK(configA.checkIfWriteConcernCanBeSatisfied(majorityWC));
WriteConcernOptions validModeWC;
- validModeWC.wMode = "valid";
+ validModeWC.w = "valid";
ASSERT_OK(configA.checkIfWriteConcernCanBeSatisfied(validModeWC));
WriteConcernOptions fakeModeWC;
- fakeModeWC.wMode = "fake";
+ fakeModeWC.w = "fake";
ASSERT_EQUALS(ErrorCodes::UnknownReplWriteConcern,
configA.checkIfWriteConcernCanBeSatisfied(fakeModeWC));
WriteConcernOptions invalidModeNotEnoughValuesWC;
- invalidModeNotEnoughValuesWC.wMode = "invalidNotEnoughValues";
+ invalidModeNotEnoughValuesWC.w = "invalidNotEnoughValues";
ASSERT_EQUALS(ErrorCodes::UnsatisfiableWriteConcern,
configA.checkIfWriteConcernCanBeSatisfied(invalidModeNotEnoughValuesWC));
WriteConcernOptions invalidModeNotEnoughNodesWC;
- invalidModeNotEnoughNodesWC.wMode = "invalidNotEnoughNodes";
+ invalidModeNotEnoughNodesWC.w = "invalidNotEnoughNodes";
ASSERT_EQUALS(ErrorCodes::UnsatisfiableWriteConcern,
configA.checkIfWriteConcernCanBeSatisfied(invalidModeNotEnoughNodesWC));
}
@@ -2102,16 +2101,11 @@ TEST(ReplSetConfig, MakeCustomWriteMode) {
<< BSON("NYC"
<< "NY")))));
- auto swPattern = config.makeCustomWriteMode(BSON("NYC"
- << "invalid value type"));
- ASSERT_FALSE(swPattern.isOK());
- ASSERT_EQ(swPattern.getStatus().code(), ErrorCodes::BadValue);
-
- swPattern = config.makeCustomWriteMode(BSON("NonExistentTag" << 1));
+ auto swPattern = config.makeCustomWriteMode({{"NonExistentTag", 1}});
ASSERT_FALSE(swPattern.isOK());
ASSERT_EQ(swPattern.getStatus().code(), ErrorCodes::NoSuchKey);
- swPattern = config.makeCustomWriteMode(BSON("NYC" << 1));
+ swPattern = config.makeCustomWriteMode({{"NYC", 1}});
ASSERT_TRUE(swPattern.isOK());
}
diff --git a/src/mongo/db/repl/repl_set_config_validators.h b/src/mongo/db/repl/repl_set_config_validators.h
index c02cfb1ee15..56eb9e80dd8 100644
--- a/src/mongo/db/repl/repl_set_config_validators.h
+++ b/src/mongo/db/repl/repl_set_config_validators.h
@@ -49,10 +49,11 @@ inline Status validateTrue(bool boolVal) {
}
inline Status validateDefaultWriteConcernHasMember(const WriteConcernOptions& defaultWriteConcern) {
- if (defaultWriteConcern.wMode.empty() && defaultWriteConcern.wNumNodes == 0) {
+ if (defaultWriteConcern.isUnacknowledged()) {
return Status(ErrorCodes::BadValue,
"Default write concern mode must wait for at least 1 member");
}
+
return Status::OK();
}
diff --git a/src/mongo/db/repl/replication_coordinator.h b/src/mongo/db/repl/replication_coordinator.h
index 12dd736fdd0..cbd90683591 100644
--- a/src/mongo/db/repl/replication_coordinator.h
+++ b/src/mongo/db/repl/replication_coordinator.h
@@ -225,7 +225,7 @@ public:
* ErrorCodes::ExceededTimeLimit if the opCtx->getMaxTimeMicrosRemaining is reached before
* the data has been sufficiently replicated
* ErrorCodes::NotWritablePrimary if the node is not a writable primary
- * ErrorCodes::UnknownReplWriteConcern if the writeConcern.wMode contains a write concern
+ * ErrorCodes::UnknownReplWriteConcern if the writeConcern.w contains a write concern
* mode that is not known
* ErrorCodes::ShutdownInProgress if we are mid-shutdown
* ErrorCodes::Interrupted if the operation was killed with killop()
diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp
index 0021211d17e..391011091c9 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -1895,17 +1895,19 @@ bool ReplicationCoordinatorImpl::_doneWaitingForReplication_inlock(
invariant(writeConcern.syncMode != WriteConcernOptions::SyncMode::UNSET);
const bool useDurableOpTime = writeConcern.syncMode == WriteConcernOptions::SyncMode::JOURNAL;
- if (writeConcern.wMode.empty()) {
- if (writeConcern.wTags()) {
- auto tagPattern = uassertStatusOK(_rsConfig.makeCustomWriteMode(*writeConcern.wTags()));
+ if (!stdx::holds_alternative<std::string>(writeConcern.w)) {
+ if (auto wTags = stdx::get_if<WTags>(&writeConcern.w)) {
+ auto tagPattern = uassertStatusOK(_rsConfig.makeCustomWriteMode(*wTags));
return _topCoord->haveTaggedNodesReachedOpTime(opTime, tagPattern, useDurableOpTime);
}
return _topCoord->haveNumNodesReachedOpTime(
- opTime, writeConcern.wNumNodes, useDurableOpTime);
+ opTime, stdx::get<int64_t>(writeConcern.w), useDurableOpTime);
}
+
StringData patternName;
- if (writeConcern.wMode == WriteConcernOptions::kMajority) {
+ auto wMode = stdx::get<std::string>(writeConcern.w);
+ if (wMode == WriteConcernOptions::kMajority) {
if (_externalState->snapshotsEnabled() && !gTestingSnapshotBehaviorInIsolation) {
// Make sure we have a valid "committed" snapshot up to the needed optime.
if (!_currentCommittedSnapshot) {
@@ -1955,8 +1957,9 @@ bool ReplicationCoordinatorImpl::_doneWaitingForReplication_inlock(
// *** Needed for J:True, writeConcernMajorityShouldJournal:False (appliedOpTime snapshot).
patternName = ReplSetConfig::kMajorityWriteConcernModeName;
} else {
- patternName = writeConcern.wMode;
+ patternName = wMode;
}
+
auto tagPattern = uassertStatusOK(_rsConfig.findCustomWriteMode(patternName));
if (writeConcern.checkCondition == WriteConcernOptions::CheckCondition::OpTime) {
return _topCoord->haveTaggedNodesReachedOpTime(opTime, tagPattern, useDurableOpTime);
@@ -5921,8 +5924,7 @@ WriteConcernOptions ReplicationCoordinatorImpl::_populateUnsetWriteConcernOption
WithLock lk, WriteConcernOptions wc) {
WriteConcernOptions writeConcern(wc);
if (writeConcern.syncMode == WriteConcernOptions::SyncMode::UNSET) {
- if (writeConcern.wMode == WriteConcernOptions::kMajority &&
- getWriteConcernMajorityShouldJournal_inlock()) {
+ if (writeConcern.isMajority() && getWriteConcernMajorityShouldJournal_inlock()) {
writeConcern.syncMode = WriteConcernOptions::SyncMode::JOURNAL;
} else {
writeConcern.syncMode = WriteConcernOptions::SyncMode::NONE;
diff --git a/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp
index f738cc855f0..781c10f0df0 100644
--- a/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp
@@ -881,10 +881,8 @@ TEST_F(ReplCoordTest, ReconfigThatChangesIDWCFromW1toWMajWithoutCWWCSetFails) {
TEST_F(ReplCoordTest, ReconfigThatChangesIDWCWMajToW1WithCWWCSetPasses) {
RWConcernDefault newDefaults;
- WriteConcernOptions wc;
- wc.wMode = "majority";
- wc.usedDefaultConstructedWC = false;
- wc.notExplicitWValue = false;
+ WriteConcernOptions wc(
+ "majority", WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoTimeout);
newDefaults.setDefaultWriteConcern(wc);
lookupMock.setLookupCallReturnValue(std::move(newDefaults));
@@ -944,10 +942,8 @@ TEST_F(ReplCoordTest, ReconfigThatChangesIDWCWMajToW1WithCWWCSetPasses) {
TEST_F(ReplCoordTest, ReconfigThatChangesIDWCW1ToWMajWithCWWCSetPasses) {
RWConcernDefault newDefaults;
- WriteConcernOptions wc;
- wc.wMode = "majority";
- wc.usedDefaultConstructedWC = false;
- wc.notExplicitWValue = false;
+ WriteConcernOptions wc(
+ "majority", WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoTimeout);
newDefaults.setDefaultWriteConcern(wc);
lookupMock.setLookupCallReturnValue(std::move(newDefaults));
@@ -2270,10 +2266,8 @@ TEST_F(ReplCoordReconfigTest, NodesWithNewlyAddedFieldSetHavePriorityZero) {
TEST_F(ReplCoordReconfigTest, ArbiterNodesShouldNeverHaveNewlyAddedField) {
RWConcernDefault newDefaults;
- WriteConcernOptions wc;
- wc.wMode = "majority";
- wc.usedDefaultConstructedWC = false;
- wc.notExplicitWValue = false;
+ WriteConcernOptions wc(
+ "majority", WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoTimeout);
newDefaults.setDefaultWriteConcern(wc);
lookupMock.setLookupCallReturnValue(std::move(newDefaults));
diff --git a/src/mongo/db/repl/replication_coordinator_impl_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_test.cpp
index 9fcd9adf9b8..cf9efee882b 100644
--- a/src/mongo/db/repl/replication_coordinator_impl_test.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl_test.cpp
@@ -624,7 +624,7 @@ TEST_F(ReplCoordTest, NodeReturnsImmediatelyWhenAwaitReplicationIsRanAgainstASta
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- writeConcern.wNumNodes = 2;
+ writeConcern.w = 2;
// Because we didn't set ReplSettings.replSet, it will think we're a standalone so
// awaitReplication will always work.
@@ -652,10 +652,9 @@ TEST_F(ReplCoordTest, NodeReturnsNotPrimaryWhenRunningAwaitReplicationAgainstASe
OpTimeWithTermOne time(100, 1);
- WriteConcernOptions writeConcern;
- writeConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- writeConcern.wNumNodes = 0; // Waiting for 0 nodes always works
- writeConcern.wMode = "";
+ // Waiting for 0 nodes always works
+ WriteConcernOptions writeConcern(
+ 0, WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoWaiting);
// Node should fail to awaitReplication when not primary.
ReplicationCoordinator::StatusAndDuration statusAndDur =
@@ -680,10 +679,9 @@ TEST_F(ReplCoordTest, NodeReturnsOkWhenRunningAwaitReplicationAgainstPrimaryWith
OpTimeWithTermOne time(100, 1);
- WriteConcernOptions writeConcern;
- writeConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- writeConcern.wNumNodes = 0; // Waiting for 0 nodes always works
- writeConcern.wMode = "";
+ // Waiting for 0 nodes always works
+ WriteConcernOptions writeConcern(
+ 0, WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoWaiting);
// Become primary.
ASSERT_OK(getReplCoord()->setFollowerMode(MemberState::RS_SECONDARY));
@@ -727,7 +725,7 @@ TEST_F(ReplCoordTest,
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- writeConcern.wNumNodes = 1;
+ writeConcern.w = 1;
writeConcern.syncMode = WriteConcernOptions::SyncMode::JOURNAL;
auto opCtx = makeOperationContext();
@@ -741,7 +739,7 @@ TEST_F(ReplCoordTest,
ASSERT_OK(statusAndDur.status);
// 2 nodes waiting for time1
- writeConcern.wNumNodes = 2;
+ writeConcern.w = 2;
statusAndDur = getReplCoord()->awaitReplication(opCtx.get(), time1, writeConcern);
ASSERT_EQUALS(ErrorCodes::WriteConcernFailed, statusAndDur.status);
// Applied is not durable and will not satisfy WriteConcern with SyncMode JOURNAL.
@@ -765,7 +763,7 @@ TEST_F(ReplCoordTest,
ASSERT_OK(statusAndDur.status);
// 3 nodes waiting for time2
- writeConcern.wNumNodes = 3;
+ writeConcern.w = 3;
statusAndDur = getReplCoord()->awaitReplication(opCtx.get(), time2, writeConcern);
ASSERT_EQUALS(ErrorCodes::WriteConcernFailed, statusAndDur.status);
ASSERT_OK(getReplCoord()->setLastAppliedOptime_forTest(2, 3, time2));
@@ -801,7 +799,7 @@ TEST_F(ReplCoordTest, NodeReturnsWriteConcernFailedUntilASufficientNumberOfNodes
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- writeConcern.wNumNodes = 1;
+ writeConcern.w = 1;
auto opCtx = makeOperationContext();
@@ -816,7 +814,7 @@ TEST_F(ReplCoordTest, NodeReturnsWriteConcernFailedUntilASufficientNumberOfNodes
ASSERT_OK(statusAndDur.status);
// 2 nodes waiting for time1
- writeConcern.wNumNodes = 2;
+ writeConcern.w = 2;
statusAndDur = getReplCoord()->awaitReplication(opCtx.get(), time1, writeConcern);
ASSERT_EQUALS(ErrorCodes::WriteConcernFailed, statusAndDur.status);
ASSERT_OK(getReplCoord()->setLastAppliedOptime_forTest(2, 1, time1));
@@ -836,7 +834,7 @@ TEST_F(ReplCoordTest, NodeReturnsWriteConcernFailedUntilASufficientNumberOfNodes
ASSERT_OK(statusAndDur.status);
// 3 nodes waiting for time2
- writeConcern.wNumNodes = 3;
+ writeConcern.w = 3;
statusAndDur = getReplCoord()->awaitReplication(opCtx.get(), time2, writeConcern);
ASSERT_EQUALS(ErrorCodes::WriteConcernFailed, statusAndDur.status);
ASSERT_OK(getReplCoord()->setLastAppliedOptime_forTest(2, 3, time2));
@@ -871,7 +869,7 @@ TEST_F(ReplCoordTest,
// Test invalid write concern
WriteConcernOptions invalidWriteConcern;
invalidWriteConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- invalidWriteConcern.wMode = "fakemode";
+ invalidWriteConcern.w = "fakemode";
auto opCtx = makeOperationContext();
ReplicationCoordinator::StatusAndDuration statusAndDur =
@@ -936,16 +934,16 @@ TEST_F(
// Set up valid write concerns for the rest of the test
WriteConcernOptions majorityWriteConcern;
majorityWriteConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- majorityWriteConcern.wMode = WriteConcernOptions::kMajority;
+ majorityWriteConcern.w = WriteConcernOptions::kMajority;
majorityWriteConcern.syncMode = WriteConcernOptions::SyncMode::JOURNAL;
WriteConcernOptions multiDCWriteConcern;
multiDCWriteConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- multiDCWriteConcern.wMode = "multiDC";
+ multiDCWriteConcern.w = "multiDC";
WriteConcernOptions multiRackWriteConcern;
multiRackWriteConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- multiRackWriteConcern.wMode = "multiDCAndRack";
+ multiRackWriteConcern.w = "multiDCAndRack";
auto opCtx = makeOperationContext();
// Nothing satisfied
@@ -1090,7 +1088,7 @@ TEST_F(ReplCoordTest, NodeReturnsOkWhenAWriteConcernWithNoTimeoutHasBeenSatisfie
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoTimeout;
- writeConcern.wNumNodes = 2;
+ writeConcern.w = 2;
// 2 nodes waiting for time1
awaiter.setOpTime(time1);
@@ -1114,7 +1112,7 @@ TEST_F(ReplCoordTest, NodeReturnsOkWhenAWriteConcernWithNoTimeoutHasBeenSatisfie
awaiter.reset();
// 3 nodes waiting for time2
- writeConcern.wNumNodes = 3;
+ writeConcern.w = 3;
awaiter.setWriteConcern(writeConcern);
awaiter.start();
ASSERT_OK(getReplCoord()->setLastAppliedOptime_forTest(2, 2, time2));
@@ -1311,7 +1309,7 @@ TEST_F(ReplCoordTest, NodeReturnsWriteConcernFailedWhenAWriteConcernTimesOutBefo
WriteConcernOptions writeConcern;
writeConcern.wDeadline = getNet()->now() + Milliseconds(50);
- writeConcern.wNumNodes = 2;
+ writeConcern.w = 2;
// 2 nodes waiting for time2
awaiter.setOpTime(time2);
@@ -1357,7 +1355,7 @@ TEST_F(ReplCoordTest,
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoTimeout;
- writeConcern.wNumNodes = 2;
+ writeConcern.w = 2;
// 2 nodes waiting for time2
awaiter.setOpTime(time2);
@@ -1453,7 +1451,7 @@ TEST_F(ReplCoordTest, NodeReturnsNotPrimaryWhenSteppingDownBeforeSatisfyingAWrit
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoTimeout;
- writeConcern.wNumNodes = 2;
+ writeConcern.w = 2;
// 2 nodes waiting for time2
awaiter.setOpTime(time2);
@@ -1492,7 +1490,7 @@ TEST_F(ReplCoordTest,
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoTimeout;
- writeConcern.wNumNodes = 2;
+ writeConcern.w = 2;
// 2 nodes waiting for time2
@@ -5113,7 +5111,7 @@ TEST_F(ReplCoordTest, DoNotProcessSelfWhenUpdatePositionContainsInfoAboutSelf) {
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- writeConcern.wNumNodes = 1;
+ writeConcern.w = 1;
auto opCtx = makeOperationContext();
@@ -5163,7 +5161,7 @@ TEST_F(ReplCoordTest, ProcessUpdatePositionWhenItsConfigVersionIsDifferent) {
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- writeConcern.wNumNodes = 1;
+ writeConcern.w = 1;
// receive updatePosition with a different config version, 3
replCoordSetMyLastAppliedOpTime(time2, Date_t() + Seconds(100));
@@ -5214,7 +5212,7 @@ TEST_F(ReplCoordTest, DoNotProcessUpdatePositionOfMembersWhoseIdsAreNotInTheConf
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- writeConcern.wNumNodes = 1;
+ writeConcern.w = 1;
// receive updatePosition with nonexistent member id
UpdatePositionArgs args;
@@ -5266,7 +5264,7 @@ TEST_F(ReplCoordTest,
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- writeConcern.wNumNodes = 1;
+ writeConcern.w = 1;
// receive a good update position
replCoordSetMyLastAppliedOpTime(time2, Date_t() + Seconds(100));
@@ -5299,7 +5297,7 @@ TEST_F(ReplCoordTest,
ASSERT_OK(getReplCoord()->processReplSetUpdatePosition(args));
ASSERT_OK(getReplCoord()->awaitReplication(opCtx.get(), time2, writeConcern).status);
- writeConcern.wNumNodes = 3;
+ writeConcern.w = 3;
ASSERT_OK(getReplCoord()->awaitReplication(opCtx.get(), time2, writeConcern).status);
}
@@ -5414,7 +5412,7 @@ TEST_F(ReplCoordTest, AwaitReplicationShouldResolveAsNormalDuringAReconfig) {
// 3 nodes waiting for time
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoTimeout;
- writeConcern.wNumNodes = 3;
+ writeConcern.w = 3;
writeConcern.syncMode = WriteConcernOptions::SyncMode::NONE;
ReplicationAwaiter awaiter(getReplCoord(), getServiceContext());
@@ -5423,7 +5421,7 @@ TEST_F(ReplCoordTest, AwaitReplicationShouldResolveAsNormalDuringAReconfig) {
awaiter.start();
ReplicationAwaiter awaiterJournaled(getReplCoord(), getServiceContext());
- writeConcern.wMode = WriteConcernOptions::kMajority;
+ writeConcern.w = WriteConcernOptions::kMajority;
awaiterJournaled.setOpTime(time);
awaiterJournaled.setWriteConcern(writeConcern);
awaiterJournaled.start();
@@ -5563,19 +5561,13 @@ TEST_F(
// 3 nodes waiting for time
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoTimeout;
- writeConcern.wNumNodes = 3;
+ writeConcern.w = 3;
ReplicationAwaiter awaiter(getReplCoord(), getServiceContext());
awaiter.setOpTime(time);
awaiter.setWriteConcern(writeConcern);
awaiter.start();
- ReplicationAwaiter awaiterJournaled(getReplCoord(), getServiceContext());
- writeConcern.wMode = WriteConcernOptions::kMajority;
- awaiterJournaled.setOpTime(time);
- awaiterJournaled.setWriteConcern(writeConcern);
- awaiterJournaled.start();
-
// reconfig to fewer nodes
Status status(ErrorCodes::InternalError, "Not Set");
stdx::thread reconfigThread(
@@ -5590,9 +5582,6 @@ TEST_F(
ReplicationCoordinator::StatusAndDuration statusAndDur = awaiter.getResult();
ASSERT_EQUALS(ErrorCodes::UnsatisfiableWriteConcern, statusAndDur.status);
awaiter.reset();
- ReplicationCoordinator::StatusAndDuration statusAndDurJournaled = awaiterJournaled.getResult();
- ASSERT_EQUALS(ErrorCodes::UnsatisfiableWriteConcern, statusAndDurJournaled.status);
- awaiterJournaled.reset();
}
TEST_F(ReplCoordTest,
@@ -5637,7 +5626,7 @@ TEST_F(ReplCoordTest,
// majority nodes waiting for time
WriteConcernOptions writeConcern;
writeConcern.wTimeout = WriteConcernOptions::kNoTimeout;
- writeConcern.wMode = WriteConcernOptions::kMajority;
+ writeConcern.w = WriteConcernOptions::kMajority;
writeConcern.syncMode = WriteConcernOptions::SyncMode::NONE;
@@ -5649,7 +5638,7 @@ TEST_F(ReplCoordTest,
// demonstrate that majority cannot currently be satisfied
WriteConcernOptions writeConcern2;
writeConcern2.wTimeout = WriteConcernOptions::kNoWaiting;
- writeConcern2.wMode = WriteConcernOptions::kMajority;
+ writeConcern2.w = WriteConcernOptions::kMajority;
writeConcern.syncMode = WriteConcernOptions::SyncMode::NONE;
ASSERT_EQUALS(ErrorCodes::WriteConcernFailed,
@@ -5702,7 +5691,7 @@ TEST_F(ReplCoordTest,
WriteConcernOptions majorityWriteConcern;
majorityWriteConcern.wTimeout = WriteConcernOptions::kNoWaiting;
- majorityWriteConcern.wMode = WriteConcernOptions::kMajority;
+ majorityWriteConcern.w = WriteConcernOptions::kMajority;
majorityWriteConcern.syncMode = WriteConcernOptions::SyncMode::JOURNAL;
auto opCtx = makeOperationContext();
@@ -7414,7 +7403,7 @@ TEST_F(
HostAndPort("test1", 1234));
WriteConcernOptions wc;
- wc.wMode = WriteConcernOptions::kMajority;
+ wc.w = WriteConcernOptions::kMajority;
wc.syncMode = WriteConcernOptions::SyncMode::UNSET;
ASSERT(WriteConcernOptions::SyncMode::NONE ==
getReplCoord()->populateUnsetWriteConcernOptionsSyncMode(wc).syncMode);
@@ -7434,7 +7423,7 @@ TEST_F(
HostAndPort("test1", 1234));
WriteConcernOptions wc;
- wc.wMode = WriteConcernOptions::kMajority;
+ wc.w = WriteConcernOptions::kMajority;
wc.syncMode = WriteConcernOptions::SyncMode::UNSET;
ASSERT(WriteConcernOptions::SyncMode::JOURNAL ==
getReplCoord()->populateUnsetWriteConcernOptionsSyncMode(wc).syncMode);
@@ -7452,7 +7441,7 @@ TEST_F(ReplCoordTest, PopulateUnsetWriteConcernOptionsSyncModeReturnsInputIfSync
HostAndPort("test1", 1234));
WriteConcernOptions wc;
- wc.wMode = WriteConcernOptions::kMajority;
+ wc.w = WriteConcernOptions::kMajority;
ASSERT(WriteConcernOptions::SyncMode::NONE ==
getReplCoord()->populateUnsetWriteConcernOptionsSyncMode(wc).syncMode);
@@ -7478,11 +7467,11 @@ TEST_F(ReplCoordTest, PopulateUnsetWriteConcernOptionsSyncModeReturnsInputIfWMod
WriteConcernOptions wc;
wc.syncMode = WriteConcernOptions::SyncMode::UNSET;
- wc.wMode = "not the value of kMajority";
+ wc.w = "not the value of kMajority";
ASSERT(WriteConcernOptions::SyncMode::NONE ==
getReplCoord()->populateUnsetWriteConcernOptionsSyncMode(wc).syncMode);
- wc.wMode = "like literally anythingelse";
+ wc.w = "like literally anythingelse";
ASSERT(WriteConcernOptions::SyncMode::NONE ==
getReplCoord()->populateUnsetWriteConcernOptionsSyncMode(wc).syncMode);
}
diff --git a/src/mongo/db/repl/replication_coordinator_mock.cpp b/src/mongo/db/repl/replication_coordinator_mock.cpp
index 85df34dcb91..43d59838487 100644
--- a/src/mongo/db/repl/replication_coordinator_mock.cpp
+++ b/src/mongo/db/repl/replication_coordinator_mock.cpp
@@ -645,7 +645,7 @@ void ReplicationCoordinatorMock::createWMajorityWriteAvailabilityDateWaiter(OpTi
WriteConcernOptions ReplicationCoordinatorMock::populateUnsetWriteConcernOptionsSyncMode(
WriteConcernOptions wc) {
if (wc.syncMode == WriteConcernOptions::SyncMode::UNSET) {
- if (wc.wMode == WriteConcernOptions::kMajority) {
+ if (wc.isMajority()) {
wc.syncMode = WriteConcernOptions::SyncMode::JOURNAL;
} else {
wc.syncMode = WriteConcernOptions::SyncMode::NONE;
diff --git a/src/mongo/db/s/chunk_move_write_concern_options.cpp b/src/mongo/db/s/chunk_move_write_concern_options.cpp
index c41db7ad8ec..f7edb110c45 100644
--- a/src/mongo/db/s/chunk_move_write_concern_options.cpp
+++ b/src/mongo/db/s/chunk_move_write_concern_options.cpp
@@ -94,7 +94,7 @@ StatusWith<WriteConcernOptions> ChunkMoveWriteConcernOptions::getEffectiveWriteC
if (writeConcern.needToWaitForOtherNodes() &&
writeConcern.wTimeout == WriteConcernOptions::kNoTimeout) {
// Don't allow no timeout
- writeConcern.wTimeout = durationCount<Milliseconds>(kDefaultWriteTimeoutForMigration);
+ writeConcern.wTimeout = duration_cast<Milliseconds>(kDefaultWriteTimeoutForMigration);
}
return writeConcern;
diff --git a/src/mongo/db/s/clone_catalog_data_command.cpp b/src/mongo/db/s/clone_catalog_data_command.cpp
index 1874b6e2376..cdfde40535b 100644
--- a/src/mongo/db/s/clone_catalog_data_command.cpp
+++ b/src/mongo/db/s/clone_catalog_data_command.cpp
@@ -95,11 +95,7 @@ public:
str::stream() << "_shardsvrCloneCatalogData can only be run on shard servers",
serverGlobalParams.clusterRole == ClusterRole::ShardServer);
- uassert(ErrorCodes::InvalidOptions,
- str::stream()
- << "_shardsvrCloneCatalogData must be called with majority writeConcern, got "
- << cmdObj,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(getName(), opCtx->getWriteConcern());
const auto cloneCatalogDataRequest =
CloneCatalogData::parse(IDLParserErrorContext("_shardsvrCloneCatalogData"), cmdObj);
diff --git a/src/mongo/db/s/config/configsvr_abort_reshard_collection_command.cpp b/src/mongo/db/s/config/configsvr_abort_reshard_collection_command.cpp
index 7a5653bb594..9cb503a2979 100644
--- a/src/mongo/db/s/config/configsvr_abort_reshard_collection_command.cpp
+++ b/src/mongo/db/s/config/configsvr_abort_reshard_collection_command.cpp
@@ -107,9 +107,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrAbortReshardCollection can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- "_configsvrAbortReshardCollection must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
const auto reshardingUUID = retrieveReshardingUUID(opCtx, ns());
diff --git a/src/mongo/db/s/config/configsvr_add_shard_command.cpp b/src/mongo/db/s/config/configsvr_add_shard_command.cpp
index 7504b149e50..7e45c082250 100644
--- a/src/mongo/db/s/config/configsvr_add_shard_command.cpp
+++ b/src/mongo/db/s/config/configsvr_add_shard_command.cpp
@@ -98,11 +98,7 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrAddShard can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(
- ErrorCodes::InvalidOptions,
- str::stream() << "_configsvrAddShard must be called with majority writeConcern, got "
- << cmdObj,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(getName(), opCtx->getWriteConcern());
// Set the operation context read concern level to local for reads into the config database.
repl::ReadConcernArgs::get(opCtx) =
diff --git a/src/mongo/db/s/config/configsvr_clear_jumbo_flag_command.cpp b/src/mongo/db/s/config/configsvr_clear_jumbo_flag_command.cpp
index 9f4a3a07cc2..f97d164151b 100644
--- a/src/mongo/db/s/config/configsvr_clear_jumbo_flag_command.cpp
+++ b/src/mongo/db/s/config/configsvr_clear_jumbo_flag_command.cpp
@@ -57,9 +57,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrClearJumboFlag can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- "_configsvrClearJumboFlag must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
// Set the operation context read concern level to local for reads into the config
// database.
diff --git a/src/mongo/db/s/config/configsvr_commit_reshard_collection_command.cpp b/src/mongo/db/s/config/configsvr_commit_reshard_collection_command.cpp
index 6cf6440a36f..fb67df820c4 100644
--- a/src/mongo/db/s/config/configsvr_commit_reshard_collection_command.cpp
+++ b/src/mongo/db/s/config/configsvr_commit_reshard_collection_command.cpp
@@ -79,10 +79,8 @@ public:
ErrorCodes::IllegalOperation,
format(FMT_STRING("{} can only be run on config servers"), definition()->getName()),
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- format(FMT_STRING("{} must be called with majority writeConcern"),
- definition()->getName()),
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
UUID reshardingUUID = retrieveReshardingUUID(opCtx, ns());
diff --git a/src/mongo/db/s/config/configsvr_create_database_command.cpp b/src/mongo/db/s/config/configsvr_create_database_command.cpp
index 86d2c81607d..83e9271954f 100644
--- a/src/mongo/db/s/config/configsvr_create_database_command.cpp
+++ b/src/mongo/db/s/config/configsvr_create_database_command.cpp
@@ -71,10 +71,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrCreateDatabase can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- str::stream()
- << "_configsvrCreateDatabase must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
// Set the operation context read concern level to local for reads into the config
// database.
diff --git a/src/mongo/db/s/config/configsvr_ensure_chunk_version_is_greater_than_command.cpp b/src/mongo/db/s/config/configsvr_ensure_chunk_version_is_greater_than_command.cpp
index 1b39374f9da..9acbfb2f107 100644
--- a/src/mongo/db/s/config/configsvr_ensure_chunk_version_is_greater_than_command.cpp
+++ b/src/mongo/db/s/config/configsvr_ensure_chunk_version_is_greater_than_command.cpp
@@ -52,10 +52,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrEnsureChunkVersionIsGreaterThan can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- "_configsvrEnsureChunkVersionIsGreaterThan must be called with majority "
- "writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
ShardingCatalogManager::get(opCtx)->ensureChunkVersionIsGreaterThan(
opCtx,
request().getCollectionUUID(),
diff --git a/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp b/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp
index ef766dd1d68..a58168f06be 100644
--- a/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp
+++ b/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp
@@ -56,9 +56,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrRefineCollectionShardKey can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- "_configsvrRefineCollectionShardKey must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
_internalRun(opCtx);
}
diff --git a/src/mongo/db/s/config/configsvr_remove_chunks_command.cpp b/src/mongo/db/s/config/configsvr_remove_chunks_command.cpp
index 77289aa3100..c08c93b9d8e 100644
--- a/src/mongo/db/s/config/configsvr_remove_chunks_command.cpp
+++ b/src/mongo/db/s/config/configsvr_remove_chunks_command.cpp
@@ -62,9 +62,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrRemoveChunks can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- "_configsvrRemoveChunks must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
// Set the operation context read concern level to local for reads into the config
// database.
diff --git a/src/mongo/db/s/config/configsvr_remove_shard_command.cpp b/src/mongo/db/s/config/configsvr_remove_shard_command.cpp
index 16e74bb3dbf..73ad8dcbb21 100644
--- a/src/mongo/db/s/config/configsvr_remove_shard_command.cpp
+++ b/src/mongo/db/s/config/configsvr_remove_shard_command.cpp
@@ -99,11 +99,7 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrRemoveShard can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(
- ErrorCodes::InvalidOptions,
- str::stream() << "_configsvrRemoveShard must be called with majority writeConcern, got "
- << cmdObj,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(getName(), opCtx->getWriteConcern());
ON_BLOCK_EXIT([&opCtx] {
repl::ReplClientInfo::forClient(opCtx->getClient()).setLastOpToSystemLastOpTime(opCtx);
diff --git a/src/mongo/db/s/config/configsvr_remove_tags_command.cpp b/src/mongo/db/s/config/configsvr_remove_tags_command.cpp
index 9bf9dbed174..ce1afe24e15 100644
--- a/src/mongo/db/s/config/configsvr_remove_tags_command.cpp
+++ b/src/mongo/db/s/config/configsvr_remove_tags_command.cpp
@@ -62,9 +62,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrRemoveTags can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- "_configsvrRemoveTags must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
// Set the operation context read concern level to local for reads into the config
// database.
diff --git a/src/mongo/db/s/config/configsvr_rename_collection_metadata_command.cpp b/src/mongo/db/s/config/configsvr_rename_collection_metadata_command.cpp
index 854f6e359e4..87a069ec3f4 100644
--- a/src/mongo/db/s/config/configsvr_rename_collection_metadata_command.cpp
+++ b/src/mongo/db/s/config/configsvr_rename_collection_metadata_command.cpp
@@ -75,9 +75,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrRenameCollectionMetadata can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- "_configsvrRenameCollectionMetadata must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
opCtx->setAlwaysInterruptAtStepDownOrUp();
diff --git a/src/mongo/db/s/config/configsvr_repair_sharded_collection_chunks_history_command.cpp b/src/mongo/db/s/config/configsvr_repair_sharded_collection_chunks_history_command.cpp
index 4586c03cc68..615e1098ccc 100644
--- a/src/mongo/db/s/config/configsvr_repair_sharded_collection_chunks_history_command.cpp
+++ b/src/mongo/db/s/config/configsvr_repair_sharded_collection_chunks_history_command.cpp
@@ -92,11 +92,7 @@ public:
repl::ReadConcernArgs::get(opCtx) =
repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern);
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << "_configsvrRepairShardedCollectionChunksHistory must be called "
- "with majority writeConcern, got "
- << cmdObj,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(getName(), opCtx->getWriteConcern());
const NamespaceString nss{parseNs(unusedDbName, cmdObj)};
diff --git a/src/mongo/db/s/config/configsvr_reshard_collection_cmd.cpp b/src/mongo/db/s/config/configsvr_reshard_collection_cmd.cpp
index c98393c64dd..55bcaa9bbd1 100644
--- a/src/mongo/db/s/config/configsvr_reshard_collection_cmd.cpp
+++ b/src/mongo/db/s/config/configsvr_reshard_collection_cmd.cpp
@@ -91,9 +91,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrReshardCollection can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- "_configsvrReshardCollection must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
repl::ReadConcernArgs::get(opCtx) =
repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern);
diff --git a/src/mongo/db/s/config/configsvr_set_allow_migrations_command.cpp b/src/mongo/db/s/config/configsvr_set_allow_migrations_command.cpp
index f70df3d9d9f..01c3032aa40 100644
--- a/src/mongo/db/s/config/configsvr_set_allow_migrations_command.cpp
+++ b/src/mongo/db/s/config/configsvr_set_allow_migrations_command.cpp
@@ -56,9 +56,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_configsvrSetAllowMigrations can only be run on config servers",
serverGlobalParams.clusterRole == ClusterRole::ConfigServer);
- uassert(ErrorCodes::InvalidOptions,
- "_configsvrSetAllowMigrations must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
// Set the operation context read concern level to local for reads into the config
// database.
diff --git a/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp b/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp
index de70ad64fd7..0a103392946 100644
--- a/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp
+++ b/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp
@@ -495,8 +495,9 @@ void ShardingCatalogManager::refineCollectionShardKey(OperationContext* opCtx,
// documents than a normal operation, so we override the write concern to not use a
// wTimeout, matching the behavior before the API was introduced.
WriteConcernOptions originalWC = opCtx->getWriteConcern();
- opCtx->setWriteConcern(WriteConcernOptions(
- WriteConcernOptions::kMajority, WriteConcernOptions::SyncMode::UNSET, 0));
+ opCtx->setWriteConcern(WriteConcernOptions{WriteConcernOptions::kMajority,
+ WriteConcernOptions::SyncMode::UNSET,
+ WriteConcernOptions::kNoTimeout});
ON_BLOCK_EXIT([opCtx, originalWC] { opCtx->setWriteConcern(originalWC); });
withTransactionAPI(opCtx, nss, std::move(updateCollectionAndChunksWithAPIFn));
diff --git a/src/mongo/db/s/migration_chunk_cloner_source_legacy_commands.cpp b/src/mongo/db/s/migration_chunk_cloner_source_legacy_commands.cpp
index f1bd1269c86..713303693e5 100644
--- a/src/mongo/db/s/migration_chunk_cloner_source_legacy_commands.cpp
+++ b/src/mongo/db/s/migration_chunk_cloner_source_legacy_commands.cpp
@@ -316,8 +316,9 @@ public:
// in this batch may have been rolled back. In this case, we abort the migration.
if (opTime) {
WriteConcernResult wcResult;
- WriteConcernOptions majorityWC(
- WriteConcernOptions::kMajority, WriteConcernOptions::SyncMode::UNSET, 0);
+ WriteConcernOptions majorityWC{WriteConcernOptions::kMajority,
+ WriteConcernOptions::SyncMode::UNSET,
+ WriteConcernOptions::kNoTimeout};
uassertStatusOK(waitForWriteConcern(opCtx, opTime.get(), majorityWC, &wcResult));
auto rollbackIdAtMigrationInit = [&]() {
diff --git a/src/mongo/db/s/migration_destination_manager.cpp b/src/mongo/db/s/migration_destination_manager.cpp
index 562b689c2f7..364195ee50b 100644
--- a/src/mongo/db/s/migration_destination_manager.cpp
+++ b/src/mongo/db/s/migration_destination_manager.cpp
@@ -98,7 +98,7 @@ const WriteConcernOptions kMajorityWriteConcern(WriteConcernOptions::kMajority,
// writeConcernMajorityJournalDefault is set to true
// in the ReplSetConfig.
WriteConcernOptions::SyncMode::UNSET,
- -1);
+ WriteConcernOptions::kNoWaiting);
BSONObj makeLocalReadConcernWithAfterClusterTime(Timestamp afterClusterTime) {
return BSON(repl::ReadConcernArgs::kReadConcernFieldName
@@ -230,7 +230,7 @@ bool opReplicatedEnough(OperationContext* opCtx,
// Enforce the user specified write concern after "majority" so it covers the union of the 2
// write concerns in case the user's write concern is stronger than majority
WriteConcernOptions userWriteConcern(writeConcern);
- userWriteConcern.wTimeout = -1;
+ userWriteConcern.wTimeout = WriteConcernOptions::kNoWaiting;
writeConcernResult.wTimedOut = false;
Status userStatus =
diff --git a/src/mongo/db/s/migration_destination_manager_legacy_commands.cpp b/src/mongo/db/s/migration_destination_manager_legacy_commands.cpp
index 419f2144c8e..7f90fe3a6d6 100644
--- a/src/mongo/db/s/migration_destination_manager_legacy_commands.cpp
+++ b/src/mongo/db/s/migration_destination_manager_legacy_commands.cpp
@@ -341,11 +341,7 @@ public:
BSONObjBuilder& result) override {
opCtx->setAlwaysInterruptAtStepDownOrUp();
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << getName() << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
-
+ CommandHelpers::uassertCommandRunWithMajority(getName(), opCtx->getWriteConcern());
const auto sessionId = uassertStatusOK(MigrationSessionId::extractFromBSON(cmdObj));
LOGV2_DEBUG(5899101, 2, "Received _recvChunkReleaseCritSec", "sessionId"_attr = sessionId);
diff --git a/src/mongo/db/s/migration_util.cpp b/src/mongo/db/s/migration_util.cpp
index dbbcafd6aac..aeab3994ee9 100644
--- a/src/mongo/db/s/migration_util.cpp
+++ b/src/mongo/db/s/migration_util.cpp
@@ -840,7 +840,7 @@ void deleteMigrationCoordinatorDocumentLocally(OperationContext* opCtx, const UU
NamespaceString::kMigrationCoordinatorsNamespace);
store.remove(opCtx,
BSON(MigrationCoordinatorDocument::kIdFieldName << migrationId),
- {1, WriteConcernOptions::SyncMode::UNSET, Seconds(0)});
+ WriteConcernOptions{1, WriteConcernOptions::SyncMode::UNSET, Seconds(0)});
}
void ensureChunkVersionIsGreaterThan(OperationContext* opCtx,
diff --git a/src/mongo/db/s/resharding/resharding_txn_cloner.cpp b/src/mongo/db/s/resharding/resharding_txn_cloner.cpp
index d4b2cc88bee..cfb088a7655 100644
--- a/src/mongo/db/s/resharding/resharding_txn_cloner.cpp
+++ b/src/mongo/db/s/resharding/resharding_txn_cloner.cpp
@@ -186,7 +186,7 @@ void ReshardingTxnCloner::_updateProgressDocument(OperationContext* opCtx,
opCtx,
BSON(ReshardingTxnClonerProgress::kSourceIdFieldName << _sourceId.toBSON()),
BSON("$set" << BSON(ReshardingTxnClonerProgress::kProgressFieldName << progress.toBSON())),
- {1, WriteConcernOptions::SyncMode::UNSET, Seconds(0)});
+ WriteConcernOptions{1, WriteConcernOptions::SyncMode::UNSET, Seconds(0)});
}
SemiFuture<void> ReshardingTxnCloner::run(
diff --git a/src/mongo/db/s/session_catalog_migration_source.cpp b/src/mongo/db/s/session_catalog_migration_source.cpp
index ce330604c81..3d378f3a8ed 100644
--- a/src/mongo/db/s/session_catalog_migration_source.cpp
+++ b/src/mongo/db/s/session_catalog_migration_source.cpp
@@ -239,8 +239,9 @@ SessionCatalogMigrationSource::SessionCatalogMigrationSource(OperationContext* o
auto opTimeToWait = repl::ReplClientInfo::forClient(opCtx->getClient()).getLastOp();
WriteConcernResult result;
- WriteConcernOptions majority(
- WriteConcernOptions::kMajority, WriteConcernOptions::SyncMode::UNSET, 0);
+ WriteConcernOptions majority{WriteConcernOptions::kMajority,
+ WriteConcernOptions::SyncMode::UNSET,
+ WriteConcernOptions::kNoTimeout};
uassertStatusOK(waitForWriteConcern(opCtx, opTimeToWait, majority, &result));
AutoGetCollection collection(
diff --git a/src/mongo/db/s/sharding_logging.cpp b/src/mongo/db/s/sharding_logging.cpp
index e6c56ad0538..c5c8925026c 100644
--- a/src/mongo/db/s/sharding_logging.cpp
+++ b/src/mongo/db/s/sharding_logging.cpp
@@ -102,7 +102,7 @@ Status ShardingLogging::logChangeChecked(OperationContext* opCtx,
const BSONObj& detail,
const WriteConcernOptions& writeConcern) {
invariant(serverGlobalParams.clusterRole == ClusterRole::ConfigServer ||
- writeConcern.wMode == WriteConcernOptions::kMajority);
+ writeConcern.isMajority());
if (_changeLogCollectionCreated.load() == 0) {
Status result = _createCappedConfigCollection(
opCtx, kChangeLogCollectionName, kChangeLogCollectionSizeMB, writeConcern);
diff --git a/src/mongo/db/s/shardsvr_abort_reshard_collection_command.cpp b/src/mongo/db/s/shardsvr_abort_reshard_collection_command.cpp
index 1b43a1f7e76..aa319814395 100644
--- a/src/mongo/db/s/shardsvr_abort_reshard_collection_command.cpp
+++ b/src/mongo/db/s/shardsvr_abort_reshard_collection_command.cpp
@@ -61,9 +61,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_shardsvrAbortReshardCollection can only be run on shard servers",
serverGlobalParams.clusterRole == ClusterRole::ShardServer);
- uassert(ErrorCodes::InvalidOptions,
- "_shardsvrAbortReshardCollection must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
std::vector<SharedSemiFuture<void>> futuresToWait;
diff --git a/src/mongo/db/s/shardsvr_collmod_command.cpp b/src/mongo/db/s/shardsvr_collmod_command.cpp
index 5591b5c841b..ab5516c9f63 100644
--- a/src/mongo/db/s/shardsvr_collmod_command.cpp
+++ b/src/mongo/db/s/shardsvr_collmod_command.cpp
@@ -96,11 +96,8 @@ public:
auto const shardingState = ShardingState::get(opCtx);
uassertStatusOK(shardingState->canAcceptShardedCommands());
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
opCtx->setAlwaysInterruptAtStepDownOrUp();
diff --git a/src/mongo/db/s/shardsvr_collmod_participant_command.cpp b/src/mongo/db/s/shardsvr_collmod_participant_command.cpp
index 155d298f751..5b8a791ec54 100644
--- a/src/mongo/db/s/shardsvr_collmod_participant_command.cpp
+++ b/src/mongo/db/s/shardsvr_collmod_participant_command.cpp
@@ -70,11 +70,8 @@ public:
Response typedRun(OperationContext* opCtx) {
uassertStatusOK(ShardingState::get(opCtx)->canAcceptShardedCommands());
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
opCtx->setAlwaysInterruptAtStepDownOrUp();
diff --git a/src/mongo/db/s/shardsvr_commit_reshard_collection_command.cpp b/src/mongo/db/s/shardsvr_commit_reshard_collection_command.cpp
index 5cf16bb5a7d..5cf90ea6441 100644
--- a/src/mongo/db/s/shardsvr_commit_reshard_collection_command.cpp
+++ b/src/mongo/db/s/shardsvr_commit_reshard_collection_command.cpp
@@ -61,9 +61,8 @@ public:
uassert(ErrorCodes::IllegalOperation,
"_shardsvrCommitReshardCollection can only be run on shard servers",
serverGlobalParams.clusterRole == ClusterRole::ShardServer);
- uassert(ErrorCodes::InvalidOptions,
- "_shardsvrCommitReshardCollection must be called with majority writeConcern",
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
std::vector<SharedSemiFuture<void>> futuresToWait;
diff --git a/src/mongo/db/s/shardsvr_create_collection_command.cpp b/src/mongo/db/s/shardsvr_create_collection_command.cpp
index 2cae74399f1..d1312c7b3db 100644
--- a/src/mongo/db/s/shardsvr_create_collection_command.cpp
+++ b/src/mongo/db/s/shardsvr_create_collection_command.cpp
@@ -73,12 +73,8 @@ public:
opCtx->setAlwaysInterruptAtStepDownOrUp();
- uassert(
- ErrorCodes::InvalidOptions,
- str::stream()
- << "_shardsvrCreateCollection must be called with majority writeConcern, got "
- << request().toBSON(BSONObj()),
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
uassert(ErrorCodes::NotImplemented,
"Create Collection path has not been implemented",
diff --git a/src/mongo/db/s/shardsvr_create_collection_participant_command.cpp b/src/mongo/db/s/shardsvr_create_collection_participant_command.cpp
index 77f4d8b4b69..4ef72fd2f72 100644
--- a/src/mongo/db/s/shardsvr_create_collection_participant_command.cpp
+++ b/src/mongo/db/s/shardsvr_create_collection_participant_command.cpp
@@ -71,11 +71,8 @@ public:
auto const shardingState = ShardingState::get(opCtx);
uassertStatusOK(shardingState->canAcceptShardedCommands());
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << "_shardsvrCreateCollectionParticipant must be called with "
- "majority writeConcern, got "
- << request().toBSON(BSONObj()),
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
opCtx->setAlwaysInterruptAtStepDownOrUp();
diff --git a/src/mongo/db/s/shardsvr_drop_collection_command.cpp b/src/mongo/db/s/shardsvr_drop_collection_command.cpp
index a2ca5259363..18f2a06d024 100644
--- a/src/mongo/db/s/shardsvr_drop_collection_command.cpp
+++ b/src/mongo/db/s/shardsvr_drop_collection_command.cpp
@@ -68,11 +68,8 @@ public:
void typedRun(OperationContext* opCtx) {
uassertStatusOK(ShardingState::get(opCtx)->canAcceptShardedCommands());
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
opCtx->setAlwaysInterruptAtStepDownOrUp();
diff --git a/src/mongo/db/s/shardsvr_drop_collection_participant_command.cpp b/src/mongo/db/s/shardsvr_drop_collection_participant_command.cpp
index 2ee8de9ee70..a9b18cf3f61 100644
--- a/src/mongo/db/s/shardsvr_drop_collection_participant_command.cpp
+++ b/src/mongo/db/s/shardsvr_drop_collection_participant_command.cpp
@@ -70,11 +70,8 @@ public:
void typedRun(OperationContext* opCtx) {
uassertStatusOK(ShardingState::get(opCtx)->canAcceptShardedCommands());
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
opCtx->setAlwaysInterruptAtStepDownOrUp();
diff --git a/src/mongo/db/s/shardsvr_drop_database_command.cpp b/src/mongo/db/s/shardsvr_drop_database_command.cpp
index a8aaef5fbcf..2ae8fbb35ec 100644
--- a/src/mongo/db/s/shardsvr_drop_database_command.cpp
+++ b/src/mongo/db/s/shardsvr_drop_database_command.cpp
@@ -69,11 +69,8 @@ public:
void typedRun(OperationContext* opCtx) {
uassertStatusOK(ShardingState::get(opCtx)->canAcceptShardedCommands());
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
opCtx->setAlwaysInterruptAtStepDownOrUp();
diff --git a/src/mongo/db/s/shardsvr_drop_database_participant_command.cpp b/src/mongo/db/s/shardsvr_drop_database_participant_command.cpp
index 04fbdb2a779..a10c5114cdb 100644
--- a/src/mongo/db/s/shardsvr_drop_database_participant_command.cpp
+++ b/src/mongo/db/s/shardsvr_drop_database_participant_command.cpp
@@ -68,11 +68,8 @@ public:
void typedRun(OperationContext* opCtx) {
uassertStatusOK(ShardingState::get(opCtx)->canAcceptShardedCommands());
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
const auto& dbName = request().getDbName();
diff --git a/src/mongo/db/s/shardsvr_move_primary_command.cpp b/src/mongo/db/s/shardsvr_move_primary_command.cpp
index de96165a672..dbf579eabf6 100644
--- a/src/mongo/db/s/shardsvr_move_primary_command.cpp
+++ b/src/mongo/db/s/shardsvr_move_primary_command.cpp
@@ -110,11 +110,7 @@ public:
str::stream() << "you have to specify where you want to move it",
!toShard.empty());
- uassert(
- ErrorCodes::InvalidOptions,
- str::stream() << "_shardsvrMovePrimary must be called with majority writeConcern, got "
- << cmdObj,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(getName(), opCtx->getWriteConcern());
ON_BLOCK_EXIT(
[opCtx, dbNss] { Grid::get(opCtx)->catalogCache()->purgeDatabase(dbNss.db()); });
diff --git a/src/mongo/db/s/shardsvr_rename_collection_command.cpp b/src/mongo/db/s/shardsvr_rename_collection_command.cpp
index 3cceae99c84..5a1918046f4 100644
--- a/src/mongo/db/s/shardsvr_rename_collection_command.cpp
+++ b/src/mongo/db/s/shardsvr_rename_collection_command.cpp
@@ -83,11 +83,8 @@ public:
opCtx->setAlwaysInterruptAtStepDownOrUp();
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
if (fromNss.db() != toNss.db()) {
sharding_ddl_util::checkDbPrimariesOnTheSameShard(opCtx, fromNss, toNss);
diff --git a/src/mongo/db/s/shardsvr_rename_collection_participant_command.cpp b/src/mongo/db/s/shardsvr_rename_collection_participant_command.cpp
index 61c9718b4e1..aa2b2bf013c 100644
--- a/src/mongo/db/s/shardsvr_rename_collection_participant_command.cpp
+++ b/src/mongo/db/s/shardsvr_rename_collection_participant_command.cpp
@@ -71,11 +71,8 @@ public:
using InvocationBase::InvocationBase;
void typedRun(OperationContext* opCtx) {
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
auto const shardingState = ShardingState::get(opCtx);
uassertStatusOK(shardingState->canAcceptShardedCommands());
@@ -167,11 +164,8 @@ public:
using InvocationBase::InvocationBase;
void typedRun(OperationContext* opCtx) {
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
auto const shardingState = ShardingState::get(opCtx);
uassertStatusOK(shardingState->canAcceptShardedCommands());
diff --git a/src/mongo/db/s/shardsvr_reshard_collection_command.cpp b/src/mongo/db/s/shardsvr_reshard_collection_command.cpp
index 46d068c12af..5a10de6a559 100644
--- a/src/mongo/db/s/shardsvr_reshard_collection_command.cpp
+++ b/src/mongo/db/s/shardsvr_reshard_collection_command.cpp
@@ -71,11 +71,8 @@ public:
void typedRun(OperationContext* opCtx) {
uassertStatusOK(ShardingState::get(opCtx)->canAcceptShardedCommands());
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << opCtx->getWriteConcern().wMode,
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
// (Generic FCV reference): To run this command and ensure the consistency of the
// metadata we need to make sure we are on a stable state.
uassert(
diff --git a/src/mongo/db/s/shardsvr_set_allow_migrations_command.cpp b/src/mongo/db/s/shardsvr_set_allow_migrations_command.cpp
index 1703dd86829..401356eb0f9 100644
--- a/src/mongo/db/s/shardsvr_set_allow_migrations_command.cpp
+++ b/src/mongo/db/s/shardsvr_set_allow_migrations_command.cpp
@@ -72,11 +72,8 @@ public:
opCtx->setAlwaysInterruptAtStepDownOrUp();
- uassert(ErrorCodes::InvalidOptions,
- str::stream() << Request::kCommandName
- << " must be called with majority writeConcern, got "
- << request().toBSON(BSONObj()),
- opCtx->getWriteConcern().wMode == WriteConcernOptions::kMajority);
+ CommandHelpers::uassertCommandRunWithMajority(Request::kCommandName,
+ opCtx->getWriteConcern());
SetAllowMigrationsRequest setAllowMigationsCmdRequest =
request().getSetAllowMigrationsRequest();
diff --git a/src/mongo/db/service_entry_point_mongod.cpp b/src/mongo/db/service_entry_point_mongod.cpp
index 771f3b9c564..7d96332a67e 100644
--- a/src/mongo/db/service_entry_point_mongod.cpp
+++ b/src/mongo/db/service_entry_point_mongod.cpp
@@ -174,7 +174,7 @@ public:
// from the primary.
if (repl::ReadConcernArgs::get(opCtx).getLevel() ==
repl::ReadConcernLevel::kLinearizableReadConcern) {
- uassertStatusOK(mongo::waitForLinearizableReadConcern(opCtx, 0));
+ uassertStatusOK(mongo::waitForLinearizableReadConcern(opCtx, Milliseconds::zero()));
}
}
diff --git a/src/mongo/db/stats/server_write_concern_metrics.cpp b/src/mongo/db/stats/server_write_concern_metrics.cpp
index 1229541db85..7dcedc40ef6 100644
--- a/src/mongo/db/stats/server_write_concern_metrics.cpp
+++ b/src/mongo/db/stats/server_write_concern_metrics.cpp
@@ -108,17 +108,22 @@ BSONObj ServerWriteConcernMetrics::toBSON() const {
void ServerWriteConcernMetrics::WriteConcernCounters::recordWriteConcern(
const WriteConcernOptions& writeConcernOptions, size_t numOps) {
- if (!writeConcernOptions.wMode.empty()) {
- if (writeConcernOptions.wMode == WriteConcernOptions::kMajority) {
+ if (auto wMode = stdx::get_if<std::string>(&writeConcernOptions.w)) {
+ if (writeConcernOptions.isMajority()) {
wMajorityCount += numOps;
return;
}
- wTagCounts[writeConcernOptions.wMode] += numOps;
+ wTagCounts[*wMode] += numOps;
return;
}
- wNumCounts[writeConcernOptions.wNumNodes] += numOps;
+ if (stdx::holds_alternative<WTags>(writeConcernOptions.w)) {
+ // wTags is an internal feature that we don't track metrics for
+ return;
+ }
+
+ wNumCounts[stdx::get<int64_t>(writeConcernOptions.w)] += numOps;
}
void ServerWriteConcernMetrics::WriteConcernMetricsForOperationType::recordWriteConcern(
diff --git a/src/mongo/db/transaction_api_test.cpp b/src/mongo/db/transaction_api_test.cpp
index 266d0c61847..9a6d2f8d25f 100644
--- a/src/mongo/db/transaction_api_test.cpp
+++ b/src/mongo/db/transaction_api_test.cpp
@@ -257,9 +257,11 @@ TEST_F(TxnAPITest, OwnSession_AttachesTxnMetadata) {
TEST_F(TxnAPITest, OwnSession_AttachesWriteConcernOnCommit) {
const std::vector<WriteConcernOptions> writeConcernOptions = {
- WriteConcernOptions(1, WriteConcernOptions::SyncMode::JOURNAL, 100),
- WriteConcernOptions("majority", WriteConcernOptions::SyncMode::FSYNC, 0),
- WriteConcernOptions(2, WriteConcernOptions::SyncMode::NONE, -1)};
+ WriteConcernOptions{1, WriteConcernOptions::SyncMode::JOURNAL, Milliseconds{100}},
+ WriteConcernOptions{
+ "majority", WriteConcernOptions::SyncMode::FSYNC, WriteConcernOptions::kNoTimeout},
+ WriteConcernOptions{
+ 2, WriteConcernOptions::SyncMode::NONE, WriteConcernOptions::kNoWaiting}};
for (const auto& writeConcern : writeConcernOptions) {
opCtx()->setWriteConcern(writeConcern);
@@ -321,9 +323,11 @@ TEST_F(TxnAPITest, OwnSession_AttachesWriteConcernOnCommit) {
TEST_F(TxnAPITest, OwnSession_AttachesWriteConcernOnAbort) {
const std::vector<WriteConcernOptions> writeConcernOptions = {
- WriteConcernOptions(1, WriteConcernOptions::SyncMode::JOURNAL, 100),
- WriteConcernOptions("majority", WriteConcernOptions::SyncMode::FSYNC, 0),
- WriteConcernOptions(2, WriteConcernOptions::SyncMode::NONE, -1)};
+ WriteConcernOptions{1, WriteConcernOptions::SyncMode::JOURNAL, Milliseconds{100}},
+ WriteConcernOptions{
+ "majority", WriteConcernOptions::SyncMode::FSYNC, WriteConcernOptions::kNoTimeout},
+ WriteConcernOptions{
+ 2, WriteConcernOptions::SyncMode::NONE, WriteConcernOptions::kNoWaiting}};
for (const auto& writeConcern : writeConcernOptions) {
opCtx()->setWriteConcern(writeConcern);
diff --git a/src/mongo/db/write_concern.cpp b/src/mongo/db/write_concern.cpp
index 906984b38a5..91a8cddac86 100644
--- a/src/mongo/db/write_concern.cpp
+++ b/src/mongo/db/write_concern.cpp
@@ -56,7 +56,6 @@
namespace mongo {
using repl::OpTime;
-using repl::OpTimeAndWallTime;
using std::string;
static TimerStats gleWtimeStats;
@@ -132,8 +131,9 @@ StatusWith<WriteConcernOptions> extractWriteConcern(OperationContext* opCtx,
}
return writeConcern;
})();
- if (writeConcern.wNumNodes == 0 && writeConcern.wMode.empty()) {
- writeConcern.wNumNodes = 1;
+
+ if (writeConcern.isUnacknowledged()) {
+ writeConcern.w = 1;
}
writeConcern.notExplicitWValue = true;
@@ -162,7 +162,7 @@ StatusWith<WriteConcernOptions> extractWriteConcern(OperationContext* opCtx,
// Upconvert the writeConcern of any incoming requests from internal connections (i.e.,
// from other nodes in the cluster) to "majority." This protects against internal code that
// does not specify writeConcern when writing to the config server.
- writeConcern = {
+ writeConcern = WriteConcernOptions{
WriteConcernOptions::kMajority, WriteConcernOptions::SyncMode::UNSET, Seconds(30)};
writeConcern.getProvenance().setSource(
ReadWriteConcernProvenance::Source::internalWriteDefault);
@@ -185,15 +185,18 @@ Status validateWriteConcern(OperationContext* opCtx, const WriteConcernOptions&
const auto replMode = repl::ReplicationCoordinator::get(opCtx)->getReplicationMode();
- if (replMode == repl::ReplicationCoordinator::modeNone && writeConcern.wNumNodes > 1) {
+ if (replMode == repl::ReplicationCoordinator::modeNone &&
+ (stdx::holds_alternative<int64_t>(writeConcern.w) &&
+ stdx::get<int64_t>(writeConcern.w) > 1)) {
return Status(ErrorCodes::BadValue, "cannot use 'w' > 1 when a host is not replicated");
}
if (replMode != repl::ReplicationCoordinator::modeReplSet &&
writeConcern.hasCustomWriteMode()) {
return Status(ErrorCodes::BadValue,
- string("cannot use custom 'w' mode ") + writeConcern.wMode +
- " when a host is not a member of a replica set");
+ fmt::format("cannot use non-majority 'w' mode \"{}\" when a host is not a "
+ "member of a replica set",
+ stdx::get<std::string>(writeConcern.w)));
}
return Status::OK();
diff --git a/src/mongo/db/write_concern_options.cpp b/src/mongo/db/write_concern_options.cpp
index 5557cee8298..4f1822884fa 100644
--- a/src/mongo/db/write_concern_options.cpp
+++ b/src/mongo/db/write_concern_options.cpp
@@ -65,8 +65,8 @@ constexpr StringData kWElectionIdFieldName = "wElectionId"_sd;
} // namespace
-constexpr int WriteConcernOptions::kNoTimeout;
-constexpr int WriteConcernOptions::kNoWaiting;
+constexpr Milliseconds WriteConcernOptions::kNoTimeout;
+constexpr Milliseconds WriteConcernOptions::kNoWaiting;
constexpr StringData WriteConcernOptions::kWriteConcernField;
const char WriteConcernOptions::kMajority[] = "majority";
@@ -86,55 +86,37 @@ constexpr Seconds WriteConcernOptions::kWriteConcernTimeoutMigration;
constexpr Seconds WriteConcernOptions::kWriteConcernTimeoutSharding;
constexpr Seconds WriteConcernOptions::kWriteConcernTimeoutUserCommand;
-
-WriteConcernOptions::WriteConcernOptions(int numNodes, SyncMode sync, int timeout)
- : WriteConcernOptions(numNodes, sync, Milliseconds(timeout)) {}
-
-WriteConcernOptions::WriteConcernOptions(const std::string& mode, SyncMode sync, int timeout)
- : WriteConcernOptions(mode, sync, Milliseconds(timeout)) {}
-
WriteConcernOptions::WriteConcernOptions(int numNodes, SyncMode sync, Milliseconds timeout)
- : syncMode(sync), wNumNodes(numNodes), wTimeout(durationCount<Milliseconds>(timeout)) {}
+ : w{numNodes},
+ syncMode{sync},
+ wTimeout(durationCount<Milliseconds>(timeout)),
+ usedDefaultConstructedWC{false},
+ notExplicitWValue{false} {}
WriteConcernOptions::WriteConcernOptions(const std::string& mode,
SyncMode sync,
Milliseconds timeout)
- : syncMode(sync), wNumNodes(0), wMode(mode), wTimeout(durationCount<Milliseconds>(timeout)) {}
+ : w{mode},
+ syncMode{sync},
+ wTimeout(durationCount<Milliseconds>(timeout)),
+ usedDefaultConstructedWC{false},
+ notExplicitWValue{false} {}
StatusWith<WriteConcernOptions> WriteConcernOptions::parse(const BSONObj& obj) try {
if (obj.isEmpty()) {
return Status(ErrorCodes::FailedToParse, "write concern object cannot be empty");
}
- auto writeConcernIdl = WriteConcernIdl::parse(IDLParserErrorContext("writeConcern"), obj);
+ auto writeConcernIdl = WriteConcernIdl::parse({"WriteConcernOptions"}, obj);
auto parsedW = writeConcernIdl.getWriteConcernW();
WriteConcernOptions writeConcern;
- writeConcern.usedDefaultConstructedWC = parsedW.usedDefaultConstructedW1() &&
- !writeConcernIdl.getJ() && !writeConcernIdl.getFsync() &&
- writeConcernIdl.getWtimeout() == 0;
+ writeConcern.usedDefaultConstructedWC = !parsedW && !writeConcernIdl.getJ() &&
+ !writeConcernIdl.getFsync() && writeConcernIdl.getWtimeout() == 0;
- if (!parsedW.usedDefaultConstructedW1()) {
+ if (parsedW) {
writeConcern.notExplicitWValue = false;
- auto wVal = parsedW.getValue();
- if (auto wNum = stdx::get_if<std::int64_t>(&wVal)) {
- if (*wNum < 0 ||
- *wNum >
- static_cast<std::decay_t<decltype(*wNum)>>(repl::ReplSetConfig::kMaxMembers)) {
- uasserted(ErrorCodes::FailedToParse,
- str::stream() << "w has to be a non-negative number and not greater than "
- << repl::ReplSetConfig::kMaxMembers << ", found: " << wNum);
- }
- writeConcern.wNumNodes = static_cast<decltype(writeConcern.wNumNodes)>(*wNum);
- } else if (auto tags = stdx::get_if<BSONObj>(&wVal)) {
- writeConcern.wNumNodes = 0;
- writeConcern._tags = *tags;
- } else {
- auto wMode = stdx::get_if<std::string>(&wVal);
- invariant(wMode);
- writeConcern.wNumNodes = 0; // Have to reset from default 1.
- writeConcern.wMode = std::move(*wMode);
- }
+ writeConcern.w = *parsedW;
}
auto j = writeConcernIdl.getJ();
@@ -153,7 +135,7 @@ StatusWith<WriteConcernOptions> WriteConcernOptions::parse(const BSONObj& obj) t
writeConcern.syncMode = SyncMode::NONE;
}
- writeConcern.wTimeout = writeConcernIdl.getWtimeout();
+ writeConcern.wTimeout = Milliseconds{writeConcernIdl.getWtimeout()};
if (auto source = writeConcernIdl.getSource()) {
writeConcern._provenance = ReadWriteConcernProvenance(*source);
}
@@ -196,14 +178,7 @@ StatusWith<WriteConcernOptions> WriteConcernOptions::extractWCFromCommand(const
BSONObj WriteConcernOptions::toBSON() const {
BSONObjBuilder builder;
-
- if (_tags) {
- builder.append("w", *_tags);
- } else if (wMode.empty()) {
- builder.append("w", wNumNodes);
- } else {
- builder.append("w", wMode);
- }
+ serializeWriteConcernW(w, "w", &builder);
if (syncMode == SyncMode::FSYNC) {
builder.append("fsync", true);
@@ -213,7 +188,9 @@ BSONObj WriteConcernOptions::toBSON() const {
builder.append("j", false);
}
- builder.append("wtimeout", wTimeout);
+ // Historically we have serialized this as a int32_t, even though it is defined as an
+ // int64_t in our IDL format.
+ builder.append("wtimeout", static_cast<int32_t>(durationCount<Milliseconds>(wTimeout)));
_provenance.serialize(&builder);
@@ -221,14 +198,13 @@ BSONObj WriteConcernOptions::toBSON() const {
}
bool WriteConcernOptions::needToWaitForOtherNodes() const {
- return !wMode.empty() || wNumNodes > 1 || _tags;
+ return stdx::holds_alternative<std::string>(w) || stdx::holds_alternative<WTags>(w) ||
+ (stdx::holds_alternative<std::int64_t>(w) && stdx::get<std::int64_t>(w) > 1);
}
bool WriteConcernOptions::operator==(const WriteConcernOptions& other) const {
- return (_tags ? other._tags && _tags->woCompare(*other._tags) == 0
- : wMode == other.wMode && wNumNodes == other.wNumNodes) &&
- syncMode == other.syncMode && wDeadline == other.wDeadline && wTimeout == other.wTimeout &&
- _provenance == other._provenance;
+ return w == other.w && syncMode == other.syncMode && wDeadline == other.wDeadline &&
+ wTimeout == other.wTimeout && _provenance == other._provenance;
}
} // namespace mongo
diff --git a/src/mongo/db/write_concern_options.h b/src/mongo/db/write_concern_options.h
index 910b859c857..4478aa173fe 100644
--- a/src/mongo/db/write_concern_options.h
+++ b/src/mongo/db/write_concern_options.h
@@ -47,8 +47,8 @@ public:
// Users can only provide OpTime condition, the others are used internally.
enum class CheckCondition { OpTime, Config };
- static constexpr int kNoTimeout = 0;
- static constexpr int kNoWaiting = -1;
+ static constexpr Milliseconds kNoTimeout{0};
+ static constexpr Milliseconds kNoWaiting{-1};
static const BSONObj Default;
static const BSONObj Acknowledged;
@@ -64,24 +64,9 @@ public:
static constexpr Seconds kWriteConcernTimeoutSharding{60};
static constexpr Seconds kWriteConcernTimeoutUserCommand{60};
- // It is assumed that a default-constructed WriteConcernOptions will be populated with the
- // default options. If it is subsequently populated with non-default options, it is the caller's
- // responsibility to set the usedDefaultConstructedWC and notExplicitWValue flag correctly.
- WriteConcernOptions()
- : syncMode(SyncMode::UNSET),
- wNumNodes(1),
- wMode(""),
- wTimeout(0),
- usedDefaultConstructedWC(true),
- notExplicitWValue(true) {}
-
- WriteConcernOptions(int numNodes, SyncMode sync, int timeout);
-
- WriteConcernOptions(int numNodes, SyncMode sync, Milliseconds timeout);
-
- WriteConcernOptions(const std::string& mode, SyncMode sync, int timeout);
-
- WriteConcernOptions(const std::string& mode, SyncMode sync, Milliseconds timeout);
+ WriteConcernOptions() = default;
+ explicit WriteConcernOptions(int numNodes, SyncMode sync, Milliseconds timeout);
+ explicit WriteConcernOptions(const std::string& mode, SyncMode sync, Milliseconds timeout);
static StatusWith<WriteConcernOptions> parse(const BSONObj& obj);
@@ -131,21 +116,33 @@ public:
}
bool hasCustomWriteMode() const {
- return !wMode.empty() && wMode != WriteConcernOptions::kMajority;
+ return stdx::holds_alternative<std::string>(w) &&
+ stdx::get<std::string>(w) != WriteConcernOptions::kMajority;
}
- SyncMode syncMode;
+ /**
+ * Returns whether this write concern's w parameter is the number 0.
+ */
+ bool isUnacknowledged() const {
+ return stdx::holds_alternative<int64_t>(w) && stdx::get<int64_t>(w) < 1;
+ }
- // The w parameter for this write concern. The wMode represents the string format and
- // takes precedence over the numeric format wNumNodes.
- int wNumNodes;
- std::string wMode;
+ /**
+ * Returns whether this write concern's w parameter is the string "majority".
+ */
+ bool isMajority() const {
+ return stdx::holds_alternative<std::string>(w) && stdx::get<std::string>(w) == kMajority;
+ }
+ // The w parameter for this write concern.
+ WriteConcernW w{1};
+ // Corresponds to the `j` or `fsync` parameters for write concern.
+ SyncMode syncMode{SyncMode::UNSET};
// Timeout in milliseconds.
- int wTimeout;
+ Milliseconds wTimeout{kNoTimeout};
// Deadline. If this is set to something other than Date_t::max(), this takes precedence over
// wTimeout.
- Date_t wDeadline = Date_t::max();
+ Date_t wDeadline{Date_t::max()};
// True if the default constructed WC ({w:1}) was used.
// - Implicit default WC when value of w is {w:1}.
@@ -159,7 +156,7 @@ public:
// - Client-supplied WC.
// - with (w) value set, for example ({writeConcern: {w:1}}).
// - without (w) value set, for example ({writeConcern: {j: true}}).
- bool usedDefaultConstructedWC = false;
+ bool usedDefaultConstructedWC{true};
// Used only for tracking opWriteConcernCounters metric.
// True if the (w) value of the write concern used is not set explicitly by client:
@@ -170,17 +167,12 @@ public:
// - without (w) value set, for example ({writeConcern: {j: true}}).
// - Client-supplied WC without (w) value set, for example ({writeConcern: {j: true}}).
// - Internal commands set empty WC ({writeConcern: {}}).
- bool notExplicitWValue = false;
-
- CheckCondition checkCondition = CheckCondition::OpTime;
+ bool notExplicitWValue{true};
- boost::optional<BSONObj> wTags() const {
- return _tags;
- }
+ CheckCondition checkCondition{CheckCondition::OpTime};
private:
ReadWriteConcernProvenance _provenance;
- boost::optional<BSONObj> _tags;
};
} // namespace mongo
diff --git a/src/mongo/db/write_concern_options_test.cpp b/src/mongo/db/write_concern_options_test.cpp
index 4f2295feb7f..e9a3d111a08 100644
--- a/src/mongo/db/write_concern_options_test.cpp
+++ b/src/mongo/db/write_concern_options_test.cpp
@@ -67,9 +67,8 @@ TEST(WriteConcernOptionsTest, ParseSetsSyncModeToJournelIfJIsTrue) {
ASSERT_OK(sw.getStatus());
WriteConcernOptions options = sw.getValue();
ASSERT_TRUE(WriteConcernOptions::SyncMode::JOURNAL == options.syncMode);
- ASSERT_EQUALS(1, options.wNumNodes);
- ASSERT_EQUALS("", options.wMode);
- ASSERT_EQUALS(0, options.wTimeout);
+ ASSERT_EQUALS(1, stdx::get<int64_t>(options.w));
+ ASSERT_EQUALS(WriteConcernOptions::kNoTimeout, options.wTimeout);
}
TEST(WriteConcernOptionsTest, ParseSetsSyncModeToFSyncIfFSyncIsTrue) {
@@ -77,9 +76,8 @@ TEST(WriteConcernOptionsTest, ParseSetsSyncModeToFSyncIfFSyncIsTrue) {
ASSERT_OK(sw.getStatus());
WriteConcernOptions options = sw.getValue();
ASSERT_TRUE(WriteConcernOptions::SyncMode::FSYNC == options.syncMode);
- ASSERT_EQUALS(1, options.wNumNodes);
- ASSERT_EQUALS("", options.wMode);
- ASSERT_EQUALS(0, options.wTimeout);
+ ASSERT_EQUALS(1, stdx::get<int64_t>(options.w));
+ ASSERT_EQUALS(WriteConcernOptions::kNoTimeout, options.wTimeout);
}
TEST(WriteConcernOptionsTest, ParseSetsSyncModeToNoneIfJIsFalse) {
@@ -87,9 +85,8 @@ TEST(WriteConcernOptionsTest, ParseSetsSyncModeToNoneIfJIsFalse) {
ASSERT_OK(sw.getStatus());
WriteConcernOptions options = sw.getValue();
ASSERT_TRUE(WriteConcernOptions::SyncMode::NONE == options.syncMode);
- ASSERT_EQUALS(1, options.wNumNodes);
- ASSERT_EQUALS("", options.wMode);
- ASSERT_EQUALS(0, options.wTimeout);
+ ASSERT_EQUALS(1, stdx::get<int64_t>(options.w));
+ ASSERT_EQUALS(WriteConcernOptions::kNoTimeout, options.wTimeout);
}
TEST(WriteConcernOptionsTest, ParseLeavesSyncModeAsUnsetIfFSyncIsFalse) {
@@ -97,15 +94,14 @@ TEST(WriteConcernOptionsTest, ParseLeavesSyncModeAsUnsetIfFSyncIsFalse) {
ASSERT_OK(sw.getStatus());
WriteConcernOptions options = sw.getValue();
ASSERT_TRUE(WriteConcernOptions::SyncMode::UNSET == options.syncMode);
- ASSERT_EQUALS(1, options.wNumNodes);
- ASSERT_EQUALS("", options.wMode);
- ASSERT_EQUALS(0, options.wTimeout);
+ ASSERT_EQUALS(1, stdx::get<int64_t>(options.w));
+ ASSERT_EQUALS(WriteConcernOptions::kNoTimeout, options.wTimeout);
}
TEST(WriteConcernOptionsTest, ParseReturnsFailedToParseIfWIsNotNumberOrStringOrObject) {
auto status = WriteConcernOptions::parse(BSON("w" << true)).getStatus();
ASSERT_EQUALS(ErrorCodes::FailedToParse, status);
- ASSERT_EQUALS("w has to be a number, string, or object", status.reason());
+ ASSERT_STRING_CONTAINS(status.reason(), "w has to be a number, string, or object");
}
TEST(WriteConcernOptionsTest, ParseReturnsFailedToParseIfWIsNegativeOrExceedsMaxMembers) {
@@ -114,7 +110,6 @@ TEST(WriteConcernOptionsTest, ParseReturnsFailedToParseIfWIsNegativeOrExceedsMax
auto st2 = WriteConcernOptions::parse(BSON("w" << -1)).getStatus();
ASSERT_EQUALS(ErrorCodes::FailedToParse, st2);
- ASSERT_EQUALS(st1.reason(), st2.reason());
}
TEST(WriteConcernOptionsTest, ParseSetsWNumNodesIfWIsANumber) {
@@ -122,9 +117,8 @@ TEST(WriteConcernOptionsTest, ParseSetsWNumNodesIfWIsANumber) {
ASSERT_OK(sw.getStatus());
WriteConcernOptions options = sw.getValue();
ASSERT_TRUE(WriteConcernOptions::SyncMode::UNSET == options.syncMode);
- ASSERT_EQUALS(3, options.wNumNodes);
- ASSERT_EQUALS("", options.wMode);
- ASSERT_EQUALS(0, options.wTimeout);
+ ASSERT_EQUALS(3, stdx::get<int64_t>(options.w));
+ ASSERT_EQUALS(WriteConcernOptions::kNoTimeout, options.wTimeout);
}
TEST(WriteConcernOptionsTest, ParseSetsWTimeoutToZeroIfWTimeoutIsNotANumber) {
@@ -133,9 +127,8 @@ TEST(WriteConcernOptionsTest, ParseSetsWTimeoutToZeroIfWTimeoutIsNotANumber) {
ASSERT_OK(sw.getStatus());
WriteConcernOptions options = sw.getValue();
ASSERT_TRUE(WriteConcernOptions::SyncMode::UNSET == options.syncMode);
- ASSERT_EQUALS("", options.wMode);
- ASSERT_EQUALS(1, options.wNumNodes);
- ASSERT_EQUALS(0, options.wTimeout);
+ ASSERT_EQUALS(1, stdx::get<int64_t>(options.w));
+ ASSERT_EQUALS(WriteConcernOptions::kNoTimeout, options.wTimeout);
}
TEST(WriteConcernOptionsTest, ParseWTimeoutAsNumber) {
@@ -143,9 +136,8 @@ TEST(WriteConcernOptionsTest, ParseWTimeoutAsNumber) {
ASSERT_OK(sw.getStatus());
WriteConcernOptions options = sw.getValue();
ASSERT_TRUE(WriteConcernOptions::SyncMode::UNSET == options.syncMode);
- ASSERT_EQUALS("", options.wMode);
- ASSERT_EQUALS(1, options.wNumNodes);
- ASSERT_EQUALS(123, options.wTimeout);
+ ASSERT_EQUALS(1, stdx::get<int64_t>(options.w));
+ ASSERT_EQUALS(Milliseconds{123}, options.wTimeout);
}
TEST(WriteConcernOptionsTest, ParseWTimeoutAsNaNDouble) {
@@ -154,9 +146,8 @@ TEST(WriteConcernOptionsTest, ParseWTimeoutAsNaNDouble) {
ASSERT_OK(sw.getStatus());
WriteConcernOptions options = sw.getValue();
ASSERT_TRUE(WriteConcernOptions::SyncMode::UNSET == options.syncMode);
- ASSERT_EQUALS("", options.wMode);
- ASSERT_EQUALS(1, options.wNumNodes);
- ASSERT_EQUALS(0, options.wTimeout);
+ ASSERT_EQUALS(1, stdx::get<int64_t>(options.w));
+ ASSERT_EQUALS(WriteConcernOptions::kNoTimeout, options.wTimeout);
}
TEST(WriteConcernOptionsTest, ParseWTimeoutAsDoubleLargerThanInt) {
@@ -165,9 +156,8 @@ TEST(WriteConcernOptionsTest, ParseWTimeoutAsDoubleLargerThanInt) {
ASSERT_OK(sw.getStatus());
WriteConcernOptions options = sw.getValue();
ASSERT_TRUE(WriteConcernOptions::SyncMode::UNSET == options.syncMode);
- ASSERT_EQUALS("", options.wMode);
- ASSERT_EQUALS(1, options.wNumNodes);
- ASSERT_LESS_THAN(options.wTimeout, 0);
+ ASSERT_EQUALS(1, stdx::get<int64_t>(options.w));
+ ASSERT_EQUALS(options.wTimeout, Milliseconds{2999999999});
}
TEST(WriteConcernOptionsTest, ParseReturnsFailedToParseOnUnknownField) {
@@ -180,9 +170,8 @@ void _testIgnoreWriteConcernField(const char* fieldName) {
ASSERT_OK(sw.getStatus());
WriteConcernOptions options = sw.getValue();
ASSERT_TRUE(WriteConcernOptions::SyncMode::UNSET == options.syncMode);
- ASSERT_EQUALS("", options.wMode);
- ASSERT_EQUALS(1, options.wNumNodes);
- ASSERT_EQUALS(0, options.wTimeout);
+ ASSERT_EQUALS(1, stdx::get<int64_t>(options.w));
+ ASSERT_EQUALS(WriteConcernOptions::kNoTimeout, options.wTimeout);
}
TEST(WriteConcernOptionsTest, ParseIgnoresSpecialFields) {
_testIgnoreWriteConcernField("wElectionId");
@@ -195,20 +184,18 @@ TEST(WriteConcernOptionsTest, ParseWithTags) {
<< "def")))
.getStatus();
ASSERT_EQUALS(ErrorCodes::FailedToParse, status);
- ASSERT_EQUALS("tags must be a single level document with only number values", status.reason());
+ ASSERT_STRING_CONTAINS(status.reason(),
+ "tags must be a single level document with only number values");
auto sw = WriteConcernOptions::parse(BSON("w" << BSON("abc" << 1)));
ASSERT_OK(sw.getStatus());
WriteConcernOptions wc = sw.getValue();
- ASSERT_EQ(wc.wNumNodes, 0);
- ASSERT_TRUE(wc.wMode.empty());
ASSERT_EQ(wc.wTimeout, WriteConcernOptions::kNoTimeout);
ASSERT_TRUE(wc.needToWaitForOtherNodes());
- auto tags = wc.wTags();
- ASSERT(tags.has_value());
- ASSERT_BSONOBJ_EQ(*tags, BSON("abc" << 1));
+ auto tags = stdx::get<WTags>(wc.w);
+ ASSERT(tags == (WTags{{"abc", 1}}));
ASSERT_BSONOBJ_EQ(wc.toBSON(), BSON("w" << BSON("abc" << 1) << "wtimeout" << 0));
auto wc2 = uassertStatusOK(WriteConcernOptions::parse(BSON("w" << BSON("abc" << 1))));
diff --git a/src/mongo/embedded/read_concern_embedded.cpp b/src/mongo/embedded/read_concern_embedded.cpp
index 708b41bc279..52bdf708c23 100644
--- a/src/mongo/embedded/read_concern_embedded.cpp
+++ b/src/mongo/embedded/read_concern_embedded.cpp
@@ -64,7 +64,8 @@ Status waitForSpeculativeMajorityReadConcernImpl(
return Status::OK();
}
-Status waitForLinearizableReadConcernImpl(OperationContext* opCtx, int readConcernTimeout) {
+Status waitForLinearizableReadConcernImpl(OperationContext* opCtx,
+ Milliseconds readConcernTimeout) {
return Status::OK();
}
diff --git a/src/mongo/embedded/service_entry_point_embedded.cpp b/src/mongo/embedded/service_entry_point_embedded.cpp
index 4a8a163f763..927d2e5d2de 100644
--- a/src/mongo/embedded/service_entry_point_embedded.cpp
+++ b/src/mongo/embedded/service_entry_point_embedded.cpp
@@ -109,7 +109,7 @@ public:
void waitForLinearizableReadConcern(OperationContext* opCtx) const override {
if (repl::ReadConcernArgs::get(opCtx).getLevel() ==
repl::ReadConcernLevel::kLinearizableReadConcern) {
- uassertStatusOK(mongo::waitForLinearizableReadConcern(opCtx, 0));
+ uassertStatusOK(mongo::waitForLinearizableReadConcern(opCtx, Milliseconds::zero()));
}
}
diff --git a/src/mongo/idl/basic_types.h b/src/mongo/idl/basic_types.h
index a725e9a8c87..ccc357630a5 100644
--- a/src/mongo/idl/basic_types.h
+++ b/src/mongo/idl/basic_types.h
@@ -30,6 +30,7 @@
#pragma once
#include "mongo/util/assert_util.h"
+#include "mongo/util/visit_helper.h"
#include <boost/optional.hpp>
#include "mongo/base/string_data.h"
@@ -37,6 +38,8 @@
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/stdx/variant.h"
+using namespace fmt::literals;
+
namespace mongo {
/**
@@ -185,59 +188,54 @@ private:
BSONObj _obj;
};
-class WriteConcernW {
-public:
- static WriteConcernW deserializeWriteConcernW(BSONElement wEl) {
- if (wEl.isNumber()) {
- return WriteConcernW{wEl.safeNumberLong()};
- } else if (wEl.type() == BSONType::String) {
- return WriteConcernW{wEl.str()};
- } else if (wEl.type() == BSONType::Object) {
- auto tags = wEl.Obj().getOwned();
- auto valid =
- std::all_of(tags.begin(), tags.end(), [](BSONElement e) { return e.isNumber(); });
- uassert(ErrorCodes::FailedToParse,
- "tags must be a single level document with only number values",
- valid);
-
- return WriteConcernW{std::move(tags)};
- } else if (wEl.eoo() || wEl.type() == BSONType::jstNULL ||
- wEl.type() == BSONType::Undefined) {
- return WriteConcernW{};
+using WTags = StringMap<int64_t>;
+using WriteConcernW = stdx::variant<std::string, std::int64_t, WTags>;
+
+inline static const int64_t kMaxMembers = 50;
+inline WriteConcernW deserializeWriteConcernW(BSONElement wEl) {
+ if (wEl.isNumber()) {
+ auto wNum = wEl.safeNumberLong();
+ if (wNum < 0 || wNum > kMaxMembers) {
+ uasserted(ErrorCodes::FailedToParse,
+ "w has to be a non-negative number and not greater than {}; found: {}"_format(
+ kMaxMembers, wNum));
}
- uasserted(ErrorCodes::FailedToParse, "w has to be a number, string, or object");
- }
- void serializeWriteConcernW(StringData fieldName, BSONObjBuilder* builder) const {
- if (auto stringVal = stdx::get_if<std::string>(&_w)) {
- builder->append(fieldName, *stringVal);
- } else if (auto objVal = stdx::get_if<BSONObj>(&_w)) {
- builder->append(fieldName, *objVal);
- } else {
- auto intVal = stdx::get_if<std::int64_t>(&_w);
- invariant(intVal);
- builder->appendNumber(fieldName, static_cast<long long>(*intVal));
+ return WriteConcernW{wNum};
+ } else if (wEl.type() == BSONType::String) {
+ return WriteConcernW{wEl.str()};
+ } else if (wEl.type() == BSONType::Object) {
+ WTags tags;
+ for (auto e : wEl.Obj()) {
+ uassert(
+ ErrorCodes::FailedToParse,
+ "tags must be a single level document with only number values; found: {}"_format(
+ e.toString()),
+ e.isNumber());
+
+ tags.try_emplace(e.fieldName(), e.safeNumberInt());
}
- }
-
- WriteConcernW() : _w{1}, _usedDefaultConstructedW1{true} {};
-
- bool usedDefaultConstructedW1() const {
- return _usedDefaultConstructedW1;
- }
- stdx::variant<std::string, std::int64_t, BSONObj> getValue() const {
- return _w;
+ return WriteConcernW{std::move(tags)};
+ } else if (wEl.eoo() || wEl.type() == BSONType::jstNULL || wEl.type() == BSONType::Undefined) {
+ return WriteConcernW{};
}
+ uasserted(ErrorCodes::FailedToParse,
+ "w has to be a number, string, or object; found: {}"_format(typeName(wEl.type())));
+}
-private:
- WriteConcernW(std::int64_t w) : _w{w}, _usedDefaultConstructedW1{false} {};
- WriteConcernW(std::string&& w) : _w(std::move(w)), _usedDefaultConstructedW1{false} {};
- WriteConcernW(BSONObj&& tags) : _w(std::move(tags)), _usedDefaultConstructedW1{false} {};
-
- stdx::variant<std::string, std::int64_t, BSONObj> _w;
- bool _usedDefaultConstructedW1;
-};
+inline void serializeWriteConcernW(const WriteConcernW& w,
+ StringData fieldName,
+ BSONObjBuilder* builder) {
+ stdx::visit(
+ visit_helper::Overloaded{[&](int64_t wNumNodes) {
+ builder->appendNumber(fieldName,
+ static_cast<long long>(wNumNodes));
+ },
+ [&](std::string wMode) { builder->append(fieldName, wMode); },
+ [&](WTags wTags) { builder->append(fieldName, wTags); }},
+ w);
+}
inline std::int64_t parseWTimeoutFromBSON(BSONElement element) {
constexpr std::array<mongo::BSONType, 4> validTypes{
diff --git a/src/mongo/idl/basic_types.idl b/src/mongo/idl/basic_types.idl
index 03cf00ba413..971b2ed83f3 100644
--- a/src/mongo/idl/basic_types.idl
+++ b/src/mongo/idl/basic_types.idl
@@ -247,9 +247,8 @@ types:
A string or integer representing the 'w' option in a document specifying write concern.
See https://docs.mongodb.com/manual/reference/write-concern/"
cpp_type: "mongo::WriteConcernW"
- default: "mongo::WriteConcernW()"
- serializer: "mongo::WriteConcernW::serializeWriteConcernW"
- deserializer: "mongo::WriteConcernW::deserializeWriteConcernW"
+ serializer: "::mongo::serializeWriteConcernW"
+ deserializer: "::mongo::deserializeWriteConcernW"
writeConcernWTimeout:
bson_serialization_type: any
@@ -345,6 +344,7 @@ structs:
w:
type: writeConcernW
cpp_name: writeConcernW
+ optional: true
unstable: false
j:
type: safeBool
diff --git a/src/mongo/s/catalog/sharding_catalog_client_impl.cpp b/src/mongo/s/catalog/sharding_catalog_client_impl.cpp
index 80a826bfbc9..bf1bd427744 100644
--- a/src/mongo/s/catalog/sharding_catalog_client_impl.cpp
+++ b/src/mongo/s/catalog/sharding_catalog_client_impl.cpp
@@ -811,8 +811,18 @@ Status ShardingCatalogClientImpl::runUserManagementWriteCommand(OperationContext
}
writeConcern = sw.getValue();
- if ((writeConcern.wNumNodes != 1) &&
- (writeConcern.wMode != WriteConcernOptions::kMajority)) {
+ auto isValidUserManagementWriteConcern = stdx::visit(
+ [](auto&& arg) {
+ using T = std::decay_t<decltype(arg)>;
+ if constexpr (std::is_same_v<T, std::string>)
+ return arg == WriteConcernOptions::kMajority;
+ else if constexpr (std::is_same_v<T, int64_t>)
+ return arg == 1;
+ return false;
+ },
+ writeConcern.w);
+
+ if (!isValidUserManagementWriteConcern) {
return {ErrorCodes::InvalidOptions,
str::stream() << "Invalid replication write concern. User management write "
"commands may only use w:1 or w:'majority', got: "
@@ -820,8 +830,7 @@ Status ShardingCatalogClientImpl::runUserManagementWriteCommand(OperationContext
}
}
- writeConcern.wMode = WriteConcernOptions::kMajority;
- writeConcern.wNumNodes = 0;
+ writeConcern.w = WriteConcernOptions::kMajority;
BSONObjBuilder modifiedCmd;
if (!initialCmdHadWriteConcern) {
@@ -895,9 +904,9 @@ Status ShardingCatalogClientImpl::applyChunkOpsDeprecated(OperationContext* opCt
const ChunkVersion& lastChunkVersion,
const WriteConcernOptions& writeConcern,
repl::ReadConcernLevel readConcern) {
- invariant(serverGlobalParams.clusterRole == ClusterRole::ConfigServer ||
- (readConcern == repl::ReadConcernLevel::kMajorityReadConcern &&
- writeConcern.wMode == WriteConcernOptions::kMajority));
+ invariant(
+ serverGlobalParams.clusterRole == ClusterRole::ConfigServer ||
+ (readConcern == repl::ReadConcernLevel::kMajorityReadConcern && writeConcern.isMajority()));
BSONObj cmd =
BSON("applyOps" << updateOps << "preCondition" << preCondition
<< WriteConcernOptions::kWriteConcernField << writeConcern.toBSON());
diff --git a/src/mongo/s/commands/cluster_rwc_defaults_commands.cpp b/src/mongo/s/commands/cluster_rwc_defaults_commands.cpp
index 4ff2186adfa..606608cc914 100644
--- a/src/mongo/s/commands/cluster_rwc_defaults_commands.cpp
+++ b/src/mongo/s/commands/cluster_rwc_defaults_commands.cpp
@@ -78,7 +78,7 @@ public:
"A custom write concern is being set as the default write concern in a sharded "
"cluster. This set is unchecked, but if the custom write concern does not "
"exist on all shards in the cluster, errors will occur upon writes",
- "customWriteConcern"_attr = optWC->wMode);
+ "customWriteConcern"_attr = stdx::get<std::string>(optWC->w));
}
}
ReadWriteConcernDefaults::get(opCtx).setDefault(opCtx, std::move(newDefaults));
diff --git a/src/mongo/s/request_types/balance_chunk_request_test.cpp b/src/mongo/s/request_types/balance_chunk_request_test.cpp
index fbffcc9da77..a9e3d133519 100644
--- a/src/mongo/s/request_types/balance_chunk_request_test.cpp
+++ b/src/mongo/s/request_types/balance_chunk_request_test.cpp
@@ -114,7 +114,9 @@ TEST(BalanceChunkRequest, ParseFromConfigCommandWithSecondaryThrottle) {
const auto& secondaryThrottle = request.getSecondaryThrottle();
ASSERT_EQ(MigrationSecondaryThrottleOptions::kOn, secondaryThrottle.getSecondaryThrottle());
- ASSERT_EQ(2, secondaryThrottle.getWriteConcern().wNumNodes);
+
+ auto writeConcern = secondaryThrottle.getWriteConcern();
+ ASSERT_EQ(2, stdx::get<int64_t>(writeConcern.w));
}
} // namespace
diff --git a/src/mongo/s/request_types/migration_secondary_throttle_options.cpp b/src/mongo/s/request_types/migration_secondary_throttle_options.cpp
index c143fc9ea60..6142cff16d2 100644
--- a/src/mongo/s/request_types/migration_secondary_throttle_options.cpp
+++ b/src/mongo/s/request_types/migration_secondary_throttle_options.cpp
@@ -56,7 +56,8 @@ MigrationSecondaryThrottleOptions MigrationSecondaryThrottleOptions::create(
MigrationSecondaryThrottleOptions MigrationSecondaryThrottleOptions::createWithWriteConcern(
const WriteConcernOptions& writeConcern) {
// Optimize on write concern, which makes no difference
- if (writeConcern.wNumNodes <= 1 && writeConcern.wMode.empty()) {
+ if (stdx::holds_alternative<int64_t>(writeConcern.w) &&
+ stdx::get<int64_t>(writeConcern.w) <= 1) {
return MigrationSecondaryThrottleOptions(kOff, boost::none);
}
diff --git a/src/mongo/s/request_types/migration_secondary_throttle_options_test.cpp b/src/mongo/s/request_types/migration_secondary_throttle_options_test.cpp
index 59c3fb130bd..4d42b3cc8d5 100644
--- a/src/mongo/s/request_types/migration_secondary_throttle_options_test.cpp
+++ b/src/mongo/s/request_types/migration_secondary_throttle_options_test.cpp
@@ -89,7 +89,8 @@ TEST(MigrationSecondaryThrottleOptions, EnabledInCommandBSONWithSimpleWriteConce
ASSERT(options.isWriteConcernSpecified());
WriteConcernOptions writeConcern = options.getWriteConcern();
- ASSERT_EQ(2, writeConcern.wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(writeConcern.w));
+ ASSERT_EQ(2, stdx::get<int64_t>(writeConcern.w));
ASSERT_EQ(static_cast<int>(WriteConcernOptions::SyncMode::UNSET),
static_cast<int>(writeConcern.syncMode));
ASSERT_EQ(WriteConcernOptions::kNoTimeout, writeConcern.wTimeout);
@@ -104,7 +105,8 @@ TEST(MigrationSecondaryThrottleOptions, EnabledInCommandBSONWithCompleteWriteCon
ASSERT(options.isWriteConcernSpecified());
WriteConcernOptions writeConcern = options.getWriteConcern();
- ASSERT_EQ(3, writeConcern.wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(writeConcern.w));
+ ASSERT_EQ(3, stdx::get<int64_t>(writeConcern.w));
ASSERT_EQ(static_cast<int>(WriteConcernOptions::SyncMode::JOURNAL),
static_cast<int>(writeConcern.syncMode));
ASSERT_EQ(WriteConcernOptions::kNoTimeout, writeConcern.wTimeout);
@@ -141,7 +143,8 @@ TEST(MigrationSecondaryThrottleOptions, EnabledInBalancerConfigWithSimpleWriteCo
ASSERT(options.isWriteConcernSpecified());
WriteConcernOptions writeConcern = options.getWriteConcern();
- ASSERT_EQ(2, writeConcern.wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(writeConcern.w));
+ ASSERT_EQ(2, stdx::get<int64_t>(writeConcern.w));
ASSERT_EQ(static_cast<int>(WriteConcernOptions::SyncMode::UNSET),
static_cast<int>(writeConcern.syncMode));
ASSERT_EQ(WriteConcernOptions::kNoTimeout, writeConcern.wTimeout);
@@ -155,7 +158,8 @@ TEST(MigrationSecondaryThrottleOptions, EnabledInBalancerConfigWithCompleteWrite
ASSERT(options.isWriteConcernSpecified());
WriteConcernOptions writeConcern = options.getWriteConcern();
- ASSERT_EQ(3, writeConcern.wNumNodes);
+ ASSERT(stdx::holds_alternative<int64_t>(writeConcern.w));
+ ASSERT_EQ(3, stdx::get<int64_t>(writeConcern.w));
ASSERT_EQ(static_cast<int>(WriteConcernOptions::SyncMode::JOURNAL),
static_cast<int>(writeConcern.syncMode));
ASSERT_EQ(WriteConcernOptions::kNoTimeout, writeConcern.wTimeout);
@@ -189,19 +193,19 @@ TEST(MigrationSecondaryThrottleOptions, IgnoreWriteConcernWhenSecondaryThrottleA
}
TEST(MigrationSecondaryThrottleOptions, EqualityOperatorSameValue) {
- auto value1 = MigrationSecondaryThrottleOptions::createWithWriteConcern(
- WriteConcernOptions("majority", WriteConcernOptions::SyncMode::JOURNAL, 30000));
- auto value2 = MigrationSecondaryThrottleOptions::createWithWriteConcern(
- WriteConcernOptions("majority", WriteConcernOptions::SyncMode::JOURNAL, 30000));
+ auto value1 = MigrationSecondaryThrottleOptions::createWithWriteConcern(WriteConcernOptions{
+ "majority", WriteConcernOptions::SyncMode::JOURNAL, Milliseconds{30000}});
+ auto value2 = MigrationSecondaryThrottleOptions::createWithWriteConcern(WriteConcernOptions{
+ "majority", WriteConcernOptions::SyncMode::JOURNAL, Milliseconds{30000}});
ASSERT(value1 == value2);
}
TEST(MigrationSecondaryThrottleOptions, EqualityOperatorDifferentValues) {
- auto value1 = MigrationSecondaryThrottleOptions::createWithWriteConcern(
- WriteConcernOptions("majority", WriteConcernOptions::SyncMode::JOURNAL, 30000));
- auto value2 = MigrationSecondaryThrottleOptions::createWithWriteConcern(
- WriteConcernOptions("majority", WriteConcernOptions::SyncMode::JOURNAL, 60000));
+ auto value1 = MigrationSecondaryThrottleOptions::createWithWriteConcern(WriteConcernOptions{
+ "majority", WriteConcernOptions::SyncMode::JOURNAL, Milliseconds{30000}});
+ auto value2 = MigrationSecondaryThrottleOptions::createWithWriteConcern(WriteConcernOptions{
+ "majority", WriteConcernOptions::SyncMode::JOURNAL, Milliseconds{60000}});
ASSERT(!(value1 == value2));
}
diff --git a/src/mongo/s/transaction_router_test.cpp b/src/mongo/s/transaction_router_test.cpp
index 7c4c0c20cda..6d27a481839 100644
--- a/src/mongo/s/transaction_router_test.cpp
+++ b/src/mongo/s/transaction_router_test.cpp
@@ -1598,7 +1598,8 @@ TEST_F(TransactionRouterTest, CommitWithRecoveryTokenWithNoParticipants) {
opCtx->setLogicalSessionId(lsid);
opCtx->setTxnNumber(txnNum);
- WriteConcernOptions writeConcern(10, WriteConcernOptions::SyncMode::NONE, 0);
+ WriteConcernOptions writeConcern(
+ 10, WriteConcernOptions::SyncMode::NONE, WriteConcernOptions::kNoTimeout);
opCtx->setWriteConcern(writeConcern);
RouterOperationContextSession scopedSession(opCtx);
@@ -1669,7 +1670,8 @@ TEST_F(TransactionRouterTestWithDefaultSession,
auto opCtx = operationContext();
opCtx->setTxnNumber(txnNum);
- WriteConcernOptions writeConcern(10, WriteConcernOptions::SyncMode::NONE, 0);
+ WriteConcernOptions writeConcern(
+ 10, WriteConcernOptions::SyncMode::NONE, WriteConcernOptions::kNoTimeout);
opCtx->setWriteConcern(writeConcern);
auto txnRouter = TransactionRouter::get(opCtx);
@@ -1764,7 +1766,8 @@ TEST_F(TransactionRouterTestWithDefaultSession,
auto opCtx = operationContext();
opCtx->setTxnNumber(txnNum);
- WriteConcernOptions writeConcern(10, WriteConcernOptions::SyncMode::NONE, 0);
+ WriteConcernOptions writeConcern(
+ 10, WriteConcernOptions::SyncMode::NONE, WriteConcernOptions::kNoTimeout);
opCtx->setWriteConcern(writeConcern);
auto txnRouter = TransactionRouter::get(opCtx);
@@ -1861,7 +1864,8 @@ TEST_F(TransactionRouterTest, CommitWithEmptyRecoveryToken) {
opCtx->setLogicalSessionId(lsid);
opCtx->setTxnNumber(txnNum);
- WriteConcernOptions writeConcern(10, WriteConcernOptions::SyncMode::NONE, 0);
+ WriteConcernOptions writeConcern(
+ 10, WriteConcernOptions::SyncMode::NONE, WriteConcernOptions::kNoTimeout);
opCtx->setWriteConcern(writeConcern);
RouterOperationContextSession scopedSession(opCtx);
@@ -1883,7 +1887,8 @@ TEST_F(TransactionRouterTest, CommitWithRecoveryTokenWithUnknownShard) {
opCtx->setLogicalSessionId(lsid);
opCtx->setTxnNumber(txnNum);
- WriteConcernOptions writeConcern(10, WriteConcernOptions::SyncMode::NONE, 0);
+ WriteConcernOptions writeConcern(
+ 10, WriteConcernOptions::SyncMode::NONE, WriteConcernOptions::kNoTimeout);
opCtx->setWriteConcern(writeConcern);
RouterOperationContextSession scopedSession(opCtx);
@@ -1913,7 +1918,8 @@ TEST_F(TransactionRouterTestWithDefaultSession, CommitWithRecoveryTokenAndTxnRet
operationContext()->setTxnNumber(txnNum);
- WriteConcernOptions writeConcern(10, WriteConcernOptions::SyncMode::NONE, 0);
+ WriteConcernOptions writeConcern(
+ 10, WriteConcernOptions::SyncMode::NONE, WriteConcernOptions::kNoTimeout);
operationContext()->setWriteConcern(writeConcern);
auto txnRouter = TransactionRouter::get(operationContext());
@@ -2779,7 +2785,8 @@ TEST_F(TransactionRouterTestWithDefaultSession, AbortPropagatesWriteConcern) {
auto opCtx = operationContext();
auto txnRouter = TransactionRouter::get(opCtx);
- WriteConcernOptions writeConcern(10, WriteConcernOptions::SyncMode::NONE, 0);
+ WriteConcernOptions writeConcern(
+ 10, WriteConcernOptions::SyncMode::NONE, WriteConcernOptions::kNoTimeout);
opCtx->setWriteConcern(writeConcern);
txnRouter.beginOrContinueTxn(