summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorA. Jesse Jiryu Davis <jesse@mongodb.com>2020-10-05 15:45:57 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-10-05 22:06:43 +0000
commit99e27ba5943fd561242ae0f90e263e9a4098036e (patch)
treea6cf16b765a877a474faaa8ba30c0f76ac312524 /src
parent5a155f06bffb6141a40497fdef1dd61a2aaf2962 (diff)
downloadmongo-99e27ba5943fd561242ae0f90e263e9a4098036e.tar.gz
SERVER-50375 Ensure mongos forwards API parameters to shards, try 3
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/api_parameters.cpp14
-rw-r--r--src/mongo/db/api_parameters.h13
-rw-r--r--src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp11
-rw-r--r--src/mongo/db/commands/kill_sessions_command.cpp6
-rw-r--r--src/mongo/db/kill_sessions.cpp31
-rw-r--r--src/mongo/db/kill_sessions.h33
-rw-r--r--src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp3
-rw-r--r--src/mongo/db/session_killer.cpp44
-rw-r--r--src/mongo/s/commands/cluster_kill_op.cpp5
-rw-r--r--src/mongo/s/commands/kill_sessions_remote.cpp8
11 files changed, 118 insertions, 51 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 4d008acaf13..7e02e458cf8 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -1527,6 +1527,7 @@ env.Library(
'$BUILD_DIR/mongo/db/auth/auth',
'$BUILD_DIR/mongo/db/auth/authprivilege',
'$BUILD_DIR/mongo/idl/idl_parser',
+ 'api_parameters',
],
)
diff --git a/src/mongo/db/api_parameters.cpp b/src/mongo/db/api_parameters.cpp
index 05ffe9c49cb..51e424637db 100644
--- a/src/mongo/db/api_parameters.cpp
+++ b/src/mongo/db/api_parameters.cpp
@@ -76,4 +76,18 @@ void APIParameters::appendInfo(BSONObjBuilder* builder) const {
}
}
+std::size_t APIParameters::Hash::operator()(const APIParameters& params) const {
+ size_t seed = 0;
+ if (params.getAPIVersion()) {
+ boost::hash_combine(seed, *params.getAPIVersion());
+ }
+ if (params.getAPIStrict()) {
+ boost::hash_combine(seed, *params.getAPIStrict());
+ }
+ if (params.getAPIDeprecationErrors()) {
+ boost::hash_combine(seed, *params.getAPIDeprecationErrors());
+ }
+ return seed;
+}
+
} // namespace mongo
diff --git a/src/mongo/db/api_parameters.h b/src/mongo/db/api_parameters.h
index efbebfabfcc..34c129bca15 100644
--- a/src/mongo/db/api_parameters.h
+++ b/src/mongo/db/api_parameters.h
@@ -49,6 +49,11 @@ public:
static APIParameters fromClient(const APIParametersFromClient& apiParamsFromClient);
static APIParameters fromBSON(const BSONObj& cmdObj);
+ // For use with unordered_map.
+ struct Hash {
+ std::size_t operator()(const APIParameters& params) const;
+ };
+
void appendInfo(BSONObjBuilder* builder) const;
const boost::optional<std::string>& getAPIVersion() const {
@@ -85,6 +90,14 @@ private:
boost::optional<bool> _apiDeprecationErrors;
};
+inline bool operator==(const APIParameters& lhs, const APIParameters& rhs) {
+ return lhs.getAPIVersion() == rhs.getAPIVersion() && lhs.getAPIStrict() == rhs.getAPIStrict() &&
+ lhs.getAPIDeprecationErrors() == rhs.getAPIDeprecationErrors();
+}
+
+inline bool operator!=(const APIParameters& lhs, const APIParameters& rhs) {
+ return !(lhs == rhs);
+}
/**
* Temporarily remove the user's API parameters from an OperationContext.
diff --git a/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp b/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp
index c7687db6782..220c585ae78 100644
--- a/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp
+++ b/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp
@@ -96,7 +96,10 @@ public:
// The empty command kills all
if (ksc.getKillAllSessionsByPattern().empty()) {
- ksc.setKillAllSessionsByPattern({makeKillAllSessionsByPattern(opCtx)});
+ auto item = makeKillAllSessionsByPattern(opCtx);
+ std::vector<mongo::KillAllSessionsByPattern> patterns;
+ patterns.push_back({std::move(item.pattern)});
+ ksc.setKillAllSessionsByPattern(std::move(patterns));
} else {
// If a pattern is passed, you may only pass impersonate data if you have the
// impersonate privilege.
@@ -114,8 +117,10 @@ public:
}
}
- KillAllSessionsByPatternSet patterns{ksc.getKillAllSessionsByPattern().begin(),
- ksc.getKillAllSessionsByPattern().end()};
+ KillAllSessionsByPatternSet patterns;
+ for (auto& pattern : ksc.getKillAllSessionsByPattern()) {
+ patterns.insert({std::move(pattern), APIParameters::get(opCtx)});
+ }
uassertStatusOK(killSessionsCmdHelper(opCtx, result, patterns));
return true;
diff --git a/src/mongo/db/commands/kill_sessions_command.cpp b/src/mongo/db/commands/kill_sessions_command.cpp
index 41e3596938f..1bb9c2e3a08 100644
--- a/src/mongo/db/commands/kill_sessions_command.cpp
+++ b/src/mongo/db/commands/kill_sessions_command.cpp
@@ -63,9 +63,9 @@ KillAllSessionsByPatternSet patternsForLoggedInUser(OperationContext* opCtx) {
User* user = authzSession->lookupUser(*iter);
invariant(user);
- auto pattern = makeKillAllSessionsByPattern(opCtx);
- pattern.setUid(user->getDigest());
- patterns.emplace(std::move(pattern));
+ auto item = makeKillAllSessionsByPattern(opCtx);
+ item.pattern.setUid(user->getDigest());
+ patterns.emplace(std::move(item));
}
} else {
patterns.emplace(makeKillAllSessionsByPattern(opCtx));
diff --git a/src/mongo/db/kill_sessions.cpp b/src/mongo/db/kill_sessions.cpp
index 41033d23bbb..b167e14c156 100644
--- a/src/mongo/db/kill_sessions.cpp
+++ b/src/mongo/db/kill_sessions.cpp
@@ -31,6 +31,7 @@
#include "mongo/db/kill_sessions.h"
+#include "mongo/db/api_parameters.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/client.h"
#include "mongo/db/operation_context.h"
@@ -96,27 +97,25 @@ std::tuple<std::vector<UserName>, std::vector<RoleName>> getKillAllSessionsByPat
return out;
}
-KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx) {
+KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx) {
KillAllSessionsByPattern kasbp;
kasbp.setUsers(getKillAllSessionsImpersonateUsers(opCtx));
kasbp.setRoles(getKillAllSessionsImpersonateRoles(opCtx));
-
- return kasbp;
+ return {kasbp, APIParameters::get(opCtx)};
}
-KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx,
- const KillAllSessionsUser& kasu) {
- KillAllSessionsByPattern kasbp = makeKillAllSessionsByPattern(opCtx);
+KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx,
+ const KillAllSessionsUser& kasu) {
+ KillAllSessionsByPatternItem item = makeKillAllSessionsByPattern(opCtx);
auto authMgr = AuthorizationManager::get(opCtx->getServiceContext());
UserName un(kasu.getUser(), kasu.getDb());
auto user = uassertStatusOK(authMgr->acquireUser(opCtx, un));
- kasbp.setUid(user->getDigest());
-
- return kasbp;
+ item.pattern.setUid(user->getDigest());
+ return item;
}
KillAllSessionsByPatternSet makeSessionFilterForAuthenticatedUsers(OperationContext* opCtx) {
@@ -127,18 +126,18 @@ KillAllSessionsByPatternSet makeSessionFilterForAuthenticatedUsers(OperationCont
if (auto user = authSession->lookupUser(*it)) {
KillAllSessionsByPattern pattern;
pattern.setUid(user->getDigest());
- patterns.emplace(std::move(pattern));
+ KillAllSessionsByPatternItem item{std::move(pattern), APIParameters::get(opCtx)};
+ patterns.emplace(std::move(item));
}
}
return patterns;
}
-KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx,
- const LogicalSessionId& lsid) {
- KillAllSessionsByPattern kasbp = makeKillAllSessionsByPattern(opCtx);
- kasbp.setLsid(lsid);
-
- return kasbp;
+KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx,
+ const LogicalSessionId& lsid) {
+ auto item = makeKillAllSessionsByPattern(opCtx);
+ item.pattern.setLsid(lsid);
+ return item;
}
} // namespace mongo
diff --git a/src/mongo/db/kill_sessions.h b/src/mongo/db/kill_sessions.h
index 29909fd49df..31ceeed9375 100644
--- a/src/mongo/db/kill_sessions.h
+++ b/src/mongo/db/kill_sessions.h
@@ -31,6 +31,7 @@
#include <tuple>
+#include "mongo/db/api_parameters.h"
#include "mongo/db/auth/role_name.h"
#include "mongo/db/auth/user_name.h"
#include "mongo/db/kill_sessions_gen.h"
@@ -41,8 +42,14 @@ namespace mongo {
class OperationContext;
class ServiceContext;
-struct KillAllSessionsByPatternHash {
- std::size_t operator()(const KillAllSessionsByPattern& pattern) const {
+struct KillAllSessionsByPatternItem {
+ KillAllSessionsByPattern pattern;
+ APIParameters apiParameters;
+};
+
+struct KillAllSessionsByPatternItemHash {
+ std::size_t operator()(const KillAllSessionsByPatternItem& item) const {
+ auto& pattern = item.pattern;
if (pattern.getLsid()) {
return lsidHasher(*pattern.getLsid());
} else if (pattern.getUid()) {
@@ -60,20 +67,22 @@ struct KillAllSessionsByPatternHash {
/**
* Patterns are specifically equal if they differ only by impersonate data.
*/
-inline bool operator==(const KillAllSessionsByPattern& lhs, const KillAllSessionsByPattern& rhs) {
- auto makeEqualityLens = [](const auto& pattern) {
- return std::tie(pattern.getLsid(), pattern.getUid());
+inline bool operator==(const KillAllSessionsByPatternItem& lhs,
+ const KillAllSessionsByPatternItem& rhs) {
+ auto makeEqualityLens = [](const auto& item) {
+ return std::tie(item.pattern.getLsid(), item.pattern.getUid(), item.apiParameters);
};
return makeEqualityLens(lhs) == makeEqualityLens(rhs);
}
-inline bool operator!=(const KillAllSessionsByPattern& lhs, const KillAllSessionsByPattern& rhs) {
+inline bool operator!=(const KillAllSessionsByPatternItem& lhs,
+ const KillAllSessionsByPatternItem& rhs) {
return !(lhs == rhs);
}
using KillAllSessionsByPatternSet =
- stdx::unordered_set<KillAllSessionsByPattern, KillAllSessionsByPatternHash>;
+ stdx::unordered_set<KillAllSessionsByPatternItem, KillAllSessionsByPatternItemHash>;
std::tuple<std::vector<UserName>, std::vector<RoleName>> getKillAllSessionsByPatternImpersonateData(
const KillAllSessionsByPattern& pattern);
@@ -86,13 +95,13 @@ std::tuple<std::vector<UserName>, std::vector<RoleName>> getKillAllSessionsByPat
/**
* Constructs a kill sessions pattern which kills all sessions
*/
-KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx);
+KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx);
/**
* Constructs a kill sessions pattern for a particular user
*/
-KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx,
- const KillAllSessionsUser& user);
+KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx,
+ const KillAllSessionsUser& user);
/**
* Constructs a KillAllSessionsByPatternSet, each element of which matches the UID of a user that is
@@ -103,7 +112,7 @@ KillAllSessionsByPatternSet makeSessionFilterForAuthenticatedUsers(OperationCont
/**
* Constructs a kill sessions pattern for a particular logical session
*/
-KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx,
- const LogicalSessionId& lsid);
+KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx,
+ const LogicalSessionId& lsid);
} // namespace mongo
diff --git a/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp b/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp
index d10ba0288d3..b82c0b908e5 100644
--- a/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp
+++ b/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp
@@ -43,6 +43,7 @@
#include "mongo/client/read_preference.h"
#include "mongo/client/remote_command_targeter.h"
#include "mongo/client/replica_set_monitor.h"
+#include "mongo/db/api_parameters.h"
#include "mongo/db/audit.h"
#include "mongo/db/catalog_raii.h"
#include "mongo/db/client.h"
@@ -145,7 +146,7 @@ StatusWith<Shard::CommandResponse> ShardingCatalogManager::_runCommandForAddShar
auto host = std::move(swHost.getValue());
executor::RemoteCommandRequest request(
- host, dbName.toString(), cmdObj, rpc::makeEmptyMetadata(), nullptr, Seconds(30));
+ host, dbName.toString(), cmdObj, rpc::makeEmptyMetadata(), opCtx, Seconds(30));
executor::RemoteCommandResponse response =
Status(ErrorCodes::InternalError, "Internal error running command");
diff --git a/src/mongo/db/session_killer.cpp b/src/mongo/db/session_killer.cpp
index 20ba36ac3dd..8ac4764398a 100644
--- a/src/mongo/db/session_killer.cpp
+++ b/src/mongo/db/session_killer.cpp
@@ -85,18 +85,19 @@ SessionKiller::ReapResult::ReapResult() : result(std::make_shared<boost::optiona
SessionKiller::Matcher::Matcher(KillAllSessionsByPatternSet&& patterns)
: _patterns(std::move(patterns)) {
- for (const auto& pattern : _patterns) {
+ for (const auto& item : _patterns) {
+ auto& pattern = item.pattern;
if (pattern.getUid()) {
_uids.emplace(pattern.getUid().get(), &pattern);
} else if (pattern.getLsid()) {
_lsids.emplace(pattern.getLsid().get(), &pattern);
} else {
// If we're killing everything, it's the only pattern we care about.
- decltype(_patterns) onlyKillAll{{pattern}};
+ decltype(_patterns) onlyKillAll{{item}};
using std::swap;
swap(_patterns, onlyKillAll);
- _killAll = &(*_patterns.begin());
+ _killAll = &(_patterns.begin()->pattern);
break;
}
}
@@ -177,19 +178,38 @@ void SessionKiller::_periodicKill(OperationContext* opCtx, stdx::unique_lock<Lat
// Drop the lock and run the killer.
lk.unlock();
- Matcher matcher(std::move(nextToReap));
- boost::optional<Result> results;
- try {
- results.emplace(_killFunc(opCtx, matcher, &_urbg));
- } catch (...) {
- results.emplace(exceptionToStatus());
+ // Group patterns with equal API parameters into sets.
+ stdx::unordered_map<APIParameters, KillAllSessionsByPatternSet, APIParameters::Hash> sets;
+ for (auto& item : nextToReap) {
+ sets[item.apiParameters].insert(std::move(item));
}
- lk.lock();
- invariant(results);
+ // Use the API parameters included in each KillAllSessionsByPattern struct.
+ IgnoreAPIParametersBlock ignoreApiParametersBlock(opCtx);
+ Result finalResults{std::vector<HostAndPort>{}};
+ for (auto& [apiParameters, items] : sets) {
+ APIParameters::get(opCtx) = apiParameters;
+ Matcher matcher(std::move(items));
+ boost::optional<Result> results;
+ try {
+ results.emplace(_killFunc(opCtx, matcher, &_urbg));
+ } catch (...) {
+ results.emplace(exceptionToStatus());
+ }
+ invariant(results);
+ if (!results->isOK()) {
+ finalResults = *results;
+ break;
+ }
+
+ finalResults.getValue().insert(finalResults.getValue().end(),
+ std::make_move_iterator(results->getValue().begin()),
+ std::make_move_iterator(results->getValue().end()));
+ }
// Expose the results and notify callers
- *(reapResults.result) = std::move(results);
+ lk.lock();
+ *(reapResults.result) = std::move(finalResults);
_callerCV.notify_all();
};
diff --git a/src/mongo/s/commands/cluster_kill_op.cpp b/src/mongo/s/commands/cluster_kill_op.cpp
index 1d4927b0f79..2ce1ecf79ef 100644
--- a/src/mongo/s/commands/cluster_kill_op.cpp
+++ b/src/mongo/s/commands/cluster_kill_op.cpp
@@ -38,6 +38,7 @@
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/bson/util/bson_extract.h"
#include "mongo/client/connpool.h"
+#include "mongo/db/api_parameters.h"
#include "mongo/db/audit.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/commands.h"
@@ -111,8 +112,10 @@ private:
result.append("shardid", opId);
ScopedDbConnection conn(shard->getConnString());
+ BSONObjBuilder bob(BSON("killOp" << 1 << "op" << opId));
+ APIParameters::get(opCtx).appendInfo(&bob);
// intentionally ignore return value - that is how legacy killOp worked.
- conn->runCommand(OpMsgRequest::fromDBAndBody("admin", BSON("killOp" << 1 << "op" << opId)));
+ conn->runCommand(OpMsgRequest::fromDBAndBody("admin", bob.obj()));
conn.done();
// The original behavior of killOp on mongos is to always return success, regardless of
diff --git a/src/mongo/s/commands/kill_sessions_remote.cpp b/src/mongo/s/commands/kill_sessions_remote.cpp
index d9b5ce26ccf..0bda8eacf61 100644
--- a/src/mongo/s/commands/kill_sessions_remote.cpp
+++ b/src/mongo/s/commands/kill_sessions_remote.cpp
@@ -119,9 +119,11 @@ SessionKiller::Result killSessionsRemote(OperationContext* opCtx,
// Generate the kill command.
KillAllSessionsByPatternCmd cmd;
- cmd.setKillAllSessionsByPattern(std::vector<KillAllSessionsByPattern>{
- matcher.getPatterns().begin(), matcher.getPatterns().end()});
-
+ std::vector<KillAllSessionsByPattern> patterns;
+ for (auto& item : matcher.getPatterns()) {
+ patterns.push_back(std::move(item.pattern));
+ }
+ cmd.setKillAllSessionsByPattern(std::move(patterns));
return parallelExec(opCtx, cmd.toBSON(), urbg);
}