summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLingzhi Deng <lingzhi.deng@mongodb.com>2019-10-05 13:16:42 +0000
committerevergreen <evergreen@mongodb.com>2019-10-05 13:16:42 +0000
commit150dfeceb607bb40bbae2e5a49ad9bca08f13e25 (patch)
tree15631469cf3b59fb6398a5df53748c6b74226cfb
parent2664c92b226bf94bb9da85c58b8820771c79c434 (diff)
downloadmongo-150dfeceb607bb40bbae2e5a49ad9bca08f13e25.tar.gz
SERVER-43769: Only get the default write concern from ReplSetConfig if no write concern is specified
-rw-r--r--src/mongo/db/repl/repl_set_config.cpp3
-rw-r--r--src/mongo/db/write_concern.cpp14
-rw-r--r--src/mongo/db/write_concern_options.cpp30
-rw-r--r--src/mongo/db/write_concern_options.h27
-rw-r--r--src/mongo/s/catalog/sharding_catalog_client_impl.cpp1
5 files changed, 29 insertions, 46 deletions
diff --git a/src/mongo/db/repl/repl_set_config.cpp b/src/mongo/db/repl/repl_set_config.cpp
index 434af8db845..6fa81e2aeb4 100644
--- a/src/mongo/db/repl/repl_set_config.cpp
+++ b/src/mongo/db/repl/repl_set_config.cpp
@@ -325,8 +325,7 @@ Status ReplSetConfig::_parseSettingsSubdocument(const BSONObj& settings) {
return status;
} else if (status == ErrorCodes::NoSuchKey) {
// Default write concern is w: 1.
- _defaultWriteConcern.reset();
- _defaultWriteConcern.wNumNodes = 1;
+ _defaultWriteConcern = WriteConcernOptions();
} else {
return status;
}
diff --git a/src/mongo/db/write_concern.cpp b/src/mongo/db/write_concern.cpp
index 8f05f50e370..30c01e5a831 100644
--- a/src/mongo/db/write_concern.cpp
+++ b/src/mongo/db/write_concern.cpp
@@ -72,14 +72,24 @@ StatusWith<WriteConcernOptions> extractWriteConcern(OperationContext* opCtx,
const BSONObj& cmdObj) {
// The default write concern if empty is {w:1}. Specifying {w:0} is/was allowed, but is
// interpreted identically to {w:1}.
- auto wcResult = WriteConcernOptions::extractWCFromCommand(
- cmdObj, repl::ReplicationCoordinator::get(opCtx)->getGetLastErrorDefault());
+ auto wcResult = WriteConcernOptions::extractWCFromCommand(cmdObj);
if (!wcResult.isOK()) {
return wcResult.getStatus();
}
WriteConcernOptions writeConcern = wcResult.getValue();
+ // Get the default write concern specified in ReplSetConfig only if no write concern is
+ // specified in the command (when usedDefault is true) to avoid locking the
+ // ReplicationCoordinator mutex unconditionally.
+ if (writeConcern.usedDefault) {
+ writeConcern = repl::ReplicationCoordinator::get(opCtx)->getGetLastErrorDefault();
+ if (writeConcern.wNumNodes == 0 && writeConcern.wMode.empty()) {
+ writeConcern.wNumNodes = 1;
+ }
+ writeConcern.usedDefaultW = true;
+ }
+
if (writeConcern.usedDefault && serverGlobalParams.clusterRole == ClusterRole::ConfigServer &&
!opCtx->getClient()->isInDirectClient() &&
(opCtx->getClient()->session() &&
diff --git a/src/mongo/db/write_concern_options.cpp b/src/mongo/db/write_concern_options.cpp
index 1ad40acebfd..22bb5b49790 100644
--- a/src/mongo/db/write_concern_options.cpp
+++ b/src/mongo/db/write_concern_options.cpp
@@ -92,7 +92,7 @@ WriteConcernOptions::WriteConcernOptions(const std::string& mode,
: syncMode(sync), wNumNodes(0), wMode(mode), wTimeout(durationCount<Milliseconds>(timeout)) {}
Status WriteConcernOptions::parse(const BSONObj& obj) {
- reset();
+ *this = WriteConcernOptions();
if (obj.isEmpty()) {
return Status(ErrorCodes::FailedToParse, "write concern object cannot be empty");
}
@@ -148,6 +148,7 @@ Status WriteConcernOptions::parse(const BSONObj& obj) {
wNumNodes = wEl.numberInt();
usedDefaultW = false;
} else if (wEl.type() == String) {
+ wNumNodes = 0;
wMode = wEl.valuestrsafe();
usedDefaultW = false;
} else if (wEl.eoo() || wEl.type() == jstNULL || wEl.type() == Undefined) {
@@ -159,37 +160,16 @@ Status WriteConcernOptions::parse(const BSONObj& obj) {
return Status::OK();
}
-namespace {
-
-/**
- * Construct a WriteConcernOptions based on an optional default WC object, in preparation for
- * parsing out of a command object or IDL.
- */
-WriteConcernOptions constructWCFromDefault(
- const WriteConcernOptions& defaultWC = WriteConcernOptions()) {
- WriteConcernOptions writeConcern = defaultWC;
- writeConcern.usedDefault = true;
- writeConcern.usedDefaultW = true;
- if (writeConcern.wNumNodes == 0 && writeConcern.wMode.empty()) {
- writeConcern.wNumNodes = 1;
- }
- return writeConcern;
-}
-
-} // namespace
-
-
WriteConcernOptions WriteConcernOptions::deserializerForIDL(const BSONObj& obj) {
- WriteConcernOptions writeConcern = constructWCFromDefault();
+ WriteConcernOptions writeConcern;
if (!obj.isEmpty()) {
uassertStatusOK(writeConcern.parse(obj));
}
return writeConcern;
}
-StatusWith<WriteConcernOptions> WriteConcernOptions::extractWCFromCommand(
- const BSONObj& cmdObj, const WriteConcernOptions& defaultWC) {
- WriteConcernOptions writeConcern = constructWCFromDefault(defaultWC);
+StatusWith<WriteConcernOptions> WriteConcernOptions::extractWCFromCommand(const BSONObj& cmdObj) {
+ WriteConcernOptions writeConcern;
// Return the default write concern if no write concern is provided. We check for the existence
// of the write concern field up front in order to avoid the expense of constructing an error
diff --git a/src/mongo/db/write_concern_options.h b/src/mongo/db/write_concern_options.h
index 39025832ea0..c20ba6287fa 100644
--- a/src/mongo/db/write_concern_options.h
+++ b/src/mongo/db/write_concern_options.h
@@ -57,13 +57,16 @@ public:
static constexpr Seconds kWriteConcernTimeoutSharding{60};
static constexpr Seconds kWriteConcernTimeoutUserCommand{60};
- WriteConcernOptions() {
- reset();
- // 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 this flag accordingly.
- usedDefault = true;
- }
+ // 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 usedDefault and usedDefaultW flag correctly.
+ WriteConcernOptions()
+ : syncMode(SyncMode::UNSET),
+ wNumNodes(1),
+ wMode(""),
+ wTimeout(0),
+ usedDefault(true),
+ usedDefaultW(true) {}
WriteConcernOptions(int numNodes, SyncMode sync, int timeout);
@@ -86,8 +89,7 @@ public:
* Attempts to extract a writeConcern from cmdObj.
* Verifies that the writeConcern is of type Object (BSON type).
*/
- static StatusWith<WriteConcernOptions> extractWCFromCommand(
- const BSONObj& cmdObj, const WriteConcernOptions& defaultWC = WriteConcernOptions());
+ static StatusWith<WriteConcernOptions> extractWCFromCommand(const BSONObj& cmdObj);
/**
* Return true if the server needs to wait for other secondary nodes to satisfy this
@@ -95,13 +97,6 @@ public:
*/
bool needToWaitForOtherNodes() const;
- void reset() {
- syncMode = SyncMode::UNSET;
- wNumNodes = 0;
- wMode = "";
- wTimeout = 0;
- }
-
// Returns the BSON representation of this object.
// Warning: does not return the same object passed on the last parse() call.
BSONObj toBSON() const;
diff --git a/src/mongo/s/catalog/sharding_catalog_client_impl.cpp b/src/mongo/s/catalog/sharding_catalog_client_impl.cpp
index 4776fed9ed3..4ced819df8a 100644
--- a/src/mongo/s/catalog/sharding_catalog_client_impl.cpp
+++ b/src/mongo/s/catalog/sharding_catalog_client_impl.cpp
@@ -590,7 +590,6 @@ bool ShardingCatalogClientImpl::runUserManagementWriteCommand(OperationContext*
// Make sure that if the command has a write concern that it is w:1 or w:majority, and
// convert w:1 or no write concern to w:majority before sending.
WriteConcernOptions writeConcern;
- writeConcern.reset();
BSONElement writeConcernElement = cmdObj[WriteConcernOptions::kWriteConcernField];
bool initialCmdHadWriteConcern = !writeConcernElement.eoo();