/**
* Copyright (C) 2017 MongoDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
#pragma once
#include
#include
#include
#include
#include "mongo/base/status_with.h"
#include "mongo/db/kill_sessions.h"
#include "mongo/stdx/condition_variable.h"
#include "mongo/stdx/functional.h"
#include "mongo/stdx/mutex.h"
#include "mongo/stdx/thread.h"
#include "mongo/stdx/unordered_set.h"
#include "mongo/util/net/hostandport.h"
namespace mongo {
/**
* The SessionKiller enforces a single thread for session killing for any given ServiceContext.
*
* The killer owns a background thread which actually does the work, and callers batch their kills
* together each round, before the killer starts its dispatching, after which they batch up for the
* next round.
*
* The KillFunc's kill function is passed in to its constructor, and parameterizes its behavior
* depending on context (mongod/mongos).
*/
class SessionKiller {
public:
/**
* The Result of a call is either:
*
* Status::OK(), empty vector - we killed everything
* Status::OK(), filled vector - we killed something. HostAndPort is filled with nodes we
* failed to kill on.
*
* !Status::OK() - The kill function itself failed. I.e. we may have killed nothing.
*
* This contract has a helper in kill_sessions_common.h which adapts results for command
* implementations. (killSessionsCmdHelper)
*/
using Result = StatusWith>;
using UniformRandomBitGenerator = std::minstd_rand;
class Matcher {
public:
Matcher(KillAllSessionsByPatternSet&& patterns);
const KillAllSessionsByPatternSet& getPatterns() const;
const KillAllSessionsByPattern* match(const LogicalSessionId& lsid) const;
private:
KillAllSessionsByPatternSet _patterns;
LogicalSessionIdMap _lsids;
stdx::unordered_map _uids;
const KillAllSessionsByPattern* _killAll = nullptr;
};
/**
* A process specific kill function (we have a different impl in mongos versus mongod).
*/
using KillFunc =
stdx::function;
/**
* The killer lives as a decoration on the service context.
*/
static SessionKiller* get(ServiceContext* service);
static SessionKiller* get(OperationContext* opCtx);
/**
* This method binds the SessionKiller to the ServiceContext.
*/
static void set(ServiceContext* ctx, std::shared_ptr sk);
explicit SessionKiller(ServiceContext* sc, KillFunc killer);
~SessionKiller();
/**
* This is the api for killSessions commands to invoke the killer. It blocks until the kill is
* finished, or until it fails (times out on all nodes in mongos).
*/
std::shared_ptr kill(OperationContext* opCtx,
const KillAllSessionsByPatternSet& toKill);
private:
/**
* This struct is a helper to default fill in the result, which is otherwise a little error
* prone.
*/
struct ReapResult {
ReapResult();
std::shared_ptr> result;
};
void _periodicKill(OperationContext* opCtx, stdx::unique_lock& lk);
KillFunc _killFunc;
stdx::thread _thread;
stdx::mutex _mutex;
stdx::condition_variable _callerCV;
stdx::condition_variable _killerCV;
UniformRandomBitGenerator _urbg;
ReapResult _reapResults;
KillAllSessionsByPatternSet _nextToReap;
bool _inShutdown = false;
};
} // namespace mongo