ReadConnRoute can handle now COM_CHANGE_USER

mysql_backend calls routeReply with backand results.

routeReply in readwritesplit.c can understand the dcb->command value
This commit is contained in:
Massimiliano Pinto
2013-07-17 10:39:08 +02:00
parent 91f1b4bc6f
commit b6cbe3a34c
4 changed files with 131 additions and 58 deletions

View File

@ -42,14 +42,16 @@
* Revision History
*
* Date Who Description
* 14/06/13 Mark Riddoch Initial implementation
* 25/06/13 Mark Riddoch Addition of checks for current server state
* 26/06/13 Mark Riddoch Use server with least connections since
* startup if the number of current
* connections is the same for two servers
* Addition of master and slave options
* 27/06/13 Vilho Raatikka Added skygw_log_write command as an example
* and necessary headers.
* 14/06/2013 Mark Riddoch Initial implementation
* 25/06/2013 Mark Riddoch Addition of checks for current server state
* 26/06/2013 Mark Riddoch Use server with least connections since
* startup if the number of current
* connections is the same for two servers
* Addition of master and slave options
* 27/06/2013 Vilho Raatikka Added skygw_log_write command as an example
* and necessary headers.
* 17/07/2013 Massimiliano Pinto Added clientReply routine:
called by backend server to send data to client
*
* @endverbatim
*/
@ -77,9 +79,10 @@ static void *newSession(ROUTER *instance, SESSION *session);
static void closeSession(ROUTER *instance, void *router_session);
static int routeQuery(ROUTER *instance, void *router_session, GWBUF *queue);
static void diagnostics(ROUTER *instance, DCB *dcb);
static void clientReply(ROUTER* instance, void* router_session, GWBUF* queue, DCB *backend_dcb);
/** The module object definition */
static ROUTER_OBJECT MyObject = { createInstance, newSession, closeSession, routeQuery, diagnostics, NULL };
static ROUTER_OBJECT MyObject = { createInstance, newSession, closeSession, routeQuery, diagnostics, clientReply };
static SPINLOCK instlock;
static INSTANCE *instances;
@ -369,9 +372,18 @@ routeQuery(ROUTER *instance, void *router_session, GWBUF *queue)
{
INSTANCE *inst = (INSTANCE *)instance;
CLIENT_SESSION *session = (CLIENT_SESSION *)router_session;
char *paylod = GWBUF_DATA(queue);
int mysql_command = -1;
mysql_command = paylod[4];
inst->stats.n_queries++;
return session->dcb->func.write(session->dcb, queue);
if (mysql_command == 0x11) {
return session->dcb->func.auth(session->dcb, NULL, session->dcb->session, queue);
} else {
return session->dcb->func.write(session->dcb, queue);
}
}
/**
@ -400,3 +412,29 @@ int i = 0;
dcb_printf(dcb, "\tCurrent no. of router sessions: %d\n", i);
dcb_printf(dcb, "\tNumber of queries forwarded: %d\n", inst->stats.n_queries);
}
/**
* Client Reply routine
*
* The routine will reply to client data from backend server
*
* @param instance The router instance
* @param router_session The router session
* @param backend_dcb The backend DCB
* @param queue The GWBUF with reply data
*/
static void
clientReply(ROUTER* instance, void* router_session, GWBUF* queue, DCB *backend_dcb)
{
INSTANCE* inst = NULL;
DCB *client = NULL;
CLIENT_SESSION* session = NULL;
inst = (INSTANCE *)instance;
session = (CLIENT_SESSION *)router_session;
client = backend_dcb->session->client;
client->func.write(client, queue);
}
///

View File

@ -23,8 +23,10 @@
#include <stdlib.h>
#include <mysql.h>
#if defined(SS_DEBUG)
#include <skygw_utils.h>
#include <log_manager.h>
#endif
#include <query_classifier.h>
#include <dcb.h>
#include <spinlock.h>
@ -420,28 +422,35 @@ static int routeQuery(
case COM_DAEMON: /**< 1d ? */
break;
}
#if defined(SS_DEBUG_)
skygw_log_write(NULL, LOGFILE_TRACE, "String\t\"%s\"", querystr);
skygw_log_write(NULL,
LOGFILE_TRACE,
"Packet type\t%s",
STRPACKETTYPE(packet_type));
#endif
switch (qtype) {
case QUERY_TYPE_WRITE:
#if defined(SS_DEBUG_)
skygw_log_write(NULL,
LOGFILE_TRACE,
"Query type\t%s, routing to Master.",
STRQTYPE(qtype));
#endif
ret = session->masterconn->func.write(session->masterconn, queue);
atomic_add(&inst->stats.n_master, 1);
goto return_ret;
break;
case QUERY_TYPE_READ:
#if defined(SS_DEBUG_)
skygw_log_write(NULL,
LOGFILE_TRACE,
"Query type\t%s, routing to Slave.",
STRQTYPE(qtype));
#endif
ret = session->slaveconn->func.write(session->slaveconn, queue);
atomic_add(&inst->stats.n_slave, 1);
goto return_ret;
@ -449,10 +458,12 @@ static int routeQuery(
case QUERY_TYPE_SESSION_WRITE:
#if defined(SS_DEBUG_)
skygw_log_write(NULL,
LOGFILE_TRACE,
"Query type\t%s, routing to All servers.",
STRQTYPE(qtype));
#endif
/**
* TODO! Connection to all servers must be established, and
* the command must be executed in them.
@ -473,10 +484,12 @@ static int routeQuery(
break;
default:
#if defined(SS_DEBUG_)
skygw_log_write(NULL,
LOGFILE_TRACE,
"Query type\t%s, routing to Master by default.",
STRQTYPE(qtype));
#endif
/** Is this really ok? */
ret = session->masterconn->func.write(session->masterconn, queue);
atomic_add(&inst->stats.n_master, 1);
@ -537,19 +550,25 @@ clientReply(ROUTER* instance, void* router_session, GWBUF* queue, DCB *backend_d
{
INSTANCE* inst = NULL;
DCB *master = NULL;
DCB *client = NULL;
CLIENT_SESSION* session = NULL;
int len = 0;
inst = (INSTANCE *)instance;
session = (CLIENT_SESSION *)router_session;
master = session->masterconn;
client = backend_dcb->session->client;
/* if backend_dcb is the master reply to the client */
if (backend_dcb == master) {
master->session->client->func.write(master->session->client, queue);
if (backend_dcb->command == ROUTER_CHANGE_SESSION) {
/* if backend_dcb is the master we can reply to the client */
if (backend_dcb == master) {
master->session->client->func.write(master->session->client, queue);
} else {
/* just consume the gwbuf without writing to the client */
gwbuf_consume(queue, gwbuf_length(queue));
}
} else {
/* just consume the gwbuf without writing to the client */
gwbuf_consume(queue, gwbuf_length(queue));
/* normal flow */
client->func.write(client, queue);
}
}
///