summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMisha Tyulenev <misha@mongodb.com>2017-10-26 18:34:38 -0400
committerMisha Tyulenev <misha@mongodb.com>2017-10-26 18:37:04 -0400
commit54f044558c0845adcc6b51c2351e8382a3e9bbd7 (patch)
tree298fe9462d1e77ae5eec6d5672bb047fb5441577 /src
parent260fd0c76599520d9d733874753a94a2db763538 (diff)
downloadmongo-54f044558c0845adcc6b51c2351e8382a3e9bbd7.tar.gz
SERVER-31613 disallow afterClusterTime on some commands
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/commands.h11
-rw-r--r--src/mongo/db/commands/current_op_common.h4
-rw-r--r--src/mongo/db/commands/generic.cpp3
-rw-r--r--src/mongo/db/commands/getmore_cmd.cpp4
-rw-r--r--src/mongo/db/commands/run_aggregate.cpp2
-rw-r--r--src/mongo/db/commands/server_status.cpp4
-rw-r--r--src/mongo/db/read_concern.cpp8
-rw-r--r--src/mongo/db/read_concern.h7
-rw-r--r--src/mongo/db/service_entry_point_mongod.cpp3
9 files changed, 40 insertions, 6 deletions
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index 5a2f31c460a..6d0a9d65a1e 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -208,6 +208,13 @@ public:
const BSONObj& cmdObj) const = 0;
/**
+ * Returns true if command allows afterClusterTime in its readConcern. The command may not allow
+ * it if it is specifically intended not to take any LockManager locks. Waiting for
+ * afterClusterTime takes the MODE_IS lock.
+ */
+ virtual bool allowsAfterClusterTime(const BSONObj& cmdObj) const = 0;
+
+ /**
* Returns LogicalOp for this command.
*/
virtual LogicalOp getLogicalOp() const = 0;
@@ -321,6 +328,10 @@ public:
return false;
}
+ bool allowsAfterClusterTime(const BSONObj& cmdObj) const override {
+ return true;
+ }
+
LogicalOp getLogicalOp() const override {
return LogicalOp::opCommand;
}
diff --git a/src/mongo/db/commands/current_op_common.h b/src/mongo/db/commands/current_op_common.h
index 1a3ae46a1ec..517d494d851 100644
--- a/src/mongo/db/commands/current_op_common.h
+++ b/src/mongo/db/commands/current_op_common.h
@@ -47,6 +47,10 @@ public:
return false;
}
+ bool allowsAfterClusterTime(const BSONObj& cmdObj) const final {
+ return false;
+ }
+
bool slaveOk() const final {
return true;
}
diff --git a/src/mongo/db/commands/generic.cpp b/src/mongo/db/commands/generic.cpp
index 9b0492e19e2..1cf3d51814a 100644
--- a/src/mongo/db/commands/generic.cpp
+++ b/src/mongo/db/commands/generic.cpp
@@ -114,6 +114,9 @@ public:
virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
return false;
}
+ virtual bool allowsAfterClusterTime(const BSONObj& cmdObj) 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/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp
index 3a347cb47ef..0cc3619a202 100644
--- a/src/mongo/db/commands/getmore_cmd.cpp
+++ b/src/mongo/db/commands/getmore_cmd.cpp
@@ -86,6 +86,10 @@ public:
return false;
}
+ virtual bool allowsAfterClusterTime(const BSONObj& cmdObj) const override {
+ return false;
+ }
+
bool slaveOk() const override {
return true;
}
diff --git a/src/mongo/db/commands/run_aggregate.cpp b/src/mongo/db/commands/run_aggregate.cpp
index 5b9280a772c..225cf6edc9c 100644
--- a/src/mongo/db/commands/run_aggregate.cpp
+++ b/src/mongo/db/commands/run_aggregate.cpp
@@ -295,7 +295,7 @@ Status waitForMajorityReadConcern(OperationContext* opCtx) {
if (!originalRC.hasLevel()) {
// If the read concern level is not specified, upgrade it to "majority".
const repl::ReadConcernArgs readConcern(repl::ReadConcernLevel::kMajorityReadConcern);
- auto rcStatus = waitForReadConcern(opCtx, readConcern);
+ auto rcStatus = waitForReadConcern(opCtx, readConcern, true);
if (!rcStatus.isOK()) {
return rcStatus;
}
diff --git a/src/mongo/db/commands/server_status.cpp b/src/mongo/db/commands/server_status.cpp
index 546944e5dc7..b3946ccbd12 100644
--- a/src/mongo/db/commands/server_status.cpp
+++ b/src/mongo/db/commands/server_status.cpp
@@ -75,7 +75,9 @@ public:
virtual bool slaveOk() const {
return true;
}
-
+ virtual bool allowsAfterClusterTime(const BSONObj& cmdObj) const override {
+ return false;
+ }
virtual void help(stringstream& help) const {
help << "returns lots of administrative server statistics";
}
diff --git a/src/mongo/db/read_concern.cpp b/src/mongo/db/read_concern.cpp
index f5f36e46ea3..38cb66eb22f 100644
--- a/src/mongo/db/read_concern.cpp
+++ b/src/mongo/db/read_concern.cpp
@@ -181,7 +181,9 @@ Status makeNoopWriteIfNeeded(OperationContext* opCtx, LogicalTime clusterTime) {
}
} // namespace
-Status waitForReadConcern(OperationContext* opCtx, const repl::ReadConcernArgs& readConcernArgs) {
+Status waitForReadConcern(OperationContext* opCtx,
+ const repl::ReadConcernArgs& readConcernArgs,
+ bool allowAfterClusterTime) {
repl::ReplicationCoordinator* const replCoord = repl::ReplicationCoordinator::get(opCtx);
invariant(replCoord);
@@ -213,6 +215,10 @@ Status waitForReadConcern(OperationContext* opCtx, const repl::ReadConcernArgs&
auto afterClusterTime = readConcernArgs.getArgsClusterTime();
if (afterClusterTime) {
+ if (!allowAfterClusterTime) {
+ return {ErrorCodes::InvalidOptions, "afterClusterTime is not allowed for this command"};
+ }
+
if ((serverGlobalParams.featureCompatibility.getVersion() !=
ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo36) &&
ShardingState::get(opCtx)->enabled()) {
diff --git a/src/mongo/db/read_concern.h b/src/mongo/db/read_concern.h
index 8c01e902f01..f50178c6956 100644
--- a/src/mongo/db/read_concern.h
+++ b/src/mongo/db/read_concern.h
@@ -43,9 +43,12 @@ class ReadConcernArgs;
/**
* Given the specified read concern arguments, performs checks that the read concern can actually be
* satisfied given the current state of the server and if so calls into the replication subsystem to
- * perform the wait.
+ * perform the wait. If allowAfterClusterTime is false returns an error if afterClusterTime is
+ * set on the readConcernArgs.
*/
-Status waitForReadConcern(OperationContext* opCtx, const repl::ReadConcernArgs& readConcernArgs);
+Status waitForReadConcern(OperationContext* opCtx,
+ const repl::ReadConcernArgs& readConcernArgs,
+ bool allowAfterClusterTime);
/*
* Given a linearizable read command, confirm that
diff --git a/src/mongo/db/service_entry_point_mongod.cpp b/src/mongo/db/service_entry_point_mongod.cpp
index 29cb58eb0da..3814ce52919 100644
--- a/src/mongo/db/service_entry_point_mongod.cpp
+++ b/src/mongo/db/service_entry_point_mongod.cpp
@@ -445,7 +445,8 @@ bool runCommandImpl(OperationContext* opCtx,
BSONObjBuilder inPlaceReplyBob = replyBuilder->getInPlaceReplyBuilder(bytesToReserve);
- Status rcStatus = waitForReadConcern(opCtx, repl::ReadConcernArgs::get(opCtx));
+ Status rcStatus = waitForReadConcern(
+ opCtx, repl::ReadConcernArgs::get(opCtx), command->allowsAfterClusterTime(cmd));
if (!rcStatus.isOK()) {
if (rcStatus == ErrorCodes::ExceededTimeLimit) {
const int debugLevel =