int test2() { GWBUF *buffer; char len = 128; char query[129]; buffer = gwbuf_alloc(132); ss_info_dassert((buffer != NULL),"Buffer should not be null"); memset(query,';',128); memset(query+128,'\0',1); *((unsigned char*)buffer->start) = len; *((unsigned char*)buffer->start+1) = 0; *((unsigned char*)buffer->start+2) = 0; *((unsigned char*)buffer->start+3) = 1; *((unsigned char*)buffer->start+4) = 0x03; memcpy(buffer->start + 5,query,strlen(query)); char* result = modutil_get_SQL(buffer); ss_dassert(strcmp(result,query) == 0); gwbuf_free(buffer); free(result); ss_dfprintf(stderr, "\t..done\n"); return 0; }
/** * The routeQuery entry point. This is passed the query buffer * to which the filter should be applied. Once applied the * query should normally be passed to the downstream component * (filter or router) in the filter chain. * * If the regular expressed configured in the match parameter of the * filter definition matches the SQL text then add the hint * "Route to named server" with the name defined in the server parameter * * @param instance The filter instance data * @param session The filter session * @param queue The query data */ static int routeQuery(FILTER *instance, void *session, GWBUF *queue) { LAG_INSTANCE *my_instance = (LAG_INSTANCE *)instance; LAG_SESSION *my_session = (LAG_SESSION *)session; char *sql; time_t now = time(NULL); if (modutil_is_SQL(queue)) { if (queue->next != NULL) { queue = gwbuf_make_contiguous(queue); } if(!query_is_parsed(queue)) { parse_query(queue); } if(query_classifier_get_operation(queue) & (QUERY_OP_DELETE|QUERY_OP_INSERT|QUERY_OP_UPDATE)) { if((sql = modutil_get_SQL(queue)) != NULL) { if(my_instance->nomatch == NULL||(my_instance->nomatch && regexec(&my_instance->nore,sql,0,NULL,0) != 0)) { if(my_instance->match == NULL|| (my_instance->match && regexec(&my_instance->re,sql,0,NULL,0) == 0)) { my_session->hints_left = my_instance->count; my_session->last_modification = now; my_instance->stats.n_modified++; } } free(sql); } } else if(my_session->hints_left > 0) { queue->hint = hint_create_route(queue->hint, HINT_ROUTE_TO_MASTER, NULL); my_session->hints_left--; my_instance->stats.n_add_count++; } else if(difftime(now,my_session->last_modification) < my_instance->time) { queue->hint = hint_create_route(queue->hint, HINT_ROUTE_TO_MASTER, NULL); my_instance->stats.n_add_time++; } } return my_session->down.routeQuery(my_session->down.instance, my_session->down.session, queue); }
/** * * @param my_instance * @param my_session * @param buffer * @return */ GWBUF* clone_query(TEE_INSTANCE* my_instance, TEE_SESSION* my_session, GWBUF* buffer) { GWBUF* clone = NULL; int length, residual = 0; char* ptr; if (my_session->branch_session && my_session->branch_session->state == SESSION_STATE_ROUTER_READY) { if (my_session->residual) { clone = gwbuf_clone_all(buffer); if (my_session->residual < GWBUF_LENGTH(clone)) { GWBUF_RTRIM(clone, GWBUF_LENGTH(clone) - residual); } my_session->residual -= GWBUF_LENGTH(clone); if (my_session->residual < 0) { my_session->residual = 0; } } else if (my_session->active && (ptr = modutil_get_SQL(buffer)) != NULL) { if ((my_instance->match == NULL || regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) && (my_instance->nomatch == NULL || regexec(&my_instance->nore,ptr,0,NULL, 0) != 0)) { length = modutil_MySQL_query_len(buffer, &residual); clone = gwbuf_clone_all(buffer); my_session->residual = residual; } free(ptr); } else if (packet_is_required(buffer)) { clone = gwbuf_clone_all(buffer); } } return clone; }
/** * The routeQuery entry point. This is passed the query buffer * to which the filter should be applied. Once applied the * query should normally be passed to the downstream component * (filter or router) in the filter chain. * * @param instance The filter instance data * @param session The filter session * @param queue The query data */ static int routeQuery(FILTER *instance, void *session, GWBUF *queue) { QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance; QLA_SESSION *my_session = (QLA_SESSION *)session; char *ptr; int length = 0; struct tm t; struct timeval tv; if (my_session->active) { if (queue->next != NULL) { queue = gwbuf_make_contiguous(queue); } if ((ptr = modutil_get_SQL(queue)) != NULL) { if ((my_instance->match == NULL || regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) && (my_instance->nomatch == NULL || regexec(&my_instance->nore,ptr,0,NULL, 0) != 0)) { gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &t); fprintf(my_session->fp, "%02d:%02d:%02d.%-3d %d/%02d/%d, ", t.tm_hour, t.tm_min, t.tm_sec, (int)(tv.tv_usec / 1000), t.tm_mday, t.tm_mon + 1, 1900 + t.tm_year); fprintf(my_session->fp,"%s\n",ptr); } free(ptr); } } /* Pass the query downstream */ return my_session->down.routeQuery(my_session->down.instance, my_session->down.session, queue); }
/** * The routeQuery entry point. This is passed the query buffer * to which the filter should be applied. Once applied the * query should normally be passed to the downstream component * (filter or router) in the filter chain. * * @param instance The filter instance data * @param session The filter session * @param queue The query data */ static int routeQuery(FILTER *instance, void *session, GWBUF *queue) { TOPN_INSTANCE *my_instance = (TOPN_INSTANCE *) instance; TOPN_SESSION *my_session = (TOPN_SESSION *) session; char *ptr; if (my_session->active) { if (queue->next != NULL) { queue = gwbuf_make_contiguous(queue); } if ((ptr = modutil_get_SQL(queue)) != NULL) { if ((my_instance->match == NULL || regexec(&my_instance->re, ptr, 0, NULL, 0) == 0) && (my_instance->exclude == NULL || regexec(&my_instance->exre, ptr, 0, NULL, 0) != 0)) { my_session->n_statements++; if (my_session->current) { free(my_session->current); } gettimeofday(&my_session->start, NULL); my_session->current = ptr; } else { free(ptr); } } } /* Pass the query downstream */ return my_session->down.routeQuery(my_session->down.instance, my_session->down.session, queue); }
/** * 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; }
/** * The routeQuery entry point. This is passed the query buffer * to which the filter should be applied. Once processed the * query is passed to the downstream component * (filter or router) in the filter chain. * * The Luafilter calls the routeQuery functions of both the session and the global script. * The query is passed as a string parameter to the routeQuery Lua function and * the return values of the session specific function, if any were returned, * are interpreted. If the first value is bool, it is interpreted as a decision * whether to route the query or to send an error packet to the client. * If it is a string, the current query is replaced with the return value and * the query will be routed. If nil is returned, the query is routed normally. * * @param instance The filter instance data * @param session The filter session * @param queue The query data */ static int routeQuery(FILTER *instance, void *session, GWBUF *queue) { LUA_SESSION *my_session = (LUA_SESSION *) session; LUA_INSTANCE *my_instance = (LUA_INSTANCE *) instance; DCB* dcb = my_session->session->client_dcb; char *fullquery = NULL, *ptr; bool route = true; GWBUF* forward = queue; int rc = 0; if (modutil_is_SQL(queue) || modutil_is_SQL_prepare(queue)) { fullquery = modutil_get_SQL(queue); if (fullquery && my_session->lua_state) { spinlock_acquire(&my_session->lock); lua_getglobal(my_session->lua_state, "routeQuery"); lua_pushlstring(my_session->lua_state, fullquery, strlen(fullquery)); if (lua_pcall(my_session->lua_state, 1, 1, 0)) { MXS_ERROR("luafilter: Session scope call to 'routeQuery' failed: '%s'.", lua_tostring(my_session->lua_state, -1)); } else if (lua_gettop(my_session->lua_state)) { if (lua_isstring(my_session->lua_state, -1)) { if (forward) { gwbuf_free(forward); } forward = modutil_create_query((char*) lua_tostring(my_session->lua_state, -1)); } else if (lua_isboolean(my_session->lua_state, -1)) { route = lua_toboolean(my_session->lua_state, -1); } } spinlock_release(&my_session->lock); } if (my_instance->global_lua_state) { spinlock_acquire(&my_instance->lock); lua_getglobal(my_instance->global_lua_state, "routeQuery"); lua_pushlstring(my_instance->global_lua_state, fullquery, strlen(fullquery)); if (lua_pcall(my_instance->global_lua_state, 1, 0, 0)) { MXS_ERROR("luafilter: Global scope call to 'routeQuery' failed: '%s'.", lua_tostring(my_session->lua_state, -1)); } else if (lua_gettop(my_instance->global_lua_state)) { if (lua_isstring(my_instance->global_lua_state, -1)) { if (forward) { gwbuf_free(forward); } forward = modutil_create_query((char*) lua_tostring(my_instance->global_lua_state, -1)); } else if (lua_isboolean(my_instance->global_lua_state, -1)) { route = lua_toboolean(my_instance->global_lua_state, -1); } } spinlock_release(&my_instance->lock); } free(fullquery); } if (!route) { gwbuf_free(queue); GWBUF* err = modutil_create_mysql_err_msg(1, 0, 1045, "28000", "Access denied."); rc = dcb->func.write(dcb, err); } else { rc = my_session->down.routeQuery(my_session->down.instance, my_session->down.session, forward); } return rc; }