/** * We have data from the client, this is a SQL command, or other MySQL * packet type. * * @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 execute(ROUTER *rinstance, void *router_session, GWBUF *queue) { INFO_INSTANCE *instance = (INFO_INSTANCE *)rinstance; INFO_SESSION *session = (INFO_SESSION *)router_session; uint8_t *data; int length, len, residual; char *sql; if (GWBUF_TYPE(queue) == GWBUF_TYPE_HTTP) { return handle_url(instance, session, queue); } if (session->queue) { queue = gwbuf_append(session->queue, queue); session->queue = NULL; queue = gwbuf_make_contiguous(queue); } data = (uint8_t *)GWBUF_DATA(queue); length = data[0] + (data[1] << 8) + (data[2] << 16); if (length + 4 > GWBUF_LENGTH(queue)) { // Incomplete packet, must be buffered session->queue = queue; return 1; } // We have a complete request in a signle buffer if (modutil_MySQL_Query(queue, &sql, &len, &residual)) { sql = strndup(sql, len); int rc = maxinfo_execute_query(instance, session, sql); free(sql); return rc; } else { switch (MYSQL_COMMAND(queue)) { case COM_PING: return maxinfo_ping(instance, session, queue); case COM_STATISTICS: return maxinfo_statistics(instance, session, queue); default: MXS_ERROR("maxinfo: Unexpected MySQL command 0x%x", MYSQL_COMMAND(queue)); } } return 1; }
int mysql_dissect_query(mysql_session* sess, half_stream* stream){ /* * expect the next packet to be the result of the query, however * if the query is too long to send at once, the next packet * will still come from client. * In that case we should get the mysql packet length according to its protocol * and if we haven't get the whole packet, we just ignore this notification * and wait for next. */ if(!mysql_dissect_is_complete(stream, sess)){ query_info_t* info = sess->query_info; DEBUG_ASSERT(info != NULL); /* first incomplete request packet */ if(info->query_start.tv_sec == 0){ gettimeofday(&info->query_start, NULL); } sess->handled_len = 0; return STREAM_DISCARD; } char* client_msg = PACKET_MSG(stream->data); int pkt_len = PACKET_LEN(stream->data); DEBUG_ASSERT(pkt_len >= 1); char cmd = MYSQL_COMMAND(client_msg); int ret; ret = mysql_handle_client_cmd(sess, cmd, pkt_len - MYSQL_COMMAND_LEN, client_msg + MYSQL_COMMAND_LEN); return ret; }
/** * Process a request packet from the slave server. * * The router can handle a limited subset of requests from the slave, these * include a subset of general SQL queries, a slave registeration command and * the binlog dump command. * * The strategy for responding to these commands is to use caches responses * for the the same commands that have previously been made to the real master * if this is possible, if it is not then the router itself will synthesize a * response. * * @param router The router instance this defines the master for this replication chain * @param slave The slave specific data * @param queue The incoming request packet */ int blr_slave_request(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue) { if (slave->state < 0 || slave->state > BLRS_MAXSTATE) { LOGIF(LE, (skygw_log_write( LOGFILE_ERROR, "Invalid slave state machine state (%d) for binlog router.", slave->state))); gwbuf_consume(queue, gwbuf_length(queue)); return 0; } slave->stats.n_requests++; switch (MYSQL_COMMAND(queue)) { case COM_QUERY: return blr_slave_query(router, slave, queue); break; case COM_REGISTER_SLAVE: return blr_slave_register(router, slave, queue); break; case COM_BINLOG_DUMP: return blr_slave_binlog_dump(router, slave, queue); break; case COM_STATISTICS: return blr_statistics(router, slave, queue); break; case COM_PING: return blr_ping(router, slave, queue); break; case COM_QUIT: LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG, "COM_QUIT received from slave with server_id %d", slave->serverid))); break; default: blr_send_custom_error(slave->dcb, 1, 0, "MySQL command not supported by the binlog router."); LOGIF(LE, (skygw_log_write( LOGFILE_ERROR, "Unexpected MySQL Command (%d) received from slave", MYSQL_COMMAND(queue)))); break; } return 0; }