summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands
diff options
context:
space:
mode:
authorJudah Schvimer <judah@mongodb.com>2016-04-12 19:11:23 -0400
committerJudah Schvimer <judah@mongodb.com>2016-04-12 19:11:23 -0400
commit7ed530a55304bd9cc2b80c054f379b10d9cea8e2 (patch)
treeff1dac44961da031f3369f0288fb38a347d0d690 /src/mongo/db/commands
parentb0c0acc6767a74ed2e5aa50361ad4474291951f9 (diff)
downloadmongo-7ed530a55304bd9cc2b80c054f379b10d9cea8e2.tar.gz
SERVER-20224 commands that write support writeConcern
Diffstat (limited to 'src/mongo/db/commands')
-rw-r--r--src/mongo/db/commands/apply_ops_cmd.cpp21
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp6
-rw-r--r--src/mongo/db/commands/authentication_commands.h3
-rw-r--r--src/mongo/db/commands/clone.cpp4
-rw-r--r--src/mongo/db/commands/clone_collection.cpp4
-rw-r--r--src/mongo/db/commands/collection_to_capped.cpp6
-rw-r--r--src/mongo/db/commands/compact.cpp3
-rw-r--r--src/mongo/db/commands/conn_pool_stats.cpp4
-rw-r--r--src/mongo/db/commands/conn_pool_sync.cpp3
-rw-r--r--src/mongo/db/commands/connection_status.cpp3
-rw-r--r--src/mongo/db/commands/copydb.cpp3
-rw-r--r--src/mongo/db/commands/copydb_start_commands.cpp8
-rw-r--r--src/mongo/db/commands/count_cmd.cpp3
-rw-r--r--src/mongo/db/commands/cpuprofile.cpp3
-rw-r--r--src/mongo/db/commands/create_indexes.cpp3
-rw-r--r--src/mongo/db/commands/current_op.cpp4
-rw-r--r--src/mongo/db/commands/dbhash.cpp4
-rw-r--r--src/mongo/db/commands/distinct.cpp3
-rw-r--r--src/mongo/db/commands/drop_indexes.cpp6
-rw-r--r--src/mongo/db/commands/explain_cmd.cpp4
-rw-r--r--src/mongo/db/commands/fail_point_cmd.cpp4
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp24
-rw-r--r--src/mongo/db/commands/find_cmd.cpp4
-rw-r--r--src/mongo/db/commands/fsync.cpp7
-rw-r--r--src/mongo/db/commands/generic.cpp28
-rw-r--r--src/mongo/db/commands/geo_near_cmd.cpp3
-rw-r--r--src/mongo/db/commands/get_last_error.cpp9
-rw-r--r--src/mongo/db/commands/getmore_cmd.cpp4
-rw-r--r--src/mongo/db/commands/group_cmd.cpp4
-rw-r--r--src/mongo/db/commands/hashcmd.cpp3
-rw-r--r--src/mongo/db/commands/index_filter_commands.cpp4
-rw-r--r--src/mongo/db/commands/index_filter_commands.h2
-rw-r--r--src/mongo/db/commands/isself.cpp3
-rw-r--r--src/mongo/db/commands/kill_op.cpp4
-rw-r--r--src/mongo/db/commands/killcursors_common.h4
-rw-r--r--src/mongo/db/commands/list_collections.cpp3
-rw-r--r--src/mongo/db/commands/list_databases.cpp3
-rw-r--r--src/mongo/db/commands/list_indexes.cpp3
-rw-r--r--src/mongo/db/commands/mr.cpp23
-rw-r--r--src/mongo/db/commands/mr.h6
-rw-r--r--src/mongo/db/commands/mr_common.cpp10
-rw-r--r--src/mongo/db/commands/oplog_note.cpp3
-rw-r--r--src/mongo/db/commands/parallel_collection_scan.cpp3
-rw-r--r--src/mongo/db/commands/parameters.cpp6
-rw-r--r--src/mongo/db/commands/pipeline_command.cpp9
-rw-r--r--src/mongo/db/commands/plan_cache_commands.cpp4
-rw-r--r--src/mongo/db/commands/plan_cache_commands.h2
-rw-r--r--src/mongo/db/commands/rename_collection_cmd.cpp3
-rw-r--r--src/mongo/db/commands/repair_cursor.cpp3
-rw-r--r--src/mongo/db/commands/server_status.cpp3
-rw-r--r--src/mongo/db/commands/shutdown.h3
-rw-r--r--src/mongo/db/commands/snapshot_management.cpp6
-rw-r--r--src/mongo/db/commands/test_commands.cpp13
-rw-r--r--src/mongo/db/commands/top_command.cpp3
-rw-r--r--src/mongo/db/commands/touch.cpp3
-rw-r--r--src/mongo/db/commands/user_management_commands.cpp190
-rw-r--r--src/mongo/db/commands/validate.cpp3
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.cpp53
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp11
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.h2
60 files changed, 450 insertions, 126 deletions
diff --git a/src/mongo/db/commands/apply_ops_cmd.cpp b/src/mongo/db/commands/apply_ops_cmd.cpp
index 2301916ef6c..12df18040a9 100644
--- a/src/mongo/db/commands/apply_ops_cmd.cpp
+++ b/src/mongo/db/commands/apply_ops_cmd.cpp
@@ -53,7 +53,6 @@
#include "mongo/db/repl/oplog.h"
#include "mongo/db/repl/repl_client_info.h"
#include "mongo/db/repl/replication_coordinator_global.h"
-#include "mongo/db/write_concern.h"
#include "mongo/util/log.h"
#include "mongo/util/scopeguard.h"
@@ -72,6 +71,10 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
+
virtual void help(stringstream& help) const {
help << "internal (sharding)\n{ applyOps : [ ] , preCondition : [ { ns : ... , q : ... , "
"res : ... } ] }";
@@ -112,14 +115,6 @@ public:
}
}
- StatusWith<WriteConcernOptions> wcResult = extractWriteConcern(txn, cmdObj, dbname);
- if (!wcResult.isOK()) {
- return appendCommandStatus(result, wcResult.getStatus());
- }
- txn->setWriteConcern(wcResult.getValue());
- setupSynchronousCommit(txn);
-
-
auto client = txn->getClient();
auto lastOpAtOperationStart = repl::ReplClientInfo::forClient(client).getLastOp();
ScopeGuard lastOpSetterGuard =
@@ -136,14 +131,6 @@ public:
lastOpSetterGuard.Dismiss();
}
- WriteConcernResult res;
- auto waitForWCStatus =
- waitForWriteConcern(txn,
- repl::ReplClientInfo::forClient(txn->getClient()).getLastOp(),
- txn->getWriteConcern(),
- &res);
- appendCommandWCStatus(result, waitForWCStatus);
-
return applyOpsStatus;
}
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index b30a7694417..6fc6268a807 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -105,6 +105,9 @@ public:
void help(stringstream& h) const {
h << "internal";
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {} // No auth required
@@ -360,6 +363,9 @@ public:
void help(stringstream& h) const {
h << "de-authenticate";
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
CmdLogout() : Command("logout") {}
bool run(OperationContext* txn,
const string& dbname,
diff --git a/src/mongo/db/commands/authentication_commands.h b/src/mongo/db/commands/authentication_commands.h
index d11ae5bc536..4b1caf54913 100644
--- a/src/mongo/db/commands/authentication_commands.h
+++ b/src/mongo/db/commands/authentication_commands.h
@@ -46,6 +46,9 @@ public:
virtual void help(std::stringstream& ss) const {
ss << "internal";
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {} // No auth required
diff --git a/src/mongo/db/commands/clone.cpp b/src/mongo/db/commands/clone.cpp
index 499b8827a76..9ce858feb3d 100644
--- a/src/mongo/db/commands/clone.cpp
+++ b/src/mongo/db/commands/clone.cpp
@@ -60,6 +60,10 @@ public:
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
+
virtual void help(stringstream& help) const {
help << "clone this database from an instance of the db on another host\n";
help << "{clone: \"host13\"[, slaveOk: <bool>]}";
diff --git a/src/mongo/db/commands/clone_collection.cpp b/src/mongo/db/commands/clone_collection.cpp
index efd3500d395..85bd9c6b1ab 100644
--- a/src/mongo/db/commands/clone_collection.cpp
+++ b/src/mongo/db/commands/clone_collection.cpp
@@ -71,6 +71,10 @@ public:
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
+
virtual std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const {
return parseNsFullyQualified(dbname, cmdObj);
}
diff --git a/src/mongo/db/commands/collection_to_capped.cpp b/src/mongo/db/commands/collection_to_capped.cpp
index a0b283ebc49..03d8552e2ae 100644
--- a/src/mongo/db/commands/collection_to_capped.cpp
+++ b/src/mongo/db/commands/collection_to_capped.cpp
@@ -56,6 +56,9 @@ public:
virtual bool slaveOk() const {
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& help) const {
help << "{ cloneCollectionAsCapped:<fromName>, toCollection:<toName>, size:<sizeInBytes> }";
}
@@ -129,6 +132,9 @@ public:
virtual bool slaveOk() const {
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& help) const {
help << "{ convertToCapped:<fromCollectionName>, size:<sizeInBytes> }";
}
diff --git a/src/mongo/db/commands/compact.cpp b/src/mongo/db/commands/compact.cpp
index cff4a4c359b..a87f2167be6 100644
--- a/src/mongo/db/commands/compact.cpp
+++ b/src/mongo/db/commands/compact.cpp
@@ -56,6 +56,9 @@ using std::stringstream;
class CompactCmd : public Command {
public:
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool adminOnly() const {
return false;
}
diff --git a/src/mongo/db/commands/conn_pool_stats.cpp b/src/mongo/db/commands/conn_pool_stats.cpp
index ffd0945ed3f..2a3b2881d45 100644
--- a/src/mongo/db/commands/conn_pool_stats.cpp
+++ b/src/mongo/db/commands/conn_pool_stats.cpp
@@ -53,6 +53,10 @@ public:
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) override {
diff --git a/src/mongo/db/commands/conn_pool_sync.cpp b/src/mongo/db/commands/conn_pool_sync.cpp
index 839e3a045b4..cb9410d7619 100644
--- a/src/mongo/db/commands/conn_pool_sync.cpp
+++ b/src/mongo/db/commands/conn_pool_sync.cpp
@@ -43,6 +43,9 @@ public:
virtual void help(std::stringstream& help) const {
help << "internal";
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
diff --git a/src/mongo/db/commands/connection_status.cpp b/src/mongo/db/commands/connection_status.cpp
index 340bc032cdb..8cf1a94ebd6 100644
--- a/src/mongo/db/commands/connection_status.cpp
+++ b/src/mongo/db/commands/connection_status.cpp
@@ -44,6 +44,9 @@ public:
virtual bool slaveOk() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {} // No auth required
diff --git a/src/mongo/db/commands/copydb.cpp b/src/mongo/db/commands/copydb.cpp
index a0ad9c46d81..7619c87a20d 100644
--- a/src/mongo/db/commands/copydb.cpp
+++ b/src/mongo/db/commands/copydb.cpp
@@ -98,6 +98,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual Status checkAuthForCommand(ClientBasic* client,
const std::string& dbname,
diff --git a/src/mongo/db/commands/copydb_start_commands.cpp b/src/mongo/db/commands/copydb_start_commands.cpp
index feb96a9552a..e37695e4181 100644
--- a/src/mongo/db/commands/copydb_start_commands.cpp
+++ b/src/mongo/db/commands/copydb_start_commands.cpp
@@ -80,6 +80,10 @@ public:
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
@@ -149,6 +153,10 @@ public:
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
virtual Status checkAuthForCommand(ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
diff --git a/src/mongo/db/commands/count_cmd.cpp b/src/mongo/db/commands/count_cmd.cpp
index c292f27c40c..b8367c35642 100644
--- a/src/mongo/db/commands/count_cmd.cpp
+++ b/src/mongo/db/commands/count_cmd.cpp
@@ -55,6 +55,9 @@ using std::stringstream;
class CmdCount : public Command {
public:
CmdCount() : Command("count") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool slaveOk() const {
// ok on --slave setups
return repl::getGlobalReplicationCoordinator()->getSettings().isSlave();
diff --git a/src/mongo/db/commands/cpuprofile.cpp b/src/mongo/db/commands/cpuprofile.cpp
index 2706d44510b..24fbd034b81 100644
--- a/src/mongo/db/commands/cpuprofile.cpp
+++ b/src/mongo/db/commands/cpuprofile.cpp
@@ -91,6 +91,9 @@ public:
// This is an abuse of the global dbmutex. We only really need to
// ensure that only one cpuprofiler command runs at once; it would
// be fine for it to run concurrently with other operations.
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
};
/**
diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp
index cb1f09988d2..d99c74fc1ae 100644
--- a/src/mongo/db/commands/create_indexes.cpp
+++ b/src/mongo/db/commands/create_indexes.cpp
@@ -62,6 +62,9 @@ class CmdCreateIndex : public Command {
public:
CmdCreateIndex() : Command("createIndexes") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual bool slaveOk() const {
return false;
} // TODO: this could be made true...
diff --git a/src/mongo/db/commands/current_op.cpp b/src/mongo/db/commands/current_op.cpp
index 680a99ced73..fed56b550ad 100644
--- a/src/mongo/db/commands/current_op.cpp
+++ b/src/mongo/db/commands/current_op.cpp
@@ -54,6 +54,10 @@ public:
CurrentOpCommand() : Command("currentOp") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
bool slaveOk() const final {
return true;
}
diff --git a/src/mongo/db/commands/dbhash.cpp b/src/mongo/db/commands/dbhash.cpp
index dcb63a5936c..2bc75db0b74 100644
--- a/src/mongo/db/commands/dbhash.cpp
+++ b/src/mongo/db/commands/dbhash.cpp
@@ -64,6 +64,10 @@ class DBHashCmd : public Command {
public:
DBHashCmd() : Command("dbHash", false, "dbhash") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
virtual bool slaveOk() const {
return true;
}
diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp
index c03f6382fe0..966a7d5b32b 100644
--- a/src/mongo/db/commands/distinct.cpp
+++ b/src/mongo/db/commands/distinct.cpp
@@ -75,6 +75,9 @@ public:
virtual bool slaveOverrideOk() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
bool supportsReadConcern() const final {
return true;
}
diff --git a/src/mongo/db/commands/drop_indexes.cpp b/src/mongo/db/commands/drop_indexes.cpp
index cead3ea45c7..950cf437750 100644
--- a/src/mongo/db/commands/drop_indexes.cpp
+++ b/src/mongo/db/commands/drop_indexes.cpp
@@ -70,6 +70,9 @@ public:
virtual bool slaveOk() const {
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& help) const {
help << "drop indexes for a collection";
}
@@ -99,6 +102,9 @@ public:
virtual bool slaveOk() const {
return true;
} // can reindex on a secondary
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& help) const {
help << "re-index a collection";
}
diff --git a/src/mongo/db/commands/explain_cmd.cpp b/src/mongo/db/commands/explain_cmd.cpp
index dc467846603..b0c8f1baec3 100644
--- a/src/mongo/db/commands/explain_cmd.cpp
+++ b/src/mongo/db/commands/explain_cmd.cpp
@@ -57,6 +57,10 @@ public:
CmdExplain() : Command("explain") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
/**
* Running an explain on a secondary requires explicitly setting slaveOk.
*/
diff --git a/src/mongo/db/commands/fail_point_cmd.cpp b/src/mongo/db/commands/fail_point_cmd.cpp
index 65ca22d59e0..22de01b1d2c 100644
--- a/src/mongo/db/commands/fail_point_cmd.cpp
+++ b/src/mongo/db/commands/fail_point_cmd.cpp
@@ -70,6 +70,10 @@ public:
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
virtual bool adminOnly() const {
return true;
}
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index 32b48d4eb3e..c806e67bdb7 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -63,6 +63,7 @@
#include "mongo/db/repl/replication_coordinator_global.h"
#include "mongo/db/s/collection_sharding_state.h"
#include "mongo/db/write_concern.h"
+#include "mongo/s/d_state.h"
#include "mongo/util/log.h"
#include "mongo/util/scopeguard.h"
@@ -214,6 +215,9 @@ public:
bool slaveOk() const override {
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) override {
@@ -332,13 +336,6 @@ public:
const FindAndModifyRequest& args = parseStatus.getValue();
const NamespaceString& nsString = args.getNamespaceString();
- StatusWith<WriteConcernOptions> wcResult = extractWriteConcern(txn, cmdObj, dbName);
- if (!wcResult.isOK()) {
- return appendCommandStatus(result, wcResult.getStatus());
- }
- txn->setWriteConcern(wcResult.getValue());
- setupSynchronousCommit(txn);
-
boost::optional<DisableDocumentValidation> maybeDisableValidation;
if (shouldBypassDocumentValidationForCommand(cmdObj))
maybeDisableValidation.emplace(txn);
@@ -350,6 +347,11 @@ public:
&repl::ReplClientInfo::setLastOpToSystemLastOpTime,
txn);
+ // If this is the local database, don't set last op.
+ if (dbName == "local") {
+ lastOpSetterGuard.Dismiss();
+ }
+
// Although usually the PlanExecutor handles WCE internally, it will throw WCEs when it is
// executing a findAndModify. This is done to ensure that we can always match, modify, and
// return the document under concurrency, if a matching document exists.
@@ -507,14 +509,6 @@ public:
lastOpSetterGuard.Dismiss();
}
- WriteConcernResult res;
- auto waitForWCStatus =
- waitForWriteConcern(txn,
- repl::ReplClientInfo::forClient(txn->getClient()).getLastOp(),
- txn->getWriteConcern(),
- &res);
- appendCommandWCStatus(result, waitForWCStatus);
-
return true;
}
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index 82c63c01cf8..f3a9ea67897 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -72,6 +72,10 @@ public:
FindCmd() : Command("find") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
bool slaveOk() const override {
return false;
}
diff --git a/src/mongo/db/commands/fsync.cpp b/src/mongo/db/commands/fsync.cpp
index 8bc028c926f..d8545f0853d 100644
--- a/src/mongo/db/commands/fsync.cpp
+++ b/src/mongo/db/commands/fsync.cpp
@@ -103,6 +103,9 @@ public:
locked = false;
pendingUnlock = false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool slaveOk() const {
return true;
}
@@ -185,6 +188,10 @@ public:
FSyncUnlockCommand() : Command("fsyncUnlock") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
bool slaveOk() const override {
return true;
}
diff --git a/src/mongo/db/commands/generic.cpp b/src/mongo/db/commands/generic.cpp
index 9795e7f2b3e..05724e33705 100644
--- a/src/mongo/db/commands/generic.cpp
+++ b/src/mongo/db/commands/generic.cpp
@@ -78,6 +78,9 @@ public:
virtual bool adminOnly() const {
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {} // No auth required
@@ -110,6 +113,9 @@ public:
help << "a way to check that the server is alive. responds immediately even if server is "
"in a db lock.";
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {} // No auth required
@@ -133,6 +139,9 @@ public:
virtual bool slaveOk() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {} // No auth required
@@ -165,6 +174,10 @@ public:
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
virtual void help(stringstream& help) const {
help << "returns information about the daemon's host";
}
@@ -207,6 +220,9 @@ public:
class LogRotateCmd : public Command {
public:
LogRotateCmd() : Command("logRotate") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool slaveOk() const {
return true;
}
@@ -240,6 +256,9 @@ public:
help << "get a list of all db commands";
}
ListCommandsCmd() : Command("listCommands", false) {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool slaveOk() const {
return true;
}
@@ -341,6 +360,9 @@ public:
virtual bool slaveOk() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {} // No auth required
@@ -363,6 +385,9 @@ public:
virtual bool slaveOk() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool adminOnly() const {
return true;
}
@@ -430,6 +455,9 @@ public:
void help(stringstream& h) const {
h << "get argv";
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool adminOnly() const {
return true;
}
diff --git a/src/mongo/db/commands/geo_near_cmd.cpp b/src/mongo/db/commands/geo_near_cmd.cpp
index 743329370be..080903e2320 100644
--- a/src/mongo/db/commands/geo_near_cmd.cpp
+++ b/src/mongo/db/commands/geo_near_cmd.cpp
@@ -63,6 +63,9 @@ class Geo2dFindNearCmd : public Command {
public:
Geo2dFindNearCmd() : Command("geoNear") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
bool slaveOk() const {
return true;
}
diff --git a/src/mongo/db/commands/get_last_error.cpp b/src/mongo/db/commands/get_last_error.cpp
index 4b026165cb0..98fbdcb9049 100644
--- a/src/mongo/db/commands/get_last_error.cpp
+++ b/src/mongo/db/commands/get_last_error.cpp
@@ -56,6 +56,9 @@ using std::stringstream;
*/
class CmdResetError : public Command {
public:
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool slaveOk() const {
return true;
}
@@ -80,6 +83,9 @@ public:
class CmdGetLastError : public Command {
public:
CmdGetLastError() : Command("getLastError", false, "getlasterror") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool slaveOk() const {
return true;
}
@@ -283,6 +289,9 @@ public:
class CmdGetPrevError : public Command {
public:
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void help(stringstream& help) const {
help << "check for errors since last reseterror commandcal";
}
diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp
index 0d474ed100d..9b7e54b04ca 100644
--- a/src/mongo/db/commands/getmore_cmd.cpp
+++ b/src/mongo/db/commands/getmore_cmd.cpp
@@ -80,6 +80,10 @@ public:
GetMoreCmd() : Command("getMore") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
bool slaveOk() const override {
return true;
}
diff --git a/src/mongo/db/commands/group_cmd.cpp b/src/mongo/db/commands/group_cmd.cpp
index e49a9081b49..25554261b69 100644
--- a/src/mongo/db/commands/group_cmd.cpp
+++ b/src/mongo/db/commands/group_cmd.cpp
@@ -52,6 +52,10 @@ public:
GroupCommand() : Command("group") {}
private:
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
virtual bool maintenanceOk() const {
return false;
}
diff --git a/src/mongo/db/commands/hashcmd.cpp b/src/mongo/db/commands/hashcmd.cpp
index f65690dddb3..76c1960f804 100644
--- a/src/mongo/db/commands/hashcmd.cpp
+++ b/src/mongo/db/commands/hashcmd.cpp
@@ -53,6 +53,9 @@ using std::stringstream;
class CmdHashElt : public Command {
public:
CmdHashElt() : Command("_hashBSONElement"){};
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool slaveOk() const {
return true;
}
diff --git a/src/mongo/db/commands/index_filter_commands.cpp b/src/mongo/db/commands/index_filter_commands.cpp
index 936dab77670..287e7e5950f 100644
--- a/src/mongo/db/commands/index_filter_commands.cpp
+++ b/src/mongo/db/commands/index_filter_commands.cpp
@@ -145,6 +145,10 @@ bool IndexFilterCommand::run(OperationContext* txn,
}
+bool IndexFilterCommand::supportsWriteConcern(const BSONObj& cmd) const {
+ return false;
+}
+
bool IndexFilterCommand::slaveOk() const {
return false;
}
diff --git a/src/mongo/db/commands/index_filter_commands.h b/src/mongo/db/commands/index_filter_commands.h
index ddd2553823a..7ba1157bef7 100644
--- a/src/mongo/db/commands/index_filter_commands.h
+++ b/src/mongo/db/commands/index_filter_commands.h
@@ -70,6 +70,8 @@ public:
std::string& errmsg,
BSONObjBuilder& result);
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override;
+
virtual bool slaveOk() const;
virtual bool slaveOverrideOk() const;
diff --git a/src/mongo/db/commands/isself.cpp b/src/mongo/db/commands/isself.cpp
index a3d8a3af918..0db7ba01440 100644
--- a/src/mongo/db/commands/isself.cpp
+++ b/src/mongo/db/commands/isself.cpp
@@ -45,6 +45,9 @@ public:
virtual bool slaveOk() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void help(stringstream& help) const {
help << "{ _isSelf : 1 } INTERNAL ONLY";
}
diff --git a/src/mongo/db/commands/kill_op.cpp b/src/mongo/db/commands/kill_op.cpp
index 753d48b9362..57838d625d1 100644
--- a/src/mongo/db/commands/kill_op.cpp
+++ b/src/mongo/db/commands/kill_op.cpp
@@ -50,6 +50,10 @@ public:
KillOpCommand() : Command("killOp") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
bool slaveOk() const final {
return true;
}
diff --git a/src/mongo/db/commands/killcursors_common.h b/src/mongo/db/commands/killcursors_common.h
index 7d082063858..db92c7ab21b 100644
--- a/src/mongo/db/commands/killcursors_common.h
+++ b/src/mongo/db/commands/killcursors_common.h
@@ -42,6 +42,10 @@ public:
KillCursorsCmdBase() : Command("killCursors") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
bool slaveOk() const final {
return true;
}
diff --git a/src/mongo/db/commands/list_collections.cpp b/src/mongo/db/commands/list_collections.cpp
index abd8302434f..0f9876420de 100644
--- a/src/mongo/db/commands/list_collections.cpp
+++ b/src/mongo/db/commands/list_collections.cpp
@@ -149,6 +149,9 @@ public:
virtual bool adminOnly() const {
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void help(stringstream& help) const {
help << "list collections for this db";
diff --git a/src/mongo/db/commands/list_databases.cpp b/src/mongo/db/commands/list_databases.cpp
index f7184d7de7d..88978246b19 100644
--- a/src/mongo/db/commands/list_databases.cpp
+++ b/src/mongo/db/commands/list_databases.cpp
@@ -57,6 +57,9 @@ public:
virtual bool adminOnly() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void help(stringstream& help) const {
help << "list databases on this server";
}
diff --git a/src/mongo/db/commands/list_indexes.cpp b/src/mongo/db/commands/list_indexes.cpp
index 5d443e98e4b..f6d144de358 100644
--- a/src/mongo/db/commands/list_indexes.cpp
+++ b/src/mongo/db/commands/list_indexes.cpp
@@ -82,6 +82,9 @@ public:
virtual bool adminOnly() const {
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void help(stringstream& help) const {
help << "list indexes for a collection";
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index 56aedcd16ae..9e5e6259d3e 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -602,7 +602,7 @@ long long State::postProcessCollectionNonAtomic(OperationContext* txn,
ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lock(txn->lockState()); // TODO(erh): why global???
// replace: just rename from temp to final collection name, dropping previous collection
- _db.dropCollection(_config.outputOptions.finalNamespace);
+ _db.dropCollection(_config.outputOptions.finalNamespace, txn->getWriteConcern());
BSONObj info;
if (!_db.runCommand("admin",
@@ -613,7 +613,7 @@ long long State::postProcessCollectionNonAtomic(OperationContext* txn,
uasserted(10076, str::stream() << "rename failed: " << info);
}
- _db.dropCollection(_config.tempNamespace);
+ _db.dropCollection(_config.tempNamespace, txn->getWriteConcern());
} else if (_config.outputOptions.outType == Config::MERGE) {
// merge: upsert new docs into old collection
{
@@ -632,7 +632,7 @@ long long State::postProcessCollectionNonAtomic(OperationContext* txn,
Helpers::upsert(_txn, _config.outputOptions.finalNamespace, o);
pm.hit();
}
- _db.dropCollection(_config.tempNamespace);
+ _db.dropCollection(_config.tempNamespace, txn->getWriteConcern());
pm.finished();
} else if (_config.outputOptions.outType == Config::REDUCE) {
// reduce: apply reduce op on new result and existing one
@@ -1287,6 +1287,10 @@ public:
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return mrSupportsWriteConcern(cmd);
+ }
+
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
@@ -1301,6 +1305,11 @@ public:
BSONObjBuilder& result) {
Timer t;
+ // Save and reset the write concern so that it doesn't get changed accidentally by
+ // DBDirectClient.
+ auto oldWC = txn->getWriteConcern();
+ ON_BLOCK_EXIT([txn, oldWC] { txn->setWriteConcern(oldWC); });
+
boost::optional<DisableDocumentValidation> maybeDisableValidation;
if (shouldBypassDocumentValidationForCommand(cmd))
maybeDisableValidation.emplace(txn);
@@ -1588,6 +1597,9 @@ public:
virtual bool slaveOverrideOk() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
@@ -1609,6 +1621,11 @@ public:
<< dbname));
}
+ // Save and reset the write concern so that it doesn't get changed accidentally by
+ // DBDirectClient.
+ auto oldWC = txn->getWriteConcern();
+ ON_BLOCK_EXIT([txn, oldWC] { txn->setWriteConcern(oldWC); });
+
boost::optional<DisableDocumentValidation> maybeDisableValidation;
if (shouldBypassDocumentValidationForCommand(cmdObj))
maybeDisableValidation.emplace(txn);
diff --git a/src/mongo/db/commands/mr.h b/src/mongo/db/commands/mr.h
index 04b5f12a661..3d967438179 100644
--- a/src/mongo/db/commands/mr.h
+++ b/src/mongo/db/commands/mr.h
@@ -411,5 +411,11 @@ void addPrivilegesRequiredForMapReduce(Command* commandTemplate,
const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out);
+
+/**
+ * Returns true if the provided mapReduce command has an 'out' parameter.
+ */
+bool mrSupportsWriteConcern(const BSONObj& cmd);
+
} // end mr namespace
}
diff --git a/src/mongo/db/commands/mr_common.cpp b/src/mongo/db/commands/mr_common.cpp
index 4d11661fd2d..d180f276249 100644
--- a/src/mongo/db/commands/mr_common.cpp
+++ b/src/mongo/db/commands/mr_common.cpp
@@ -132,5 +132,15 @@ void addPrivilegesRequiredForMapReduce(Command* commandTemplate,
out->push_back(Privilege(outputResource, outputActions));
}
}
+
+bool mrSupportsWriteConcern(const BSONObj& cmd) {
+ if (!cmd.hasField("out")) {
+ return false;
+ } else if (cmd["out"].type() == Object && cmd["out"].Obj().hasField("inline")) {
+ return false;
+ } else {
+ return true;
+ }
+}
}
}
diff --git a/src/mongo/db/commands/oplog_note.cpp b/src/mongo/db/commands/oplog_note.cpp
index 6c96f0907b8..bebf6d4d13c 100644
--- a/src/mongo/db/commands/oplog_note.cpp
+++ b/src/mongo/db/commands/oplog_note.cpp
@@ -54,6 +54,9 @@ public:
virtual bool adminOnly() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& help) const {
help << "Adds a no-op entry to the oplog";
}
diff --git a/src/mongo/db/commands/parallel_collection_scan.cpp b/src/mongo/db/commands/parallel_collection_scan.cpp
index 4ca7a131f60..bc280f4b937 100644
--- a/src/mongo/db/commands/parallel_collection_scan.cpp
+++ b/src/mongo/db/commands/parallel_collection_scan.cpp
@@ -58,6 +58,9 @@ public:
ParallelCollectionScanCmd() : Command("parallelCollectionScan") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool slaveOk() const {
return true;
}
diff --git a/src/mongo/db/commands/parameters.cpp b/src/mongo/db/commands/parameters.cpp
index 17a85c757b3..c9bc974e040 100644
--- a/src/mongo/db/commands/parameters.cpp
+++ b/src/mongo/db/commands/parameters.cpp
@@ -71,6 +71,9 @@ public:
virtual bool adminOnly() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
@@ -118,6 +121,9 @@ public:
virtual bool adminOnly() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp
index b04d6ffe1ef..d8836346c5e 100644
--- a/src/mongo/db/commands/pipeline_command.cpp
+++ b/src/mongo/db/commands/pipeline_command.cpp
@@ -53,6 +53,7 @@
#include "mongo/db/query/get_executor.h"
#include "mongo/db/storage/storage_options.h"
#include "mongo/stdx/memory.h"
+#include "mongo/util/scopeguard.h"
namespace mongo {
@@ -154,6 +155,9 @@ public:
PipelineCommand() : Command(Pipeline::commandName) {} // command is called "aggregate"
// Locks are managed manually, in particular by DocumentSourceCursor.
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return Pipeline::aggSupportsWriteConcern(cmd);
+ }
virtual bool slaveOk() const {
return false;
}
@@ -199,6 +203,11 @@ public:
if (!pPipeline.get())
return false;
+ // Save and reset the write concern so that it doesn't get changed accidentally by
+ // DBDirectClient.
+ auto oldWC = txn->getWriteConcern();
+ ON_BLOCK_EXIT([txn, oldWC] { txn->setWriteConcern(oldWC); });
+
// This is outside of the if block to keep the object alive until the pipeline is finished.
BSONObj parsed;
if (kDebugBuild && !pPipeline->isExplain() && !pCtx->inShard) {
diff --git a/src/mongo/db/commands/plan_cache_commands.cpp b/src/mongo/db/commands/plan_cache_commands.cpp
index 49c25de5514..b7c408f3b3c 100644
--- a/src/mongo/db/commands/plan_cache_commands.cpp
+++ b/src/mongo/db/commands/plan_cache_commands.cpp
@@ -141,6 +141,10 @@ bool PlanCacheCommand::run(OperationContext* txn,
}
+bool PlanCacheCommand::supportsWriteConcern(const BSONObj& cmd) const {
+ return false;
+}
+
bool PlanCacheCommand::slaveOk() const {
return false;
}
diff --git a/src/mongo/db/commands/plan_cache_commands.h b/src/mongo/db/commands/plan_cache_commands.h
index f419eaed8eb..87316b84178 100644
--- a/src/mongo/db/commands/plan_cache_commands.h
+++ b/src/mongo/db/commands/plan_cache_commands.h
@@ -64,6 +64,8 @@ public:
std::string& errmsg,
BSONObjBuilder& result);
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override;
+
virtual bool slaveOk() const;
virtual bool slaveOverrideOk() const;
diff --git a/src/mongo/db/commands/rename_collection_cmd.cpp b/src/mongo/db/commands/rename_collection_cmd.cpp
index b2b12c5fed3..eb42664c57b 100644
--- a/src/mongo/db/commands/rename_collection_cmd.cpp
+++ b/src/mongo/db/commands/rename_collection_cmd.cpp
@@ -67,6 +67,9 @@ public:
virtual bool slaveOk() const {
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual Status checkAuthForCommand(ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
diff --git a/src/mongo/db/commands/repair_cursor.cpp b/src/mongo/db/commands/repair_cursor.cpp
index 8792afe2092..ad8afe526bb 100644
--- a/src/mongo/db/commands/repair_cursor.cpp
+++ b/src/mongo/db/commands/repair_cursor.cpp
@@ -48,6 +48,9 @@ class RepairCursorCmd : public Command {
public:
RepairCursorCmd() : Command("repairCursor") {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool slaveOk() const {
return true;
}
diff --git a/src/mongo/db/commands/server_status.cpp b/src/mongo/db/commands/server_status.cpp
index e7f15f8e4cb..423991bdbfc 100644
--- a/src/mongo/db/commands/server_status.cpp
+++ b/src/mongo/db/commands/server_status.cpp
@@ -67,6 +67,9 @@ public:
CmdServerStatus()
: Command("serverStatus", true), _started(curTimeMillis64()), _runCalled(false) {}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool slaveOk() const {
return true;
}
diff --git a/src/mongo/db/commands/shutdown.h b/src/mongo/db/commands/shutdown.h
index 2bb71e7373d..f1f55d0668c 100644
--- a/src/mongo/db/commands/shutdown.h
+++ b/src/mongo/db/commands/shutdown.h
@@ -54,6 +54,9 @@ public:
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out);
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
protected:
static void shutdownHelper();
diff --git a/src/mongo/db/commands/snapshot_management.cpp b/src/mongo/db/commands/snapshot_management.cpp
index cb90e41d685..9eec705e4af 100644
--- a/src/mongo/db/commands/snapshot_management.cpp
+++ b/src/mongo/db/commands/snapshot_management.cpp
@@ -45,6 +45,9 @@ public:
virtual bool slaveOk() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool adminOnly() const {
return true;
}
@@ -92,6 +95,9 @@ public:
virtual bool slaveOk() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool adminOnly() const {
return true;
}
diff --git a/src/mongo/db/commands/test_commands.cpp b/src/mongo/db/commands/test_commands.cpp
index 39b6ef90636..58d554cef84 100644
--- a/src/mongo/db/commands/test_commands.cpp
+++ b/src/mongo/db/commands/test_commands.cpp
@@ -65,6 +65,9 @@ public:
virtual bool slaveOk() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
// No auth needed because it only works when enabled via command line.
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
@@ -110,6 +113,10 @@ public:
/* for diagnostic / testing purposes. Enabled via command line. */
class CmdSleep : public Command {
public:
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
virtual bool adminOnly() const {
return true;
}
@@ -204,6 +211,9 @@ public:
virtual bool slaveOk() const {
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
// No auth needed because it only works when enabled via command line.
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
@@ -271,6 +281,9 @@ public:
virtual bool slaveOk() const {
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
// No auth needed because it only works when enabled via command line.
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
diff --git a/src/mongo/db/commands/top_command.cpp b/src/mongo/db/commands/top_command.cpp
index 70407d67ea6..e4b788dc711 100644
--- a/src/mongo/db/commands/top_command.cpp
+++ b/src/mongo/db/commands/top_command.cpp
@@ -52,6 +52,9 @@ public:
virtual bool adminOnly() const {
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void help(std::stringstream& help) const {
help << "usage by collection, in micros ";
}
diff --git a/src/mongo/db/commands/touch.cpp b/src/mongo/db/commands/touch.cpp
index 530d8937588..520f74e64a1 100644
--- a/src/mongo/db/commands/touch.cpp
+++ b/src/mongo/db/commands/touch.cpp
@@ -57,6 +57,9 @@ using std::stringstream;
class TouchCmd : public Command {
public:
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual bool adminOnly() const {
return false;
}
diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp
index 5e35694173e..f058a892a9b 100644
--- a/src/mongo/db/commands/user_management_commands.cpp
+++ b/src/mongo/db/commands/user_management_commands.cpp
@@ -62,12 +62,18 @@
#include "mongo/db/operation_context.h"
#include "mongo/db/service_context.h"
#include "mongo/platform/unordered_set.h"
+#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/rpc/protocol.h"
+#include "mongo/s/write_ops/batched_command_response.h"
+#include "mongo/s/write_ops/batched_delete_request.h"
+#include "mongo/s/write_ops/batched_insert_request.h"
+#include "mongo/s/write_ops/batched_update_request.h"
#include "mongo/stdx/functional.h"
#include "mongo/stdx/mutex.h"
#include "mongo/util/log.h"
#include "mongo/util/mongoutils/str.h"
#include "mongo/util/net/ssl_manager.h"
+#include "mongo/util/scopeguard.h"
#include "mongo/util/sequence_util.h"
#include "mongo/util/time_support.h"
@@ -260,24 +266,28 @@ Status insertAuthzDocument(OperationContext* txn,
const NamespaceString& collectionName,
const BSONObj& document,
const BSONObj& writeConcern) {
+ // Save and reset the write concern so that it doesn't get changed accidentally by
+ // DBDirectClient.
+ auto oldWC = txn->getWriteConcern();
+ ON_BLOCK_EXIT([txn, oldWC] { txn->setWriteConcern(oldWC); });
+
try {
DBDirectClient client(txn);
- client.insert(collectionName.ns(), document);
- // Handle write concern
- BSONObjBuilder gleBuilder;
- gleBuilder.append("getLastError", 1);
- gleBuilder.appendElements(writeConcern);
+ BatchedInsertRequest req;
+ req.setNS(collectionName);
+ req.addToDocuments(document);
+
BSONObj res;
- client.runCommand("admin", gleBuilder.done(), res);
- string errstr = client.getLastErrorString(res);
- if (errstr.empty()) {
- return Status::OK();
- }
- if (res.hasField("code") && res["code"].Int() == ASSERT_ID_DUPKEY) {
- return Status(ErrorCodes::DuplicateKey, errstr);
+ client.runCommand(collectionName.db().toString(), req.toBSON(), res);
+
+ BatchedCommandResponse response;
+ std::string errmsg;
+ response.parseBSON(res, &errmsg);
+ if (errmsg != "") {
+ return Status(ErrorCodes::FailedToParse, errmsg);
}
- return Status(ErrorCodes::UnknownError, errstr);
+ return response.toStatus();
} catch (const DBException& e) {
return e.toStatus();
}
@@ -296,23 +306,38 @@ Status updateAuthzDocuments(OperationContext* txn,
bool upsert,
bool multi,
const BSONObj& writeConcern,
- int* nMatched) {
+ long long* nMatched) {
+ // Save and reset the write concern so that it doesn't get changed accidentally by
+ // DBDirectClient.
+ auto oldWC = txn->getWriteConcern();
+ ON_BLOCK_EXIT([txn, oldWC] { txn->setWriteConcern(oldWC); });
+
try {
DBDirectClient client(txn);
- client.update(collectionName.ns(), query, updatePattern, upsert, multi);
- // Handle write concern
- BSONObjBuilder gleBuilder;
- gleBuilder.append("getLastError", 1);
- gleBuilder.appendElements(writeConcern);
+ auto doc = stdx::make_unique<BatchedUpdateDocument>();
+ doc->setQuery(query);
+ doc->setUpdateExpr(updatePattern);
+ doc->setMulti(multi);
+ doc->setUpsert(upsert);
+
+ BatchedUpdateRequest req;
+ req.setNS(collectionName);
+ req.addToUpdates(doc.release());
+
BSONObj res;
- client.runCommand("admin", gleBuilder.done(), res);
- string errstr = client.getLastErrorString(res);
- if (errstr.empty()) {
- *nMatched = res["n"].numberInt();
- return Status::OK();
+ client.runCommand(collectionName.db().toString(), req.toBSON(), res);
+
+ BatchedCommandResponse response;
+ std::string errmsg;
+ response.parseBSON(res, &errmsg);
+ if (errmsg != "") {
+ return Status(ErrorCodes::FailedToParse, errmsg);
}
- return Status(ErrorCodes::UnknownError, errstr);
+ if (response.getOk()) {
+ *nMatched = response.getN();
+ }
+ return response.toStatus();
} catch (const DBException& e) {
return e.toStatus();
}
@@ -336,7 +361,7 @@ Status updateOneAuthzDocument(OperationContext* txn,
const BSONObj& updatePattern,
bool upsert,
const BSONObj& writeConcern) {
- int nMatched;
+ long long nMatched;
Status status = updateAuthzDocuments(
txn, collectionName, query, updatePattern, upsert, false, writeConcern, &nMatched);
if (!status.isOK()) {
@@ -359,23 +384,36 @@ Status removeAuthzDocuments(OperationContext* txn,
const NamespaceString& collectionName,
const BSONObj& query,
const BSONObj& writeConcern,
- int* numRemoved) {
+ long long* numRemoved) {
+ // Save and reset the write concern so that it doesn't get changed accidentally by
+ // DBDirectClient.
+ auto oldWC = txn->getWriteConcern();
+ ON_BLOCK_EXIT([txn, oldWC] { txn->setWriteConcern(oldWC); });
+
try {
DBDirectClient client(txn);
- client.remove(collectionName.ns(), query);
- // Handle write concern
- BSONObjBuilder gleBuilder;
- gleBuilder.append("getLastError", 1);
- gleBuilder.appendElements(writeConcern);
+ auto doc = stdx::make_unique<BatchedDeleteDocument>();
+ doc->setQuery(query);
+ doc->setLimit(0);
+
+ BatchedDeleteRequest req;
+ req.setNS(collectionName);
+ req.addToDeletes(doc.release());
+
BSONObj res;
- client.runCommand("admin", gleBuilder.done(), res);
- string errstr = client.getLastErrorString(res);
- if (errstr.empty()) {
- *numRemoved = res["n"].numberInt();
- return Status::OK();
+ client.runCommand(collectionName.db().toString(), req.toBSON(), res);
+
+ BatchedCommandResponse response;
+ std::string errmsg;
+ response.parseBSON(res, &errmsg);
+ if (errmsg != "") {
+ return Status(ErrorCodes::FailedToParse, errmsg);
}
- return Status(ErrorCodes::UnknownError, errstr);
+ if (response.getOk()) {
+ *numRemoved = response.getN();
+ }
+ return response.toStatus();
} catch (const DBException& e) {
return e.toStatus();
}
@@ -445,7 +483,7 @@ Status updateRoleDocument(OperationContext* txn,
Status removeRoleDocuments(OperationContext* txn,
const BSONObj& query,
const BSONObj& writeConcern,
- int* numRemoved) {
+ long long* numRemoved) {
Status status = removeAuthzDocuments(
txn, AuthorizationManager::rolesCollectionNamespace, query, writeConcern, numRemoved);
if (status.code() == ErrorCodes::UnknownError) {
@@ -518,7 +556,7 @@ Status updatePrivilegeDocument(OperationContext* txn,
Status removePrivilegeDocuments(OperationContext* txn,
const BSONObj& query,
const BSONObj& writeConcern,
- int* numRemoved) {
+ long long* numRemoved) {
Status status = removeAuthzDocuments(
txn, AuthorizationManager::usersCollectionNamespace, query, writeConcern, numRemoved);
if (status.code() == ErrorCodes::UnknownError) {
@@ -608,6 +646,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Adds a user to the system" << endl;
@@ -750,6 +791,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Used to update a user, for example to change its password" << endl;
@@ -864,6 +908,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Drops a single user." << endl;
@@ -899,7 +946,7 @@ public:
audit::logDropUser(ClientBasic::getCurrent(), userName);
- int nMatched;
+ long long nMatched;
status = removePrivilegeDocuments(txn,
BSON(AuthorizationManager::USER_NAME_FIELD_NAME
<< userName.getUser()
@@ -933,6 +980,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Drops all users for a single database." << endl;
@@ -967,7 +1017,7 @@ public:
audit::logDropAllUsersFromDatabase(ClientBasic::getCurrent(), dbname);
- int numRemoved;
+ long long numRemoved;
status = removePrivilegeDocuments(txn,
BSON(AuthorizationManager::USER_DB_FIELD_NAME << dbname),
writeConcern,
@@ -992,6 +1042,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Grants roles to a user." << endl;
@@ -1064,6 +1117,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Revokes roles from a user." << endl;
@@ -1138,6 +1194,9 @@ public:
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
CmdUsersInfo() : Command("usersInfo") {}
@@ -1289,6 +1348,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Adds a role to the system" << endl;
@@ -1400,6 +1462,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Used to update a role" << endl;
@@ -1496,6 +1561,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Grants privileges to a role" << endl;
@@ -1601,6 +1669,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Revokes privileges from a role" << endl;
@@ -1714,6 +1785,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Grants roles to another role." << endl;
@@ -1806,6 +1880,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Revokes roles from another role." << endl;
@@ -1892,6 +1969,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Drops a single role. Before deleting the role completely it must remove it "
@@ -1943,7 +2023,7 @@ public:
}
// Remove this role from all users
- int nMatched;
+ long long nMatched;
status = updateAuthzDocuments(
txn,
AuthorizationManager::usersCollectionNamespace,
@@ -2043,6 +2123,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Drops all roles from the given database. Before deleting the roles completely "
@@ -2080,7 +2163,7 @@ public:
}
// Remove these roles from all users
- int nMatched;
+ long long nMatched;
status = updateAuthzDocuments(
txn,
AuthorizationManager::usersCollectionNamespace,
@@ -2163,6 +2246,9 @@ public:
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
CmdRolesInfo() : Command("rolesInfo") {}
@@ -2235,6 +2321,9 @@ public:
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
CmdInvalidateUserCache() : Command("invalidateUserCache") {}
@@ -2271,6 +2360,9 @@ public:
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
CmdGetCacheGeneration() : Command("_getUserCacheGeneration") {}
@@ -2315,6 +2407,9 @@ public:
return false;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual bool adminOnly() const {
return true;
@@ -2559,7 +2654,7 @@ public:
}
if (drop) {
- int numRemoved;
+ long long numRemoved;
for (unordered_set<UserName>::iterator it = usersToDrop.begin();
it != usersToDrop.end();
++it) {
@@ -2640,7 +2735,7 @@ public:
}
if (drop) {
- int numRemoved;
+ long long numRemoved;
for (unordered_set<RoleName>::iterator it = rolesToDrop.begin();
it != rolesToDrop.end();
++it) {
@@ -2897,6 +2992,9 @@ public:
return true;
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return true;
+ }
virtual void help(stringstream& ss) const {
ss << "Upgrades the auth data storage schema";
diff --git a/src/mongo/db/commands/validate.cpp b/src/mongo/db/commands/validate.cpp
index e41374cba6a..1569bf5cdcc 100644
--- a/src/mongo/db/commands/validate.cpp
+++ b/src/mongo/db/commands/validate.cpp
@@ -62,6 +62,9 @@ public:
"Add full:true option to do a more thorough check";
}
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp
index 51b446532a7..bd71a02d6aa 100644
--- a/src/mongo/db/commands/write_commands/batch_executor.cpp
+++ b/src/mongo/db/commands/write_commands/batch_executor.cpp
@@ -121,19 +121,6 @@ private:
std::unique_ptr<WriteErrorDetail> _error;
};
-unique_ptr<WCErrorDetail> toWriteConcernError(const Status& wcStatus,
- const WriteConcernResult& wcResult) {
- auto wcError = stdx::make_unique<WCErrorDetail>();
-
- wcError->setErrCode(wcStatus.code());
- wcError->setErrMessage(wcStatus.reason());
- if (wcResult.wTimedOut) {
- wcError->setErrInfo(BSON("wtimeout" << true));
- }
-
- return wcError;
-}
-
WriteErrorDetail* toWriteError(const Status& status) {
WriteErrorDetail* error = new WriteErrorDetail;
@@ -278,27 +265,6 @@ void WriteBatchExecutor::executeBatch(const BatchedCommandRequest& request,
bulkExecute(request, &upserted, &writeErrors);
//
- // Always try to enforce the write concern, even if everything failed.
- // If something failed, we have already set the lastOp to be the last op to have succeeded
- // and written to the oplog.
-
- {
- stdx::lock_guard<Client> lk(*_txn->getClient());
- CurOp::get(_txn)->setMessage_inlock("waiting for write concern");
- }
-
- unique_ptr<WCErrorDetail> wcError;
- WriteConcernResult res;
- Status status =
- waitForWriteConcern(_txn,
- repl::ReplClientInfo::forClient(_txn->getClient()).getLastOp(),
- _txn->getWriteConcern(),
- &res);
- if (!status.isOK()) {
- wcError = toWriteConcernError(status, res);
- }
-
- //
// Refresh metadata if needed
//
@@ -328,10 +294,6 @@ void WriteBatchExecutor::executeBatch(const BatchedCommandRequest& request,
response->setErrDetails(writeErrors);
}
- if (wcError.get()) {
- response->setWriteConcernError(wcError.release());
- }
-
repl::ReplicationCoordinator* replCoord = repl::getGlobalReplicationCoordinator();
const repl::ReplicationCoordinator::Mode replMode = replCoord->getReplicationMode();
if (replMode != repl::ReplicationCoordinator::modeNone) {
@@ -743,6 +705,11 @@ void WriteBatchExecutor::execInserts(const BatchedCommandRequest& request,
&repl::ReplClientInfo::setLastOpToSystemLastOpTime,
_txn);
+ // If this is the local database, don't set last op.
+ if (request.getNS().isLocal()) {
+ lastOpSetterGuard.Dismiss();
+ }
+
int64_t chunkCount = 0;
int64_t chunkBytes = 0;
const int64_t chunkMaxCount = internalQueryExecYieldIterations / 2;
@@ -1047,6 +1014,11 @@ static void multiUpdate(OperationContext* txn,
&repl::ReplClientInfo::setLastOpToSystemLastOpTime,
txn);
+ // If this is the local database, don't set last op.
+ if (nsString.isLocal()) {
+ lastOpSetterGuard.Dismiss();
+ }
+
int attempt = 0;
bool createCollection = false;
for (int fakeLoop = 0; fakeLoop < 1; fakeLoop++) {
@@ -1226,6 +1198,11 @@ static void multiRemove(OperationContext* txn,
&repl::ReplClientInfo::setLastOpToSystemLastOpTime,
txn);
+ // If this is the local database, don't set last op.
+ if (nss.isLocal()) {
+ lastOpSetterGuard.Dismiss();
+ }
+
int attempt = 1;
while (1) {
try {
diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp
index cd3c13674a1..7e56675ef3c 100644
--- a/src/mongo/db/commands/write_commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands.cpp
@@ -92,6 +92,10 @@ bool WriteCmd::slaveOk() const {
}
+bool WriteCmd::supportsWriteConcern(const BSONObj& cmd) const {
+ return true;
+}
+
Status WriteCmd::checkAuthForCommand(ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
@@ -128,13 +132,6 @@ bool WriteCmd::run(OperationContext* txn,
return appendCommandStatus(result, Status(ErrorCodes::FailedToParse, errMsg));
}
- StatusWith<WriteConcernOptions> wcStatus = extractWriteConcern(txn, cmdObj, dbName);
-
- if (!wcStatus.isOK()) {
- return appendCommandStatus(result, wcStatus.getStatus());
- }
- txn->setWriteConcern(wcStatus.getValue());
-
WriteBatchExecutor writeBatchExecutor(
txn, &globalOpCounters, &LastError::get(txn->getClient()));
diff --git a/src/mongo/db/commands/write_commands/write_commands.h b/src/mongo/db/commands/write_commands/write_commands.h
index e8dfaaa9608..e01ade2b2ff 100644
--- a/src/mongo/db/commands/write_commands/write_commands.h
+++ b/src/mongo/db/commands/write_commands/write_commands.h
@@ -63,6 +63,8 @@ protected:
private:
virtual bool slaveOk() const;
+ virtual bool supportsWriteConcern(const BSONObj& cmd) const override;
+
virtual Status checkAuthForCommand(ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj);