diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/api_parameters.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/api_parameters.h | 13 | ||||
-rw-r--r-- | src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/commands/kill_sessions_command.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/kill_sessions.cpp | 31 | ||||
-rw-r--r-- | src/mongo/db/kill_sessions.h | 33 | ||||
-rw-r--r-- | src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/session_killer.cpp | 44 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_kill_op.cpp | 5 | ||||
-rw-r--r-- | src/mongo/s/commands/kill_sessions_remote.cpp | 8 |
11 files changed, 118 insertions, 51 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index f7ef628e7ef..ae87ab8a48e 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); } |