static int test1() { GWBUF *buffer; char *(sql[100]); int result, length, residual; /* Poll tests */ ss_dfprintf(stderr, "testmodutil : Rudimentary tests."); buffer = gwbuf_alloc(100); ss_info_dassert(0 == modutil_is_SQL(buffer), "Default buffer should be diagnosed as not SQL"); /* There would ideally be some straightforward way to create a SQL buffer? */ ss_dfprintf(stderr, "\t..done\nExtract SQL from buffer"); ss_info_dassert(0 == modutil_extract_SQL(buffer, sql, &length), "Default buffer should fail"); ss_dfprintf(stderr, "\t..done\nExtract SQL from buffer different way?"); ss_info_dassert(0 == modutil_MySQL_Query(buffer, sql, &length, &residual), "Default buffer should fail"); ss_dfprintf(stderr, "\t..done\nReplace SQL in buffer"); ss_info_dassert(0 == modutil_replace_SQL(buffer, "select * from some_table;"), "Default buffer should fail"); ss_dfprintf(stderr, "\t..done\nTidy up."); gwbuf_free(buffer); 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. * * @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; int length; if (my_session->active && modutil_extract_SQL(queue, &ptr, &length)) { 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 = strndup(ptr, length); } } /* 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) { QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance; QLA_SESSION *my_session = (QLA_SESSION *)session; char *ptr; int length; struct tm t; struct timeval tv; if (my_session->active && modutil_extract_SQL(queue, &ptr, &length)) { 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); fwrite(ptr, sizeof(char), length, my_session->fp); fwrite("\n", sizeof(char), 1, my_session->fp); } } /* 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 processed the * query is passed to the downstream component * (filter or router) in the filter chain. * * The function checks whether required logging trigger conditions are met and if so, * tries to extract a SQL query out of the query buffer, canonize the query, add * a timestamp to it and publish the resulting string on the exchange. * The message is tagged with an unique identifier and the clientReply will * use the same identifier for the reply from the backend to form a query-reply pair. * * @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) { MQ_SESSION *my_session = (MQ_SESSION *)session; MQ_INSTANCE *my_instance = (MQ_INSTANCE *)instance; char *ptr, t_buf[128], *combined,*canon_q,*sesshost,*sessusr; bool success = false, src_ok = false,schema_ok = false,obj_ok = false; int length, i, j,dbcount = 0; char** sesstbls; unsigned int plen = 0; amqp_basic_properties_t *prop; /**The user is changing databases*/ if(*((char*)(queue->start + 4)) == 0x02){ if(my_session->db){ free(my_session->db); } plen = pktlen(queue->start); my_session->db = calloc(plen,sizeof(char)); memcpy(my_session->db,queue->start + 5,plen - 1); } if(modutil_is_SQL(queue)){ /**Parse the query*/ if (!query_is_parsed(queue)){ success = parse_query(queue); } if(!success){ skygw_log_write(LOGFILE_ERROR,"Error: Parsing query failed."); goto send_downstream; } if(!my_instance->log_all){ if(!skygw_is_real_query(queue)){ goto send_downstream; } } if(my_instance->trgtype == TRG_ALL){ skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_ALL"); schema_ok = true; src_ok = true; obj_ok = true; goto validate_triggers; } if(my_instance->trgtype & TRG_SOURCE && my_instance->src_trg){ if(session_isvalid(my_session->session)){ sessusr = session_getUser(my_session->session); sesshost = session_get_remote(my_session->session); /**Username was configured*/ if(my_instance->src_trg->usize > 0){ for(i = 0;i<my_instance->src_trg->usize;i++){ if(strcmp(my_instance->src_trg->user[i],sessusr) == 0) { skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_SOURCE: user: %s = %s",my_instance->src_trg->user[i],sessusr); src_ok = true; break; } } } /**If username was not matched, try to match hostname*/ if(!src_ok && my_instance->src_trg->hsize > 0){ for(i = 0;i<my_instance->src_trg->hsize;i++){ if(strcmp(my_instance->src_trg->host[i],sesshost) == 0) { skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_SOURCE: host: %s = %s",my_instance->src_trg->host[i],sesshost); src_ok = true; break; } } } } if(src_ok && !my_instance->strict_logging){ schema_ok = true; obj_ok = true; goto validate_triggers; } }else{ src_ok = true; } if(my_instance->trgtype & TRG_SCHEMA && my_instance->shm_trg){ int tbsz = 0,z; char** tblnames = skygw_get_table_names(queue,&tbsz,true); char* tmp; bool all_remotes = true; for(z = 0;z<tbsz;z++){ if((tmp = strchr(tblnames[z],'.')) != NULL){ char *lasts; tmp = strtok_r(tblnames[z],".",&lasts); for(i = 0; i<my_instance->shm_trg->size; i++){ if(strcmp(tmp,my_instance->shm_trg->objects[i]) == 0){ skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_SCHEMA: %s = %s",tmp,my_instance->shm_trg->objects[i]); schema_ok = true; break; } } }else{ all_remotes = false; } free(tblnames[z]); } free(tblnames); if(!schema_ok && !all_remotes && my_session->db && strlen(my_session->db)>0){ for(i = 0; i<my_instance->shm_trg->size; i++){ if(strcmp(my_session->db,my_instance->shm_trg->objects[i]) == 0){ skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_SCHEMA: %s = %s",my_session->db,my_instance->shm_trg->objects[i]); schema_ok = true; break; } } } if(schema_ok && !my_instance->strict_logging){ src_ok = true; obj_ok = true; goto validate_triggers; } }else{ schema_ok = true; } if(my_instance->trgtype & TRG_OBJECT && my_instance->obj_trg){ sesstbls = skygw_get_table_names(queue,&dbcount,false); for(j = 0; j<dbcount; j++){ char* tbnm = NULL; if((strchr(sesstbls[j],'.')) != NULL){ char *lasts; tbnm = strtok_r(sesstbls[j],".",&lasts); tbnm = strtok_r(NULL,".",&lasts); }else{ tbnm = sesstbls[j]; } for(i = 0; i<my_instance->obj_trg->size; i++){ if(!strcmp(tbnm,my_instance->obj_trg->objects[i])){ obj_ok = true; skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_OBJECT: %s = %s",my_instance->obj_trg->objects[i],sesstbls[j]); break; } } } if(dbcount > 0){ for(j = 0; j<dbcount; j++){ free(sesstbls[j]); } free(sesstbls); dbcount = 0; } if(obj_ok && !my_instance->strict_logging){ src_ok = true; schema_ok = true; goto validate_triggers; } }else{ obj_ok = true; } validate_triggers: if(src_ok&&schema_ok&&obj_ok){ /** * Something matched the trigger, log the query */ skygw_log_write_flush(LOGFILE_TRACE,"Routing message to: %s:%d %s as %s/%s, exchange: %s<%s> key:%s queue:%s", my_instance->hostname,my_instance->port, my_instance->vhost,my_instance->username, my_instance->password,my_instance->exchange, my_instance->exchange_type,my_instance->key, my_instance->queue); if(my_session->uid == NULL){ my_session->uid = calloc(33,sizeof(char)); if(!my_session->uid){ skygw_log_write(LOGFILE_ERROR,"Error : Out of memory."); }else{ genkey(my_session->uid,32); } } if (queue->next != NULL) { queue = gwbuf_make_contiguous(queue); } if(modutil_extract_SQL(queue, &ptr, &length)){ my_session->was_query = true; if((prop = malloc(sizeof(amqp_basic_properties_t)))){ prop->_flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG | AMQP_BASIC_MESSAGE_ID_FLAG | AMQP_BASIC_CORRELATION_ID_FLAG; prop->content_type = amqp_cstring_bytes("text/plain"); prop->delivery_mode = AMQP_DELIVERY_PERSISTENT; prop->correlation_id = amqp_cstring_bytes(my_session->uid); prop->message_id = amqp_cstring_bytes("query"); } if(success){ /**Try to convert to a canonical form and use the plain query if unsuccessful*/ if((canon_q = skygw_get_canonical(queue)) == NULL){ skygw_log_write_flush(LOGFILE_ERROR, "Error: Cannot form canonical query."); } } memset(t_buf,0,128); sprintf(t_buf, "%lu|",(unsigned long)time(NULL)); int qlen = strnlen(canon_q,length) + strnlen(t_buf,128); if((combined = malloc((qlen+1)*sizeof(char))) == NULL){ skygw_log_write_flush(LOGFILE_ERROR, "Error: Out of memory"); } strcpy(combined,t_buf); strncat(combined,canon_q,length); pushMessage(my_instance,prop,combined); free(canon_q); } } /** Pass the query downstream */ } send_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 processed the * query is passed to the downstream component * (filter or router) in the filter chain. * * The function tries to extract a SQL query out of the query buffer, * adds a timestamp to it and publishes the resulting string on the exchange. * The message is tagged with an unique identifier and the clientReply will * use the same identifier for the reply from the backend. * * @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) { MQ_SESSION *my_session = (MQ_SESSION *)session; MQ_INSTANCE *my_instance = (MQ_INSTANCE *)instance; char *ptr, t_buf[128], *combined; int length, err_code = AMQP_STATUS_OK; amqp_basic_properties_t prop; spinlock_acquire(my_instance->rconn_lock); if(my_instance->conn_stat != AMQP_STATUS_OK){ if(difftime(time(NULL),my_instance->last_rconn) > my_instance->rconn_intv){ my_instance->last_rconn = time(NULL); if(init_conn(my_instance,my_session)){ my_instance->rconn_intv = 1.0; my_instance->conn_stat = AMQP_STATUS_OK; }else{ my_instance->rconn_intv += 5.0; skygw_log_write(LOGFILE_ERROR, "Error : Failed to reconnect to the MQRabbit server "); } err_code = my_instance->conn_stat; } } spinlock_release(my_instance->rconn_lock); if(modutil_is_SQL(queue)){ if(my_session->uid == NULL){ my_session->uid = calloc(33,sizeof(char)); if(!my_session->uid){ skygw_log_write(LOGFILE_ERROR,"Error : Out of memory."); }else{ genkey(my_session->uid,32); } } } if (err_code == AMQP_STATUS_OK){ if(modutil_extract_SQL(queue, &ptr, &length)){ my_session->was_query = 1; prop._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG | AMQP_BASIC_MESSAGE_ID_FLAG | AMQP_BASIC_CORRELATION_ID_FLAG; prop.content_type = amqp_cstring_bytes("text/plain"); prop.delivery_mode = AMQP_DELIVERY_PERSISTENT; prop.correlation_id = amqp_cstring_bytes(my_session->uid); prop.message_id = amqp_cstring_bytes("query"); memset(t_buf,0,128); sprintf(t_buf, "%lu|",(unsigned long)time(NULL)); int qlen = length + strnlen(t_buf,128); if((combined = malloc((qlen+1)*sizeof(char))) == NULL){ skygw_log_write_flush(LOGFILE_ERROR, "Error : Out of memory"); } strcpy(combined,t_buf); strncat(combined,ptr,length); if((err_code = amqp_basic_publish(my_session->conn,my_session->channel, amqp_cstring_bytes(my_instance->exchange), amqp_cstring_bytes(my_instance->key), 0,0,&prop,amqp_cstring_bytes(combined)) ) != AMQP_STATUS_OK){ spinlock_acquire(my_instance->rconn_lock); my_instance->conn_stat = err_code; spinlock_release(my_instance->rconn_lock); skygw_log_write_flush(LOGFILE_ERROR, "Error : Failed to publish message to MQRabbit server: " "%s",amqp_error_string2(err_code)); } } } /** Pass the query downstream */ return my_session->down.routeQuery(my_session->down.instance, my_session->down.session, queue); }