mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-03 23:45:27 +00:00
[#1147] Reorganized v6 client handler
This commit is contained in:
@@ -18,20 +18,6 @@ using namespace isc::util;
|
|||||||
namespace isc {
|
namespace isc {
|
||||||
namespace dhcp {
|
namespace dhcp {
|
||||||
|
|
||||||
mutex ClientHandler::mutex_;
|
|
||||||
|
|
||||||
ClientHandler::ClientContainer ClientHandler::clients_;
|
|
||||||
|
|
||||||
ClientHandler::ClientHandler() : client_(), locked_() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientHandler::~ClientHandler() {
|
|
||||||
if (locked_) {
|
|
||||||
lock_guard<mutex> lock_(mutex_);
|
|
||||||
unLock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientHandler::Client::Client(Pkt6Ptr query, DuidPtr client_id)
|
ClientHandler::Client::Client(Pkt6Ptr query, DuidPtr client_id)
|
||||||
: query_(query), thread_(this_thread::get_id()) {
|
: query_(query), thread_(this_thread::get_id()) {
|
||||||
// Sanity checks.
|
// Sanity checks.
|
||||||
@@ -45,6 +31,10 @@ ClientHandler::Client::Client(Pkt6Ptr query, DuidPtr client_id)
|
|||||||
duid_ = client_id->getDuid();
|
duid_ = client_id->getDuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex ClientHandler::mutex_;
|
||||||
|
|
||||||
|
ClientHandler::ClientContainer ClientHandler::clients_;
|
||||||
|
|
||||||
ClientHandler::ClientPtr
|
ClientHandler::ClientPtr
|
||||||
ClientHandler::lookup(const DuidPtr& duid) {
|
ClientHandler::lookup(const DuidPtr& duid) {
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
@@ -60,37 +50,34 @@ ClientHandler::lookup(const DuidPtr& duid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ClientHandler::lock() {
|
ClientHandler::add(const ClientPtr& client) {
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
if (!locked_) {
|
if (!client) {
|
||||||
isc_throw(Unexpected, "nothing to lock in ClientHandler::lock");
|
isc_throw(InvalidParameter, "client is null in ClientHandler::add");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume insert will never fail so not checking its result.
|
// Assume insert will never fail so not checking its result.
|
||||||
clients_.insert(client_);
|
clients_.insert(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ClientHandler::unLock() {
|
ClientHandler::del(const DuidPtr& duid) {
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
if (!locked_) {
|
if (!duid) {
|
||||||
isc_throw(Unexpected, "nothing to unlock in ClientHandler::unLock");
|
isc_throw(InvalidParameter, "duid is null in ClientHandler::del");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume erase will never fail so not checking its result.
|
// Assume erase will never fail so not checking its result.
|
||||||
clients_.erase(locked_->getDuid());
|
clients_.erase(duid->getDuid());
|
||||||
locked_.reset();
|
|
||||||
if (!client_ || !client_->cont_) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to process next query. As the caller holds the mutex of
|
ClientHandler::ClientHandler() : client_(), locked_() {
|
||||||
// the handler class the continuation will be resumed after.
|
|
||||||
MultiThreadingMgr& mt_mgr = MultiThreadingMgr::instance();
|
|
||||||
if (mt_mgr.getMode()) {
|
|
||||||
if (!mt_mgr.getThreadPool().addFront(client_->cont_)) {
|
|
||||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_PACKET_QUEUE_FULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClientHandler::~ClientHandler() {
|
||||||
|
if (locked_) {
|
||||||
|
lock_guard<mutex> lock_(mutex_);
|
||||||
|
unLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,5 +145,37 @@ ClientHandler::tryLock(Pkt6Ptr query, ContinuationPtr cont) {
|
|||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClientHandler::lock() {
|
||||||
|
// Sanity check.
|
||||||
|
if (!locked_) {
|
||||||
|
isc_throw(Unexpected, "nothing to lock in ClientHandler::lock");
|
||||||
|
}
|
||||||
|
add(client_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClientHandler::unLock() {
|
||||||
|
// Sanity check.
|
||||||
|
if (!locked_) {
|
||||||
|
isc_throw(Unexpected, "nothing to unlock in ClientHandler::unLock");
|
||||||
|
}
|
||||||
|
|
||||||
|
del(locked_);
|
||||||
|
locked_.reset();
|
||||||
|
if (!client_ || !client_->cont_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to process next query. As the caller holds the mutex of
|
||||||
|
// the handler class the continuation will be resumed after.
|
||||||
|
MultiThreadingMgr& mt_mgr = MultiThreadingMgr::instance();
|
||||||
|
if (mt_mgr.getMode()) {
|
||||||
|
if (!mt_mgr.getThreadPool().addFront(client_->cont_)) {
|
||||||
|
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_BASIC, DHCP6_PACKET_QUEUE_FULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dhcp
|
} // namespace dhcp
|
||||||
} // namespace isc
|
} // namespace isc
|
||||||
|
@@ -35,31 +35,10 @@ inline ContinuationPtr makeContinuation(Continuation&& cont) {
|
|||||||
|
|
||||||
/// @brief Client race avoidance RAII handler.
|
/// @brief Client race avoidance RAII handler.
|
||||||
class ClientHandler : public boost::noncopyable {
|
class ClientHandler : public boost::noncopyable {
|
||||||
public:
|
|
||||||
|
|
||||||
/// @brief Constructor.
|
|
||||||
ClientHandler();
|
|
||||||
|
|
||||||
/// @brief Destructor.
|
|
||||||
///
|
|
||||||
/// Releases the client if it was acquired.
|
|
||||||
virtual ~ClientHandler();
|
|
||||||
|
|
||||||
/// @brief Tries to acquires a client.
|
|
||||||
///
|
|
||||||
/// Lookup the client:
|
|
||||||
/// - if not found insert the client in the clients map and return true
|
|
||||||
/// - if found, if has a continuation put it in the holder,
|
|
||||||
/// and return false
|
|
||||||
///
|
|
||||||
/// @param query The query from the client.
|
|
||||||
/// @param cont The continuation in the case the client was held.
|
|
||||||
/// @return true if the client was acquired, false if there is already
|
|
||||||
/// a query from the same client.
|
|
||||||
bool tryLock(Pkt6Ptr query, ContinuationPtr cont = ContinuationPtr());
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/// Class (aka static) types, methods and members.
|
||||||
|
|
||||||
/// @brief Structure representing a client.
|
/// @brief Structure representing a client.
|
||||||
struct Client {
|
struct Client {
|
||||||
|
|
||||||
@@ -95,38 +74,6 @@ private:
|
|||||||
/// @brief The type of shared pointers to clients.
|
/// @brief The type of shared pointers to clients.
|
||||||
typedef boost::shared_ptr<Client> ClientPtr;
|
typedef boost::shared_ptr<Client> ClientPtr;
|
||||||
|
|
||||||
/// @brief Local client.
|
|
||||||
ClientPtr client_;
|
|
||||||
|
|
||||||
/// @brief Client ID locked by this handler.
|
|
||||||
DuidPtr locked_;
|
|
||||||
|
|
||||||
/// @brief Mutex to protect the client container.
|
|
||||||
///
|
|
||||||
/// The mutex is used only by public methods for guards.
|
|
||||||
static std::mutex mutex_;
|
|
||||||
|
|
||||||
/// @brief Lookup a client.
|
|
||||||
///
|
|
||||||
/// The mutex must be held by the caller.
|
|
||||||
///
|
|
||||||
/// @param duid The duid of the query from the client.
|
|
||||||
/// @return The held client or null.
|
|
||||||
static ClientPtr lookup(const DuidPtr& duid);
|
|
||||||
|
|
||||||
/// @brief Acquire a client.
|
|
||||||
///
|
|
||||||
/// The mutex must be held by the caller.
|
|
||||||
void lock();
|
|
||||||
|
|
||||||
/// @brief Release a client.
|
|
||||||
///
|
|
||||||
/// If the client has a continuation, push it at front of the thread
|
|
||||||
/// packet queue.
|
|
||||||
///
|
|
||||||
/// The mutex must be held by the caller.
|
|
||||||
void unLock();
|
|
||||||
|
|
||||||
/// @brief The type of the client container.
|
/// @brief The type of the client container.
|
||||||
typedef boost::multi_index_container<
|
typedef boost::multi_index_container<
|
||||||
|
|
||||||
@@ -147,8 +94,84 @@ private:
|
|||||||
>
|
>
|
||||||
> ClientContainer;
|
> ClientContainer;
|
||||||
|
|
||||||
|
/// @brief Lookup a client.
|
||||||
|
///
|
||||||
|
/// The mutex must be held by the caller.
|
||||||
|
///
|
||||||
|
/// @param duid The duid of the query from the client.
|
||||||
|
/// @return The client found in the container or null.
|
||||||
|
static ClientPtr lookup(const DuidPtr& duid);
|
||||||
|
|
||||||
|
/// @brief Add a client.
|
||||||
|
///
|
||||||
|
/// The mutex must be held by the caller.
|
||||||
|
///
|
||||||
|
/// @param client The client to insert into the client container.
|
||||||
|
static void add(const ClientPtr& client);
|
||||||
|
|
||||||
|
/// @brief Delete a client.
|
||||||
|
///
|
||||||
|
/// The mutex must be held by the caller.
|
||||||
|
///
|
||||||
|
/// @param duid The duid to delete from the client container.
|
||||||
|
static void del(const DuidPtr& duid);
|
||||||
|
|
||||||
|
/// @brief Mutex to protect the client container.
|
||||||
|
///
|
||||||
|
/// The mutex is used only by public methods for guards.
|
||||||
|
static std::mutex mutex_;
|
||||||
|
|
||||||
/// @brief The client container.
|
/// @brief The client container.
|
||||||
static ClientContainer clients_;
|
static ClientContainer clients_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Public interface.
|
||||||
|
|
||||||
|
/// @brief Constructor.
|
||||||
|
ClientHandler();
|
||||||
|
|
||||||
|
/// @brief Destructor.
|
||||||
|
///
|
||||||
|
/// Releases the client if it was acquired.
|
||||||
|
virtual ~ClientHandler();
|
||||||
|
|
||||||
|
/// @brief Tries to acquires a client.
|
||||||
|
///
|
||||||
|
/// Lookup the client:
|
||||||
|
/// - if not found insert the client in the clients map and return true
|
||||||
|
/// - if found, if has a continuation put it in the holder,
|
||||||
|
/// and return false
|
||||||
|
///
|
||||||
|
/// @param query The query from the client.
|
||||||
|
/// @param cont The continuation in the case the client was held.
|
||||||
|
/// @return true if the client was acquired, false if there is already
|
||||||
|
/// a query from the same client.
|
||||||
|
bool tryLock(Pkt6Ptr query, ContinuationPtr cont = ContinuationPtr());
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/// Instance methods and members.
|
||||||
|
|
||||||
|
/// @brief Acquire a client.
|
||||||
|
///
|
||||||
|
/// The mutex must be held by the caller.
|
||||||
|
void lock();
|
||||||
|
|
||||||
|
/// @brief Release a client.
|
||||||
|
///
|
||||||
|
/// If the client has a continuation, push it at front of the thread
|
||||||
|
/// packet queue.
|
||||||
|
///
|
||||||
|
/// The mutex must be held by the only caller: the destructor.
|
||||||
|
void unLock();
|
||||||
|
|
||||||
|
/// @brief Local client.
|
||||||
|
ClientPtr client_;
|
||||||
|
|
||||||
|
/// @brief Client ID locked by this handler.
|
||||||
|
DuidPtr locked_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace isc
|
} // namespace isc
|
||||||
|
Reference in New Issue
Block a user