示例#1
0
MDB_ASYNC_ST MySQL_Connection::handler(short event) {
	if (mysql==NULL) {
		// it is the first time handler() is being called
		async_state_machine=ASYNC_CONNECT_START;
		myds->wait_until=myds->sess->thread->curtime+mysql_thread___connect_timeout_server*1000;
	}
handler_again:
	proxy_debug(PROXY_DEBUG_MYSQL_PROTOCOL, 6,"async_state_machine=%d\n", async_state_machine);
	switch (async_state_machine) {
		case ASYNC_CONNECT_START:
			connect_start();
			if (async_exit_status) {
				next_event(ASYNC_CONNECT_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_CONNECT_END);
			}
			break;
		case ASYNC_CONNECT_CONT:
			if (event) {
				connect_cont(event);
			}
			if (async_exit_status) {
					if (myds->sess->thread->curtime >= myds->wait_until) {
						NEXT_IMMEDIATE(ASYNC_CONNECT_TIMEOUT);
					}
      	next_event(ASYNC_CONNECT_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_CONNECT_END);
			}
    break;
			break;
		case ASYNC_CONNECT_END:
			if (!ret_mysql) {
				// always increase the counter
				proxy_error("Failed to mysql_real_connect() on %s:%d , %d: %s\n", parent->address, parent->port, mysql_errno(mysql), mysql_error(mysql));
    		NEXT_IMMEDIATE(ASYNC_CONNECT_FAILED);
			} else {
    		NEXT_IMMEDIATE(ASYNC_CONNECT_SUCCESSFUL);
			}
    	break;
		case ASYNC_CONNECT_SUCCESSFUL:
			__sync_fetch_and_add(&MyHGM->status.server_connections_connected,1);
			__sync_fetch_and_add(&parent->connect_OK,1);
			break;
		case ASYNC_CONNECT_FAILED:
			parent->connect_error(mysql_errno(mysql));
			break;
		case ASYNC_CONNECT_TIMEOUT:
			proxy_error("Connect timeout on %s:%d : %llu - %llu = %llu\n",  parent->address, parent->port, myds->sess->thread->curtime , myds->wait_until, myds->sess->thread->curtime - myds->wait_until);
			parent->connect_error(mysql_errno(mysql));
			break;
		case ASYNC_CHANGE_USER_START:
			change_user_start();
			if (async_exit_status) {
				next_event(ASYNC_CHANGE_USER_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_CHANGE_USER_END);
			}
			break;
		case ASYNC_CHANGE_USER_CONT:
			assert(myds->sess->status==CHANGING_USER_SERVER);
			change_user_cont(event);
			if (async_exit_status) {
				next_event(ASYNC_CHANGE_USER_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_CHANGE_USER_END);
			}
			break;
		case ASYNC_CHANGE_USER_END:
			if (ret_bool) {
				fprintf(stderr,"Failed to mysql_change_user()");
				NEXT_IMMEDIATE(ASYNC_CHANGE_USER_FAILED);
			} else {
				NEXT_IMMEDIATE(ASYNC_CHANGE_USER_SUCCESSFUL);
			}
			break;
		case ASYNC_CHANGE_USER_SUCCESSFUL:
			break;
		case ASYNC_CHANGE_USER_FAILED:
			break;
		case ASYNC_PING_START:
			ping_start();
			if (async_exit_status) {
				next_event(ASYNC_PING_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_PING_END);
			}
			break;
		case ASYNC_PING_CONT:
			assert(myds->sess->status==PINGING_SERVER);
			ping_cont(event);
			if (async_exit_status) {
				next_event(ASYNC_PING_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_PING_END);
			}
			break;
		case ASYNC_PING_END:
			if (interr) {
				NEXT_IMMEDIATE(ASYNC_PING_FAILED);
			} else {
				NEXT_IMMEDIATE(ASYNC_PING_SUCCESSFUL);
			}
			break;
		case ASYNC_PING_SUCCESSFUL:
			break;
		case ASYNC_PING_FAILED:
			break;
		case ASYNC_QUERY_START:
			real_query_start();
			__sync_fetch_and_add(&parent->queries_sent,1);
			__sync_fetch_and_add(&parent->bytes_sent,query.length);
			myds->sess->thread->status_variables.queries_backends_bytes_sent+=query.length;
			if (async_exit_status) {
				next_event(ASYNC_QUERY_CONT);
			} else {
#ifdef PROXYSQL_USE_RESULT
				NEXT_IMMEDIATE(ASYNC_USE_RESULT_START);
#else
				NEXT_IMMEDIATE(ASYNC_STORE_RESULT_START);
#endif
			}
			break;
		case ASYNC_QUERY_CONT:
			real_query_cont(event);
			if (async_exit_status) {
				next_event(ASYNC_QUERY_CONT);
			} else {
#ifdef PROXYSQL_USE_RESULT
				NEXT_IMMEDIATE(ASYNC_USE_RESULT_START);
#else
				NEXT_IMMEDIATE(ASYNC_STORE_RESULT_START);
#endif
			}
			break;
		case ASYNC_STORE_RESULT_START:
			if (mysql_errno(mysql)) {
				NEXT_IMMEDIATE(ASYNC_QUERY_END);
			}
			store_result_start();
			if (async_exit_status) {
				next_event(ASYNC_STORE_RESULT_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_QUERY_END);
			}
			break;
		case ASYNC_STORE_RESULT_CONT:
			store_result_cont(event);
			if (async_exit_status) {
				next_event(ASYNC_STORE_RESULT_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_QUERY_END);
			}
			break;
		case ASYNC_USE_RESULT_START:
			if (mysql_errno(mysql)) {
				NEXT_IMMEDIATE(ASYNC_QUERY_END);
			}
			mysql_result=mysql_use_result(mysql);
			if (mysql_result==NULL) {
				NEXT_IMMEDIATE(ASYNC_QUERY_END);
			} else {
				MyRS=new MySQL_ResultSet(&myds->sess->client_myds->myprot, mysql_result, mysql);
				async_fetch_row_start=false;
				NEXT_IMMEDIATE(ASYNC_USE_RESULT_CONT);
			}
			break;
		case ASYNC_USE_RESULT_CONT:
			if (async_fetch_row_start==false) {
				async_exit_status=mysql_fetch_row_start(&mysql_row,mysql_result);
				async_fetch_row_start=true;
			} else {
				async_exit_status=mysql_fetch_row_cont(&mysql_row,mysql_result, mysql_status(event, true));
			}
			if (async_exit_status) {
				next_event(ASYNC_USE_RESULT_CONT);
			} else {
				async_fetch_row_start=false;
				if (mysql_row) {
					unsigned int br=MyRS->add_row(mysql_row);
					__sync_fetch_and_add(&parent->bytes_recv,br);
					myds->sess->thread->status_variables.queries_backends_bytes_recv+=br;
					NEXT_IMMEDIATE(ASYNC_USE_RESULT_CONT);
				} else {
					MyRS->add_eof();
					NEXT_IMMEDIATE(ASYNC_QUERY_END);
				}
			}
			break;
		case ASYNC_QUERY_END:
			break;
		case ASYNC_SET_AUTOCOMMIT_START:
			set_autocommit_start();
			if (async_exit_status) {
				next_event(ASYNC_SET_AUTOCOMMIT_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_SET_AUTOCOMMIT_END);
			}
			break;
		case ASYNC_SET_AUTOCOMMIT_CONT:
			set_autocommit_cont(event);
			if (async_exit_status) {
				next_event(ASYNC_SET_AUTOCOMMIT_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_SET_AUTOCOMMIT_END);
			}
			break;
		case ASYNC_SET_AUTOCOMMIT_END:
			if (ret_bool) {
				NEXT_IMMEDIATE(ASYNC_SET_AUTOCOMMIT_FAILED);
			} else {
				NEXT_IMMEDIATE(ASYNC_SET_AUTOCOMMIT_SUCCESSFUL);
			}
			break;
		case ASYNC_SET_AUTOCOMMIT_SUCCESSFUL:
			break;
		case ASYNC_SET_AUTOCOMMIT_FAILED:
			fprintf(stderr,"%s\n",mysql_error(mysql));
			break;
		case ASYNC_SET_NAMES_START:
			set_names_start();
			if (async_exit_status) {
				next_event(ASYNC_SET_NAMES_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_SET_NAMES_END);
			}
			break;
		case ASYNC_SET_NAMES_CONT:
			set_names_cont(event);
			if (async_exit_status) {
				next_event(ASYNC_SET_NAMES_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_SET_NAMES_END);
			}
			break;
		case ASYNC_SET_NAMES_END:
			if (interr) {
				NEXT_IMMEDIATE(ASYNC_SET_NAMES_FAILED);
			} else {
				NEXT_IMMEDIATE(ASYNC_SET_NAMES_SUCCESSFUL);
			}
			break;
		case ASYNC_SET_NAMES_SUCCESSFUL:
			break;
		case ASYNC_SET_NAMES_FAILED:
			fprintf(stderr,"%s\n",mysql_error(mysql));
			break;
		case ASYNC_INITDB_START:
			initdb_start();
			if (async_exit_status) {
				next_event(ASYNC_INITDB_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_INITDB_END);
			}
			break;
		case ASYNC_INITDB_CONT:
			initdb_cont(event);
			if (async_exit_status) {
				next_event(ASYNC_INITDB_CONT);
			} else {
				NEXT_IMMEDIATE(ASYNC_INITDB_END);
			}
			break;
		case ASYNC_INITDB_END:
			if (interr) {
				NEXT_IMMEDIATE(ASYNC_INITDB_FAILED);
			} else {
				NEXT_IMMEDIATE(ASYNC_INITDB_SUCCESSFUL);
			}
			break;
		case ASYNC_INITDB_SUCCESSFUL:
			break;
		case ASYNC_INITDB_FAILED:
			fprintf(stderr,"%s\n",mysql_error(mysql));
			break;
		default:
			assert(0); //we should never reach here
			break;
		}
	return async_state_machine;
}
示例#2
0
static void
state_machine_handler(int fd __attribute__((unused)), short event, void *arg)
{
  struct state_data *sd= arg;
  int status;

again:
  switch(sd->ST)
  {
  case 0:
    /* Initial state, start making the connection. */
    status= mysql_real_connect_start(&sd->ret, &sd->mysql, opt_host, opt_user, opt_password, opt_db, opt_port, opt_socket, 0);
    if (status)
      /* Wait for connect to complete. */
      next_event(1, status, sd);
    else
      NEXT_IMMEDIATE(sd, 9);
    break;

  case 1:
    status= mysql_real_connect_cont(&sd->ret, &sd->mysql, mysql_status(event));
    if (status)
      next_event(1, status, sd);
    else
      NEXT_IMMEDIATE(sd, 9);
    break;

  case 9:
    if (!sd->ret)
      fatal(sd, "Failed to mysql_real_connect()");
    NEXT_IMMEDIATE(sd, 10);
    break;

  case 10:
    /* Now run the next query. */
    sd->query_element= query_list;
    if (!sd->query_element)
    {
      /* No more queries, end the connection. */
      NEXT_IMMEDIATE(sd, 40);
    }
    query_list= query_list->next;

    sd->index= sd->query_element->index;
    printf("%d ! %s\n", sd->index, sd->query_element->query);
    status= mysql_real_query_start(&sd->err, &sd->mysql, sd->query_element->query,
                                   strlen(sd->query_element->query));
    if (status)
      next_event(11, status, sd);
    else
      NEXT_IMMEDIATE(sd, 20);
    break;

  case 11:
    status= mysql_real_query_cont(&sd->err, &sd->mysql, mysql_status(event));
    if (status)
      next_event(11, status, sd);
    else
      NEXT_IMMEDIATE(sd, 20);
    break;

  case 20:
    my_free(sd->query_element->query);
    my_free(sd->query_element);
    if (sd->err)
    {
      printf("%d | Error: %s\n", sd->index, mysql_error(&sd->mysql));
      NEXT_IMMEDIATE(sd, 10);
    }
    else
    {
      sd->result= mysql_use_result(&sd->mysql);
      if (!sd->result)
        fatal(sd, "mysql_use_result() returns error");
      NEXT_IMMEDIATE(sd, 30);
    }
    break;

  case 30:
    status= mysql_fetch_row_start(&sd->row, sd->result);
    if (status)
      next_event(31, status, sd);
    else
      NEXT_IMMEDIATE(sd, 39);
    break;

  case 31:
    status= mysql_fetch_row_cont(&sd->row, sd->result, mysql_status(event));
    if (status)
      next_event(31, status, sd);
    else
      NEXT_IMMEDIATE(sd, 39);
    break;

  case 39:
    if (sd->row)
    {
      /* Got a row. */
      unsigned int i;
      printf("%d - ", sd->index);
      for (i= 0; i < mysql_num_fields(sd->result); i++)
        printf("%s%s", (i ? "\t" : ""), (sd->row[i] ? sd->row[i] : "(null)"));
      printf ("\n");
      NEXT_IMMEDIATE(sd, 30);
    }
    else
    {
      if (mysql_errno(&sd->mysql))
      {
        /* An error occured. */
        printf("%d | Error: %s\n", sd->index, mysql_error(&sd->mysql));
      }
      else
      {
        /* EOF. */
        printf("%d | EOF\n", sd->index);
      }
      mysql_free_result(sd->result);
      NEXT_IMMEDIATE(sd, 10);
    }
    break;

  case 40:
    status= mysql_close_start(&sd->mysql);
    if (status)
      next_event(41, status, sd);
    else
      NEXT_IMMEDIATE(sd, 50);
    break;

  case 41:
    status= mysql_close_cont(&sd->mysql, mysql_status(event));
    if (status)
      next_event(41, status, sd);
    else
      NEXT_IMMEDIATE(sd, 50);
    break;

  case 50:
    /* We are done! */
    num_active_connections--;
    if (num_active_connections == 0)
      event_loopbreak();
    break;

  default:
    abort();
  }
}