Example #1
0
/**
 * 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;
}
Example #3
0
/**
 * 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;
}