diff options
author | Misha Tyulenev <misha@mongodb.com> | 2017-10-26 18:34:38 -0400 |
---|---|---|
committer | Misha Tyulenev <misha@mongodb.com> | 2017-10-26 18:37:04 -0400 |
commit | 54f044558c0845adcc6b51c2351e8382a3e9bbd7 (patch) | |
tree | 298fe9462d1e77ae5eec6d5672bb047fb5441577 /src/mongo/db | |
parent | 260fd0c76599520d9d733874753a94a2db763538 (diff) | |
download | mongo-54f044558c0845adcc6b51c2351e8382a3e9bbd7.tar.gz |
SERVER-31613 disallow afterClusterTime on some commands
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/commands.h | 11 | ||||
-rw-r--r-- | src/mongo/db/commands/current_op_common.h | 4 | ||||
-rw-r--r-- | src/mongo/db/commands/generic.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/commands/getmore_cmd.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/commands/run_aggregate.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/commands/server_status.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/read_concern.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/read_concern.h | 7 | ||||
-rw-r--r-- | src/mongo/db/service_entry_point_mongod.cpp | 3 |
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 = |