/** * Close a session with the router, this is the mechanism * by which a router may cleanup data structure etc. * * @param instance The router instance data * @param router_session The session being closed */ static void closeSession(ROUTER *instance, void *router_session) { ROUTER_CLIENT_SES *router_cli_ses = (ROUTER_CLIENT_SES *)router_session; DCB* backend_dcb; CHK_CLIENT_RSES(router_cli_ses); /** * Lock router client session for secure read and update. */ if (rses_begin_locked_router_action(router_cli_ses)) { /* decrease server current connection counter */ atomic_add(&router_cli_ses->backend->server->stats.n_current, -1); backend_dcb = router_cli_ses->backend_dcb; router_cli_ses->backend_dcb = NULL; router_cli_ses->rses_closed = true; /** Unlock */ rses_end_locked_router_action(router_cli_ses); /** * Close the backend server connection */ if (backend_dcb != NULL) { CHK_DCB(backend_dcb); dcb_close(backend_dcb); } } }
/** * We have data from the client, we must route it to the backend. * This is simply a case of sending it to the connection that was * chosen when we started the client session. * * @param instance The router instance * @param router_session The router session returned from the newSession call * @param queue The queue of data buffers to route * @return if succeed 1, otherwise 0 */ static int routeQuery(ROUTER *instance, void *router_session, GWBUF *queue) { ROUTER_INSTANCE *inst = (ROUTER_INSTANCE *)instance; ROUTER_CLIENT_SES *router_cli_ses = (ROUTER_CLIENT_SES *)router_session; uint8_t *payload = GWBUF_DATA(queue); int mysql_command; int rc; DCB* backend_dcb; bool rses_is_closed; inst->stats.n_queries++; mysql_command = MYSQL_GET_COMMAND(payload); /** Dirty read for quick check if router is closed. */ if (router_cli_ses->rses_closed) { rses_is_closed = true; } else { /** * Lock router client session for secure read of DCBs */ rses_is_closed = !(rses_begin_locked_router_action(router_cli_ses)); } if (!rses_is_closed) { backend_dcb = router_cli_ses->backend_dcb; /** unlock */ rses_end_locked_router_action(router_cli_ses); } if (rses_is_closed || backend_dcb == NULL || SERVER_IS_DOWN(router_cli_ses->backend->server)) { LOGIF(LT, (skygw_log_write( LOGFILE_TRACE|LOGFILE_ERROR, "Error : Failed to route MySQL command %d to backend " "server.%s", mysql_command,rses_is_closed ? " Session is closed." : ""))); rc = 0; goto return_rc; } char* trc = NULL; switch(mysql_command) { case MYSQL_COM_CHANGE_USER: rc = backend_dcb->func.auth( backend_dcb, NULL, backend_dcb->session, queue); break; case MYSQL_COM_QUERY: LOGIF(LOGFILE_TRACE,(trc = modutil_get_SQL(queue))); default: rc = backend_dcb->func.write(backend_dcb, queue); break; } LOGIF(LOGFILE_TRACE,skygw_log_write( LOGFILE_DEBUG|LOGFILE_TRACE, "Routed [%s] to '%s'%s%s", STRPACKETTYPE(mysql_command), backend_dcb->server->unique_name, trc?": ":".", trc?trc:"")); free(trc); return_rc: return rc; }
/** * We have data from the client, we must route it to the backend. * This is simply a case of sending it to the connection that was * chosen when we started the client session. * * @param instance The router instance * @param router_session The router session returned from the newSession call * @param queue The queue of data buffers to route * @return The number of bytes sent */ static int routeQuery(ROUTER *instance, void *router_session, GWBUF *queue) { ROUTER_INSTANCE *inst = (ROUTER_INSTANCE *)instance; ROUTER_CLIENT_SES *router_cli_ses = (ROUTER_CLIENT_SES *)router_session; uint8_t *payload = GWBUF_DATA(queue); int mysql_command; int rc; DCB* backend_dcb; bool rses_is_closed; inst->stats.n_queries++; mysql_command = MYSQL_GET_COMMAND(payload); /** Dirty read for quick check if router is closed. */ if (router_cli_ses->rses_closed) { rses_is_closed = true; } else { /** * Lock router client session for secure read of DCBs */ rses_is_closed = !(rses_begin_locked_router_action(router_cli_ses)); } if (!rses_is_closed) { backend_dcb = router_cli_ses->backend_dcb; /** unlock */ rses_end_locked_router_action(router_cli_ses); } if (rses_is_closed || backend_dcb == NULL) { LOGIF(LT, (skygw_log_write( LOGFILE_TRACE, "Error : Failed to route MySQL command %d to backend " "server.", mysql_command))); goto return_rc; } switch(mysql_command) { case MYSQL_COM_CHANGE_USER: rc = backend_dcb->func.auth( backend_dcb, NULL, backend_dcb->session, queue); break; default: rc = backend_dcb->func.write(backend_dcb, queue); break; } CHK_PROTOCOL(((MySQLProtocol*)backend_dcb->protocol)); LOGIF(LD, (skygw_log_write( LOGFILE_DEBUG, "%lu [readconnroute:routeQuery] Routed command %d to dcb %p " "with return value %d.", pthread_self(), mysql_command, backend_dcb, rc))); return_rc: return rc; }