mirror of
https://github.com/MariaDB/server.git
synced 2025-08-21 16:03:24 +03:00
MWL#192: Non-blocking client API for libmysqlclient.
All client functions that can block on I/O have alternate _start() and _cont() versions that do not block but return control back to the application, which can then issue I/O wait in its own fashion and later call back into the library to continue the operation. Works behind the scenes by spawning a co-routine/fiber to run the blocking operation and suspend it while waiting for I/O. This co-routine/fiber use is invisible to applications. For i368/x86_64 on GCC, uses very fast assembler co-routine support. On Windows uses native Win32 Fibers. Falls back to POSIX ucontext on other platforms. Assembler routines for more platforms are relatively easy to add by extending mysys/my_context.c, eg. similar to the Lua lcoco library. For testing, mysqltest and mysql_client_test are extended with the option --non-blocking-api. This causes the programs to use the non-blocking API for database access. mysql-test-run.pl has a similar option --non-blocking-api that uses this, as well as additional testcases. An example program tests/async_queries.c is included that uses the new non-blocking API with libevent to show how, in a single-threaded program, to issue many queries in parallel against a database. client/async_example.c: Fix const warning ****** Fix bug with wrong timeout value for poll(). include/Makefile.am: Fix missing include for `make dist` include/mysql.h: Add prototypes for all non-blocking API calls. include/mysql.h.pp: Add prototypes for all non-blocking API calls. mysys/my_context.c: Fix type warning for makecontext() function pointer argument. sql-common/mysql_async.c: Fix crashes in the non-blocking API for functions that can take MYSQL argument that is NULL. tests/Makefile.am: Add header file to `make dist` tests/mysql_client_test.c: Replace blocking calls with wrappers around the non-blocking calls, used in mysql_client_test to test the new non-blocking API. tests/nonblock-wrappers.h: Replace blocking calls with wrappers around the non-blocking calls, used in mysql_client_test to test the new non-blocking API.
This commit is contained in:
@@ -318,6 +318,7 @@ typedef struct character_set
|
||||
} MY_CHARSET_INFO;
|
||||
struct st_mysql_methods;
|
||||
struct st_mysql_stmt;
|
||||
struct st_mysql_extension;
|
||||
typedef struct st_mysql
|
||||
{
|
||||
NET net;
|
||||
@@ -353,7 +354,7 @@ typedef struct st_mysql
|
||||
void *thd;
|
||||
my_bool *unbuffered_fetch_owner;
|
||||
char *info_buffer;
|
||||
void *extension;
|
||||
struct st_mysql_extension *extension;
|
||||
} MYSQL;
|
||||
typedef struct st_mysql_res {
|
||||
my_ulonglong row_count;
|
||||
@@ -391,6 +392,12 @@ typedef struct st_mysql_parameters
|
||||
unsigned long *p_net_buffer_length;
|
||||
void *extension;
|
||||
} MYSQL_PARAMETERS;
|
||||
typedef enum {
|
||||
MYSQL_WAIT_READ= 1,
|
||||
MYSQL_WAIT_WRITE= 2,
|
||||
MYSQL_WAIT_EXCEPT= 4,
|
||||
MYSQL_WAIT_TIMEOUT= 8
|
||||
} MYSQL_ASYNC_STATUS;
|
||||
int mysql_server_init(int argc, char **argv, char **groups);
|
||||
void mysql_server_end(void);
|
||||
MYSQL_PARAMETERS * mysql_get_parameters(void);
|
||||
@@ -415,6 +422,10 @@ const char * mysql_info(MYSQL *mysql);
|
||||
unsigned long mysql_thread_id(MYSQL *mysql);
|
||||
const char * mysql_character_set_name(MYSQL *mysql);
|
||||
int mysql_set_character_set(MYSQL *mysql, const char *csname);
|
||||
int mysql_set_character_set_start(int *ret, MYSQL *mysql,
|
||||
const char *csname);
|
||||
int mysql_set_character_set_cont(int *ret, MYSQL *mysql,
|
||||
int status);
|
||||
MYSQL * mysql_init(MYSQL *mysql);
|
||||
my_bool mysql_ssl_set(MYSQL *mysql, const char *key,
|
||||
const char *cert, const char *ca,
|
||||
@@ -422,6 +433,12 @@ my_bool mysql_ssl_set(MYSQL *mysql, const char *key,
|
||||
const char * mysql_get_ssl_cipher(MYSQL *mysql);
|
||||
my_bool mysql_change_user(MYSQL *mysql, const char *user,
|
||||
const char *passwd, const char *db);
|
||||
int mysql_change_user_start(my_bool *ret, MYSQL *mysql,
|
||||
const char *user,
|
||||
const char *passwd,
|
||||
const char *db);
|
||||
int mysql_change_user_cont(my_bool *ret, MYSQL *mysql,
|
||||
int status);
|
||||
MYSQL * mysql_real_connect(MYSQL *mysql, const char *host,
|
||||
const char *user,
|
||||
const char *passwd,
|
||||
@@ -429,13 +446,44 @@ MYSQL * mysql_real_connect(MYSQL *mysql, const char *host,
|
||||
unsigned int port,
|
||||
const char *unix_socket,
|
||||
unsigned long clientflag);
|
||||
int mysql_real_connect_start(MYSQL **ret, MYSQL *mysql,
|
||||
const char *host,
|
||||
const char *user,
|
||||
const char *passwd,
|
||||
const char *db,
|
||||
unsigned int port,
|
||||
const char *unix_socket,
|
||||
unsigned long clientflag);
|
||||
int mysql_real_connect_cont(MYSQL **ret, MYSQL *mysql,
|
||||
int status);
|
||||
int mysql_select_db(MYSQL *mysql, const char *db);
|
||||
int mysql_select_db_start(int *ret, MYSQL *mysql,
|
||||
const char *db);
|
||||
int mysql_select_db_cont(int *ret, MYSQL *mysql,
|
||||
int status);
|
||||
int mysql_query(MYSQL *mysql, const char *q);
|
||||
int mysql_query_start(int *ret, MYSQL *mysql,
|
||||
const char *q);
|
||||
int mysql_query_cont(int *ret, MYSQL *mysql,
|
||||
int status);
|
||||
int mysql_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
int mysql_send_query_start(int *ret, MYSQL *mysql,
|
||||
const char *q,
|
||||
unsigned long length);
|
||||
int mysql_send_query_cont(int *ret, MYSQL *mysql,
|
||||
int status);
|
||||
int mysql_real_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
int mysql_real_query_start(int *ret, MYSQL *mysql,
|
||||
const char *q,
|
||||
unsigned long length);
|
||||
int mysql_real_query_cont(int *ret, MYSQL *mysql,
|
||||
int status);
|
||||
MYSQL_RES * mysql_store_result(MYSQL *mysql);
|
||||
int mysql_store_result_start(MYSQL_RES **ret, MYSQL *mysql);
|
||||
int mysql_store_result_cont(MYSQL_RES **ret, MYSQL *mysql,
|
||||
int status);
|
||||
MYSQL_RES * mysql_use_result(MYSQL *mysql);
|
||||
my_bool mysql_master_query(MYSQL *mysql, const char *q,
|
||||
unsigned long length);
|
||||
@@ -478,15 +526,39 @@ int mysql_add_slave(MYSQL* mysql, const char* host,
|
||||
int mysql_shutdown(MYSQL *mysql,
|
||||
enum mysql_enum_shutdown_level
|
||||
shutdown_level);
|
||||
int mysql_shutdown_start(int *ret, MYSQL *mysql,
|
||||
enum mysql_enum_shutdown_level
|
||||
shutdown_level);
|
||||
int mysql_shutdown_cont(int *ret, MYSQL *mysql,
|
||||
int status);
|
||||
int mysql_dump_debug_info(MYSQL *mysql);
|
||||
int mysql_dump_debug_info_start(int *ret, MYSQL *mysql);
|
||||
int mysql_dump_debug_info_cont(int *ret, MYSQL *mysql,
|
||||
int status);
|
||||
int mysql_refresh(MYSQL *mysql,
|
||||
unsigned int refresh_options);
|
||||
int mysql_refresh_start(int *ret, MYSQL *mysql,
|
||||
unsigned int refresh_options);
|
||||
int mysql_refresh_cont(int *ret, MYSQL *mysql, int status);
|
||||
int mysql_kill(MYSQL *mysql,unsigned long pid);
|
||||
int mysql_kill_start(int *ret, MYSQL *mysql,
|
||||
unsigned long pid);
|
||||
int mysql_kill_cont(int *ret, MYSQL *mysql, int status);
|
||||
int mysql_set_server_option(MYSQL *mysql,
|
||||
enum enum_mysql_set_option
|
||||
option);
|
||||
int mysql_set_server_option_start(int *ret, MYSQL *mysql,
|
||||
enum enum_mysql_set_option
|
||||
option);
|
||||
int mysql_set_server_option_cont(int *ret, MYSQL *mysql,
|
||||
int status);
|
||||
int mysql_ping(MYSQL *mysql);
|
||||
int mysql_ping_start(int *ret, MYSQL *mysql);
|
||||
int mysql_ping_cont(int *ret, MYSQL *mysql, int status);
|
||||
const char * mysql_stat(MYSQL *mysql);
|
||||
int mysql_stat_start(const char **ret, MYSQL *mysql);
|
||||
int mysql_stat_cont(const char **ret, MYSQL *mysql,
|
||||
int status);
|
||||
const char * mysql_get_server_info(MYSQL *mysql);
|
||||
const char * mysql_get_server_name(MYSQL *mysql);
|
||||
const char * mysql_get_client_info(void);
|
||||
@@ -495,11 +567,25 @@ const char * mysql_get_host_info(MYSQL *mysql);
|
||||
unsigned long mysql_get_server_version(MYSQL *mysql);
|
||||
unsigned int mysql_get_proto_info(MYSQL *mysql);
|
||||
MYSQL_RES * mysql_list_dbs(MYSQL *mysql,const char *wild);
|
||||
int mysql_list_dbs_start(MYSQL_RES **ret, MYSQL *mysql,
|
||||
const char *wild);
|
||||
int mysql_list_dbs_cont(MYSQL_RES **ret, MYSQL *mysql,
|
||||
int status);
|
||||
MYSQL_RES * mysql_list_tables(MYSQL *mysql,const char *wild);
|
||||
int mysql_list_tables_start(MYSQL_RES **ret, MYSQL *mysql,
|
||||
const char *wild);
|
||||
int mysql_list_tables_cont(MYSQL_RES **ret, MYSQL *mysql,
|
||||
int status);
|
||||
MYSQL_RES * mysql_list_processes(MYSQL *mysql);
|
||||
int mysql_list_processes_start(MYSQL_RES **ret,
|
||||
MYSQL *mysql);
|
||||
int mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql,
|
||||
int status);
|
||||
int mysql_options(MYSQL *mysql,enum mysql_option option,
|
||||
const void *arg);
|
||||
void mysql_free_result(MYSQL_RES *result);
|
||||
int mysql_free_result_start(MYSQL_RES *result);
|
||||
int mysql_free_result_cont(MYSQL_RES *result, int status);
|
||||
void mysql_data_seek(MYSQL_RES *result,
|
||||
my_ulonglong offset);
|
||||
MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result,
|
||||
@@ -507,10 +593,19 @@ MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result,
|
||||
MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result,
|
||||
MYSQL_FIELD_OFFSET offset);
|
||||
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
|
||||
int mysql_fetch_row_start(MYSQL_ROW *ret,
|
||||
MYSQL_RES *result);
|
||||
int mysql_fetch_row_cont(MYSQL_ROW *ret, MYSQL_RES *result,
|
||||
int status);
|
||||
unsigned long * mysql_fetch_lengths(MYSQL_RES *result);
|
||||
MYSQL_FIELD * mysql_fetch_field(MYSQL_RES *result);
|
||||
MYSQL_RES * mysql_list_fields(MYSQL *mysql, const char *table,
|
||||
const char *wild);
|
||||
int mysql_list_fields_start(MYSQL_RES **ret, MYSQL *mysql,
|
||||
const char *table,
|
||||
const char *wild);
|
||||
int mysql_list_fields_cont(MYSQL_RES **ret, MYSQL *mysql,
|
||||
int status);
|
||||
unsigned long mysql_escape_string(char *to,const char *from,
|
||||
unsigned long from_length);
|
||||
unsigned long mysql_hex_string(char *to,const char *from,
|
||||
@@ -536,6 +631,10 @@ int mysql_manager_fetch_line(MYSQL_MANAGER* con,
|
||||
char* res_buf,
|
||||
int res_buf_size);
|
||||
my_bool mysql_read_query_result(MYSQL *mysql);
|
||||
int mysql_read_query_result_start(my_bool *ret,
|
||||
MYSQL *mysql);
|
||||
int mysql_read_query_result_cont(my_bool *ret,
|
||||
MYSQL *mysql, int status);
|
||||
enum enum_mysql_stmt_state
|
||||
{
|
||||
MYSQL_STMT_INIT_DONE= 1, MYSQL_STMT_PREPARE_DONE, MYSQL_STMT_EXECUTE_DONE,
|
||||
@@ -605,12 +704,22 @@ enum enum_stmt_attr_type
|
||||
MYSQL_STMT * mysql_stmt_init(MYSQL *mysql);
|
||||
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
|
||||
unsigned long length);
|
||||
int mysql_stmt_prepare_start(int *ret, MYSQL_STMT *stmt,
|
||||
const char *query, unsigned long length);
|
||||
int mysql_stmt_prepare_cont(int *ret, MYSQL_STMT *stmt, int status);
|
||||
int mysql_stmt_execute(MYSQL_STMT *stmt);
|
||||
int mysql_stmt_execute_start(int *ret, MYSQL_STMT *stmt);
|
||||
int mysql_stmt_execute_cont(int *ret, MYSQL_STMT *stmt, int status);
|
||||
int mysql_stmt_fetch(MYSQL_STMT *stmt);
|
||||
int mysql_stmt_fetch_start(int *ret, MYSQL_STMT *stmt);
|
||||
int mysql_stmt_fetch_cont(int *ret, MYSQL_STMT *stmt, int status);
|
||||
int mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg,
|
||||
unsigned int column,
|
||||
unsigned long offset);
|
||||
int mysql_stmt_store_result(MYSQL_STMT *stmt);
|
||||
int mysql_stmt_store_result_start(int *ret, MYSQL_STMT *stmt);
|
||||
int mysql_stmt_store_result_cont(int *ret, MYSQL_STMT *stmt,
|
||||
int status);
|
||||
unsigned long mysql_stmt_param_count(MYSQL_STMT * stmt);
|
||||
my_bool mysql_stmt_attr_set(MYSQL_STMT *stmt,
|
||||
enum enum_stmt_attr_type attr_type,
|
||||
@@ -621,12 +730,25 @@ my_bool mysql_stmt_attr_get(MYSQL_STMT *stmt,
|
||||
my_bool mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
|
||||
my_bool mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
|
||||
my_bool mysql_stmt_close(MYSQL_STMT * stmt);
|
||||
int mysql_stmt_close_start(my_bool *ret, MYSQL_STMT *stmt);
|
||||
int mysql_stmt_close_cont(my_bool *ret, MYSQL_STMT * stmt, int status);
|
||||
my_bool mysql_stmt_reset(MYSQL_STMT * stmt);
|
||||
int mysql_stmt_reset_start(my_bool *ret, MYSQL_STMT * stmt);
|
||||
int mysql_stmt_reset_cont(my_bool *ret, MYSQL_STMT *stmt, int status);
|
||||
my_bool mysql_stmt_free_result(MYSQL_STMT *stmt);
|
||||
int mysql_stmt_free_result_start(my_bool *ret, MYSQL_STMT *stmt);
|
||||
int mysql_stmt_free_result_cont(my_bool *ret, MYSQL_STMT *stmt,
|
||||
int status);
|
||||
my_bool mysql_stmt_send_long_data(MYSQL_STMT *stmt,
|
||||
unsigned int param_number,
|
||||
const char *data,
|
||||
unsigned long length);
|
||||
int mysql_stmt_send_long_data_start(my_bool *ret, MYSQL_STMT *stmt,
|
||||
unsigned int param_number,
|
||||
const char *data,
|
||||
unsigned long len);
|
||||
int mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt,
|
||||
int status);
|
||||
MYSQL_RES * mysql_stmt_result_metadata(MYSQL_STMT *stmt);
|
||||
MYSQL_RES * mysql_stmt_param_metadata(MYSQL_STMT *stmt);
|
||||
unsigned int mysql_stmt_errno(MYSQL_STMT * stmt);
|
||||
@@ -641,8 +763,21 @@ my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt);
|
||||
my_ulonglong mysql_stmt_insert_id(MYSQL_STMT *stmt);
|
||||
unsigned int mysql_stmt_field_count(MYSQL_STMT *stmt);
|
||||
my_bool mysql_commit(MYSQL * mysql);
|
||||
int mysql_commit_start(my_bool *ret, MYSQL * mysql);
|
||||
int mysql_commit_cont(my_bool *ret, MYSQL * mysql, int status);
|
||||
my_bool mysql_rollback(MYSQL * mysql);
|
||||
int mysql_rollback_start(my_bool *ret, MYSQL * mysql);
|
||||
int mysql_rollback_cont(my_bool *ret, MYSQL * mysql, int status);
|
||||
my_bool mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
|
||||
int mysql_autocommit_start(my_bool *ret, MYSQL * mysql,
|
||||
my_bool auto_mode);
|
||||
int mysql_autocommit_cont(my_bool *ret, MYSQL * mysql, int status);
|
||||
my_bool mysql_more_results(MYSQL *mysql);
|
||||
int mysql_next_result(MYSQL *mysql);
|
||||
int mysql_next_result_start(int *ret, MYSQL *mysql);
|
||||
int mysql_next_result_cont(int *ret, MYSQL *mysql, int status);
|
||||
void mysql_close(MYSQL *sock);
|
||||
int mysql_close_start(MYSQL *sock);
|
||||
int mysql_close_cont(MYSQL *sock, int status);
|
||||
my_socket mysql_get_socket(const MYSQL *mysql);
|
||||
unsigned int mysql_get_timeout_value(const MYSQL *mysql);
|
||||
|
Reference in New Issue
Block a user