Add delayed query retry prototype

This is a proof-of-concept that validates the query retrying method. The
actual implementation of the query retrying mechanism needs more thought
as using the housekeeper is not very efficient.
This commit is contained in:
Markus Mäkelä
2018-04-01 13:27:30 +03:00
parent e76b00e340
commit 761fda2806
7 changed files with 140 additions and 4 deletions

View File

@ -47,6 +47,7 @@
using std::string;
using std::stringstream;
using namespace maxscale;
/** Global session id counter. Must be updated atomically. Value 0 is reserved for
* dummy/unused sessions.
@ -1378,3 +1379,93 @@ void session_dump_statements(MXS_SESSION* pSession)
}
}
}
class DelayedRoutingTask: public mxs::WorkerDisposableTask
{
DelayedRoutingTask(const DelayedRoutingTask&);
DelayedRoutingTask& operator=(const DelayedRoutingTask&);
public:
DelayedRoutingTask(MXS_SESSION* session, MXS_DOWNSTREAM down, GWBUF *buffer):
m_session(session_get_ref(session)),
m_down(down),
m_buffer(buffer)
{
}
~DelayedRoutingTask()
{
session_put_ref(m_session);
gwbuf_free(m_buffer);
}
void execute(Worker& worker)
{
if (m_session->state == SESSION_STATE_ROUTER_READY)
{
GWBUF* buffer = m_buffer;
m_buffer = NULL;
if (m_down.routeQuery(m_down.instance, m_down.session, buffer) == 0)
{
// Routing failed, send a hangup to the client.
poll_fake_hangup_event(m_session->client_dcb);
}
}
}
private:
MXS_SESSION* m_session;
MXS_DOWNSTREAM m_down;
GWBUF* m_buffer;
};
struct TaskAssignment
{
TaskAssignment(std::auto_ptr<DelayedRoutingTask> task, Worker* worker):
task(task),
worker(worker)
{}
std::auto_ptr<DelayedRoutingTask> task;
Worker* worker;
};
static void delayed_routing_cb(void* data)
{
TaskAssignment* job = static_cast<TaskAssignment*>(data);
job->worker->post(job->task, mxs::Worker::EXECUTE_QUEUED);
delete job;
}
bool session_delay_routing(MXS_SESSION* session, MXS_DOWNSTREAM down, GWBUF* buffer, int seconds)
{
bool success = false;
try
{
std::stringstream name;
name << "Session_" << session->ses_id << "_retry";
Worker* worker = Worker::get_current();
ss_dassert(worker == Worker::get(session->client_dcb->poll.thread.id));
std::auto_ptr<DelayedRoutingTask> task(new DelayedRoutingTask(session, down, buffer));
std::auto_ptr<TaskAssignment> job(new TaskAssignment(task, worker));
TaskAssignment* pJob = job.release();
if (hktask_oneshot(name.str().c_str(), delayed_routing_cb, pJob, seconds))
{
success = true;
}
else
{
delete pJob;
}
}
catch (std::bad_alloc)
{
MXS_OOM();
}
return success;
}