Change session registry to a template class
The template class wraps a HashMap such that only a few operations are allowed. Usage requires specializing a RegistryTraits class template for each entry type.
This commit is contained in:
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include <maxscale/cppdefs.hh>
|
#include <maxscale/cppdefs.hh>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <tr1/unordered_map>
|
||||||
|
|
||||||
namespace maxscale
|
namespace maxscale
|
||||||
{
|
{
|
||||||
@ -177,4 +178,94 @@ struct CloserTraits<FILE*>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Helper type for Registry. Must be specialized for each EntryType. The types
|
||||||
|
* listed below are just examples and will not compile. */
|
||||||
|
template<typename EntryType>
|
||||||
|
struct RegistryTraits
|
||||||
|
{
|
||||||
|
typedef int id_type;
|
||||||
|
typedef EntryType* entry_type;
|
||||||
|
|
||||||
|
static id_type get_id(entry_type entry)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(EntryType) != sizeof(EntryType), "get_id() and the"
|
||||||
|
" surrounding struct must be specialized for every EntryType!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static entry_type null_entry()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Registy wraps a map, allowing only a few operations on it. The intended
|
||||||
|
* use is simple registries, such as the session registry in Worker. The owner
|
||||||
|
* can expose a reference to this class without exposing all the methods the
|
||||||
|
* underlying container implements. When instantiating with a new EntryType, the
|
||||||
|
* traits-class RegistryTraits should be specialized for the new type as well.
|
||||||
|
*/
|
||||||
|
template <typename EntryType>
|
||||||
|
class Registry
|
||||||
|
{
|
||||||
|
Registry(const Registry&);
|
||||||
|
Registry& operator = (const Registry&);
|
||||||
|
public:
|
||||||
|
typedef typename RegistryTraits<EntryType>::id_type id_type;
|
||||||
|
typedef typename RegistryTraits<EntryType>::entry_type entry_type;
|
||||||
|
|
||||||
|
Registry()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Find an entry in the registry.
|
||||||
|
*
|
||||||
|
* @param id Entry key
|
||||||
|
* @return The found entry, or NULL if not found
|
||||||
|
*/
|
||||||
|
entry_type lookup(id_type id) const
|
||||||
|
{
|
||||||
|
entry_type rval = RegistryTraits<EntryType>::null_entry();
|
||||||
|
typename ContainerType::const_iterator iter = m_registry.find(id);
|
||||||
|
if (iter != m_registry.end())
|
||||||
|
{
|
||||||
|
rval = iter->second;
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an entry to the registry.
|
||||||
|
*
|
||||||
|
* @param entry The entry to add
|
||||||
|
* @return True if successful, false if id was already in
|
||||||
|
*/
|
||||||
|
bool add(entry_type entry)
|
||||||
|
{
|
||||||
|
id_type id = RegistryTraits<EntryType>::get_id(entry);
|
||||||
|
typename ContainerType::value_type new_value(id, entry);
|
||||||
|
return m_registry.insert(new_value).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an entry from the registry.
|
||||||
|
*
|
||||||
|
* @param id Entry id
|
||||||
|
* @return True if an entry was removed, false if not found
|
||||||
|
*/
|
||||||
|
bool remove(id_type id)
|
||||||
|
{
|
||||||
|
entry_type rval = lookup(id);
|
||||||
|
if (rval)
|
||||||
|
{
|
||||||
|
m_registry.erase(id);
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef typename std::tr1::unordered_map<id_type, entry_type> ContainerType;
|
||||||
|
ContainerType m_registry;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ bool mxs_worker_register_session(MXS_SESSION* session);
|
|||||||
* @param id Which id to remove.
|
* @param id Which id to remove.
|
||||||
* @return The removed session or NULL if not found.
|
* @return The removed session or NULL if not found.
|
||||||
*/
|
*/
|
||||||
MXS_SESSION* mxs_worker_deregister_session(uint64_t id);
|
bool mxs_worker_deregister_session(uint64_t id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a session in the current worker's session container.
|
* Find a session in the current worker's session container.
|
||||||
|
39
server/core/maxscale/session.hh
Normal file
39
server/core/maxscale/session.hh
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||||
|
*
|
||||||
|
* Use of this software is governed by the Business Source License included
|
||||||
|
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||||
|
*
|
||||||
|
* Change Date: 2019-07-01
|
||||||
|
*
|
||||||
|
* On the date above, in accordance with the Business Source License, use
|
||||||
|
* of this software will be governed by version 2 or later of the General
|
||||||
|
* Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <maxscale/cppdefs.hh>
|
||||||
|
#include <maxscale/session.h>
|
||||||
|
|
||||||
|
namespace maxscale
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Specialization of RegistryTraits for the session registry.
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
struct RegistryTraits<MXS_SESSION>
|
||||||
|
{
|
||||||
|
typedef uint64_t id_type;
|
||||||
|
typedef MXS_SESSION* entry_type;
|
||||||
|
|
||||||
|
static id_type get_id(entry_type entry)
|
||||||
|
{
|
||||||
|
return entry->ses_id;
|
||||||
|
}
|
||||||
|
static entry_type null_entry()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -14,13 +14,14 @@
|
|||||||
|
|
||||||
#include <maxscale/cppdefs.hh>
|
#include <maxscale/cppdefs.hh>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <tr1/unordered_map>
|
|
||||||
#include <maxscale/platform.h>
|
#include <maxscale/platform.h>
|
||||||
#include <maxscale/session.h>
|
#include <maxscale/session.h>
|
||||||
|
#include <maxscale/utils.hh>
|
||||||
#include "messagequeue.hh"
|
#include "messagequeue.hh"
|
||||||
#include "poll.h"
|
#include "poll.h"
|
||||||
#include "worker.h"
|
#include "worker.h"
|
||||||
#include "workertask.hh"
|
#include "workertask.hh"
|
||||||
|
#include "session.hh"
|
||||||
|
|
||||||
namespace maxscale
|
namespace maxscale
|
||||||
{
|
{
|
||||||
@ -69,7 +70,7 @@ public:
|
|||||||
typedef WORKER_STATISTICS STATISTICS;
|
typedef WORKER_STATISTICS STATISTICS;
|
||||||
typedef WorkerTask Task;
|
typedef WorkerTask Task;
|
||||||
typedef WorkerDisposableTask DisposableTask;
|
typedef WorkerDisposableTask DisposableTask;
|
||||||
typedef std::tr1::unordered_map<uint64_t, MXS_SESSION*> SessionsById;
|
typedef Registry<MXS_SESSION> SessionsById;
|
||||||
|
|
||||||
enum state_t
|
enum state_t
|
||||||
{
|
{
|
||||||
@ -397,28 +398,11 @@ public:
|
|||||||
bool post_message(uint32_t msg_id, intptr_t arg1, intptr_t arg2);
|
bool post_message(uint32_t msg_id, intptr_t arg1, intptr_t arg2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a session to the session container.
|
* Return a reference to the session registry of this worker.
|
||||||
*
|
*
|
||||||
* @param session The session to add
|
* @return Session registry.
|
||||||
* @return true if successful
|
|
||||||
*/
|
*/
|
||||||
bool register_session(MXS_SESSION* session);
|
SessionsById& session_registry();
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a session from the session container.
|
|
||||||
*
|
|
||||||
* @param id Session id
|
|
||||||
* @return The removed session, or NULL if not found
|
|
||||||
*/
|
|
||||||
MXS_SESSION* deregister_session(uint64_t id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a session in the session container.
|
|
||||||
*
|
|
||||||
* @param id Session id
|
|
||||||
* @return The found session, or NULL if not found
|
|
||||||
*/
|
|
||||||
MXS_SESSION* find_session(uint64_t id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broadcast a message to all worker.
|
* Broadcast a message to all worker.
|
||||||
|
@ -109,7 +109,7 @@ public:
|
|||||||
|
|
||||||
void execute(maxscale::Worker& worker)
|
void execute(maxscale::Worker& worker)
|
||||||
{
|
{
|
||||||
MXS_SESSION* target = worker.find_session(m_target_id);
|
MXS_SESSION* target = worker.session_registry().lookup(m_target_id);
|
||||||
if (target && issuer_can_kill_target(m_issuer_user, m_issuer_host, target))
|
if (target && issuer_can_kill_target(m_issuer_user, m_issuer_host, target))
|
||||||
{
|
{
|
||||||
poll_fake_hangup_event(target->client_dcb);
|
poll_fake_hangup_event(target->client_dcb);
|
||||||
|
@ -728,55 +728,26 @@ bool mxs_worker_register_session(MXS_SESSION* session)
|
|||||||
{
|
{
|
||||||
Worker* worker = Worker::get_current();
|
Worker* worker = Worker::get_current();
|
||||||
ss_dassert(worker);
|
ss_dassert(worker);
|
||||||
return worker->register_session(session);
|
return worker->session_registry().add(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
MXS_SESSION* mxs_worker_deregister_session(uint64_t id)
|
bool mxs_worker_deregister_session(uint64_t id)
|
||||||
{
|
{
|
||||||
MXS_SESSION* rval = NULL;
|
|
||||||
Worker* worker = Worker::get_current();
|
Worker* worker = Worker::get_current();
|
||||||
if (worker)
|
ss_dassert(worker);
|
||||||
{
|
return worker->session_registry().remove(id);
|
||||||
rval = worker->deregister_session(id);
|
|
||||||
}
|
|
||||||
return rval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MXS_SESSION* mxs_worker_find_session(uint64_t id)
|
MXS_SESSION* mxs_worker_find_session(uint64_t id)
|
||||||
{
|
{
|
||||||
MXS_SESSION* rval = NULL;
|
|
||||||
Worker* worker = Worker::get_current();
|
Worker* worker = Worker::get_current();
|
||||||
if (worker)
|
ss_dassert(worker);
|
||||||
{
|
return worker->session_registry().lookup(id);
|
||||||
rval = worker->find_session(id);
|
|
||||||
}
|
|
||||||
return rval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Worker::register_session(MXS_SESSION* session)
|
Worker::SessionsById& Worker::session_registry()
|
||||||
{
|
{
|
||||||
return m_sessions.insert(SessionsById::value_type(session->ses_id, session)).second;
|
return m_sessions;
|
||||||
}
|
|
||||||
|
|
||||||
MXS_SESSION* Worker::deregister_session(uint64_t id)
|
|
||||||
{
|
|
||||||
MXS_SESSION* rval = find_session(id);
|
|
||||||
if (rval)
|
|
||||||
{
|
|
||||||
m_sessions.erase(id);
|
|
||||||
}
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
MXS_SESSION* Worker::find_session(uint64_t id)
|
|
||||||
{
|
|
||||||
MXS_SESSION* rval = NULL;
|
|
||||||
SessionsById::const_iterator iter = m_sessions.find(id);
|
|
||||||
if (iter != m_sessions.end())
|
|
||||||
{
|
|
||||||
rval = iter->second;
|
|
||||||
}
|
|
||||||
return rval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class WorkerInfoTask: public maxscale::WorkerTask
|
class WorkerInfoTask: public maxscale::WorkerTask
|
||||||
|
@ -1305,8 +1305,8 @@ static int gw_client_close(DCB *dcb)
|
|||||||
{
|
{
|
||||||
ss_dassert(target->state == SESSION_STATE_ROUTER_READY ||
|
ss_dassert(target->state == SESSION_STATE_ROUTER_READY ||
|
||||||
target->state == SESSION_STATE_STOPPING);
|
target->state == SESSION_STATE_STOPPING);
|
||||||
ss_debug(MXS_SESSION* removed =) mxs_worker_deregister_session(target->ses_id);
|
ss_debug(bool removed =) mxs_worker_deregister_session(target->ses_id);
|
||||||
ss_dassert(removed == target);
|
ss_dassert(removed);
|
||||||
session_close(target);
|
session_close(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user