MXS-1220: Simplify admin request handling
The admin requests are now processed in blocking mode. The timing out of connecttions is handled by a specific timeout thread that checks the state of each admin request. The simplification will help with the JSON parsing with PUT/POST commands. If non-blocking IO is used, the network reading code and JSON parsing needs a lot more work to handle partial reads. If the administrative interface requires higher performance and concurrency, a multi-threaded solution could be created.
This commit is contained in:

committed by
Markus Mäkelä

parent
439d67d129
commit
e34b65658e
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "maxscale/admin.hh"
|
||||
#include "maxscale/hk_heartbeat.h"
|
||||
|
||||
#include <climits>
|
||||
#include <new>
|
||||
@ -26,6 +27,7 @@
|
||||
|
||||
static AdminListener* admin = NULL;
|
||||
static THREAD admin_thread;
|
||||
static THREAD timeout_thread;
|
||||
|
||||
// TODO: Read values from the configuration
|
||||
static AdminConfig config = {DEFAULT_ADMIN_HOST, DEFAULT_ADMIN_PORT};
|
||||
@ -36,6 +38,12 @@ void admin_main(void* data)
|
||||
admin->start();
|
||||
}
|
||||
|
||||
void timeout_main(void *data)
|
||||
{
|
||||
AdminListener* admin = reinterpret_cast<AdminListener*>(data);
|
||||
admin->check_timeouts();
|
||||
}
|
||||
|
||||
AdminConfig& mxs_admin_get_config()
|
||||
{
|
||||
return config;
|
||||
@ -56,12 +64,14 @@ bool mxs_admin_init()
|
||||
|
||||
if (admin)
|
||||
{
|
||||
if (thread_start(&admin_thread, admin_main, admin))
|
||||
if (thread_start(&admin_thread, admin_main, admin) &&
|
||||
thread_start(&timeout_thread, timeout_main, admin))
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
admin->stop();
|
||||
delete admin;
|
||||
admin = NULL;
|
||||
}
|
||||
@ -87,6 +97,7 @@ void mxs_admin_shutdown()
|
||||
if (admin)
|
||||
{
|
||||
admin->stop();
|
||||
thread_wait(timeout_thread);
|
||||
thread_wait(admin_thread);
|
||||
delete admin;
|
||||
admin = NULL;
|
||||
@ -95,7 +106,7 @@ void mxs_admin_shutdown()
|
||||
|
||||
AdminListener::AdminListener(int sock):
|
||||
m_socket(sock),
|
||||
m_active(0),
|
||||
m_active(1),
|
||||
m_timeout(10)
|
||||
{
|
||||
}
|
||||
@ -111,15 +122,15 @@ void AdminListener::handle_clients()
|
||||
|
||||
if (client)
|
||||
{
|
||||
client->process();
|
||||
delete client;
|
||||
SAdminClient sclient(client);
|
||||
ClientList::iterator it = m_clients.insert(m_clients.begin(), sclient);
|
||||
sclient->process();
|
||||
m_clients.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void AdminListener::start()
|
||||
{
|
||||
atomic_write(&m_active, 1);
|
||||
|
||||
while (atomic_read(&m_active))
|
||||
{
|
||||
MXS_EXCEPTION_GUARD(handle_clients());
|
||||
@ -140,7 +151,6 @@ AdminClient* AdminListener::accept_client()
|
||||
|
||||
if (fd > -1)
|
||||
{
|
||||
setnonblocking(fd);
|
||||
rval = new AdminClient(fd, addr, m_timeout);
|
||||
}
|
||||
else if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
@ -155,3 +165,29 @@ AdminClient* AdminListener::accept_client()
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
void AdminListener::handle_timeouts()
|
||||
{
|
||||
int64_t now = hkheartbeat;
|
||||
|
||||
for (ClientList::iterator it = m_clients.begin(); it != m_clients.end(); it++)
|
||||
{
|
||||
SAdminClient& client = *it;
|
||||
|
||||
if (now - client->last_activity() > m_timeout * 10)
|
||||
{
|
||||
client->close_connection();
|
||||
}
|
||||
}
|
||||
|
||||
/** Sleep for roughly one housekeeper heartbeat */
|
||||
thread_millisleep(100);
|
||||
}
|
||||
|
||||
void AdminListener::check_timeouts()
|
||||
{
|
||||
while (atomic_read(&m_active))
|
||||
{
|
||||
MXS_EXCEPTION_GUARD(handle_timeouts());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user