diff options
author | unknown <knielsen@knielsen-hq.org> | 2011-09-20 12:49:25 +0200 |
---|---|---|
committer | unknown <knielsen@knielsen-hq.org> | 2011-09-20 12:49:25 +0200 |
commit | a5b881594da4258257b18cc42f5ce7be3524e02c (patch) | |
tree | 6ddddaef439cce2f930abfab3929f9ad80d8c818 /include | |
parent | 1a344b87e4d153d52468307cc886b5f424cb2dbf (diff) | |
download | mariadb-git-a5b881594da4258257b18cc42f5ce7be3524e02c.tar.gz |
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.
Diffstat (limited to 'include')
-rw-r--r-- | include/Makefile.am | 2 | ||||
-rw-r--r-- | include/my_context.h | 222 | ||||
-rw-r--r-- | include/my_dbug.h | 2 | ||||
-rw-r--r-- | include/mysql.h | 160 | ||||
-rw-r--r-- | include/mysql.h.pp | 137 | ||||
-rw-r--r-- | include/sql_common.h | 11 | ||||
-rw-r--r-- | include/violite.h | 2 |
7 files changed, 531 insertions, 5 deletions
diff --git a/include/Makefile.am b/include/Makefile.am index e23fd94a7fc..e13e7755670 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -46,7 +46,7 @@ noinst_HEADERS = config-win.h config-netware.h lf.h my_bit.h \ atomic/rwlock.h atomic/x86-gcc.h \ atomic/generic-msvc.h \ atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h \ - wqueue.h waiting_threads.h + wqueue.h waiting_threads.h my_context.h EXTRA_DIST = mysql.h.pp mysql/plugin_auth.h.pp mysql/client_plugin.h.pp CMakeLists.txt diff --git a/include/my_context.h b/include/my_context.h new file mode 100644 index 00000000000..e19ee89a8be --- /dev/null +++ b/include/my_context.h @@ -0,0 +1,222 @@ +/* + Copyright 2011 Kristian Nielsen + + Experiments with non-blocking libmysql. + + This is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + Simple API for spawning a co-routine, to be used for async libmysqlclient. + + Idea is that by implementing this interface using whatever facilities are + available for given platform, we can use the same code for the generic + libmysqlclient-async code. + + (This particular implementation uses Posix ucontext swapcontext().) +*/ + +#ifdef __WIN__ +#define MY_CONTEXT_USE_WIN32_FIBERS 1 +#elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__x86_64__) +#define MY_CONTEXT_USE_X86_64_GCC_ASM +#elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__) +#define MY_CONTEXT_USE_I386_GCC_ASM +#else +#define MY_CONTEXT_USE_UCONTEXT +#endif + +#ifdef MY_CONTEXT_USE_WIN32_FIBERS +struct my_context { + void (*user_func)(void *); + void *user_arg; + void *app_fiber; + void *lib_fiber; + int return_value; +#ifndef DBUG_OFF + void *dbug_state; +#endif +}; +#endif + + +#ifdef MY_CONTEXT_USE_UCONTEXT +#include <ucontext.h> + +struct my_context { + void (*user_func)(void *); + void *user_data; + void *stack; + size_t stack_size; + ucontext_t base_context; + ucontext_t spawned_context; + int active; +#ifdef HAVE_VALGRIND_VALGRIND_H + unsigned int valgrind_stack_id; +#endif +#ifndef DBUG_OFF + void *dbug_state; +#endif +}; +#endif + + +#ifdef MY_CONTEXT_USE_X86_64_GCC_ASM +#include <stdint.h> + +struct my_context { + uint64_t save[9]; + void *stack_top; + void *stack_bot; +#ifdef HAVE_VALGRIND_VALGRIND_H + unsigned int valgrind_stack_id; +#endif +#ifndef DBUG_OFF + void *dbug_state; +#endif +}; +#endif + + +#ifdef MY_CONTEXT_USE_I386_GCC_ASM +#include <stdint.h> + +struct my_context { + uint64_t save[7]; + void *stack_top; + void *stack_bot; +#ifdef HAVE_VALGRIND_VALGRIND_H + unsigned int valgrind_stack_id; +#endif +#ifndef DBUG_OFF + void *dbug_state; +#endif +}; +#endif + + +/* + Initialize an asynchroneous context object. + Returns 0 on success, non-zero on failure. +*/ +extern int my_context_init(struct my_context *c, size_t stack_size); + +/* Free an asynchroneous context object, deallocating any resources used. */ +extern void my_context_destroy(struct my_context *c); + +/* + Spawn an asynchroneous context. The context will run the supplied user + function, passing the supplied user data pointer. + + The context must have been initialised with my_context_init() prior to + this call. + + The user function may call my_context_yield(), which will cause this + function to return 1. Then later my_context_continue() may be called, which + will resume the asynchroneous context by returning from the previous + my_context_yield() call. + + When the user function returns, this function returns 0. + + In case of error, -1 is returned. +*/ +extern int my_context_spawn(struct my_context *c, void (*f)(void *), void *d); + +/* + Suspend an asynchroneous context started with my_context_spawn. + + When my_context_yield() is called, execution immediately returns from the + last my_context_spawn() or my_context_continue() call. Then when later + my_context_continue() is called, execution resumes by returning from this + my_context_yield() call. + + Returns 0 if ok, -1 in case of error. +*/ +extern int my_context_yield(struct my_context *c); + +/* + Resume an asynchroneous context. The context was spawned by + my_context_spawn(), and later suspended inside my_context_yield(). + + The asynchroneous context may be repeatedly suspended with + my_context_yield() and resumed with my_context_continue(). + + Each time it is suspended, this function returns 1. When the originally + spawned user function returns, this function returns 0. + + In case of error, -1 is returned. +*/ +extern int my_context_continue(struct my_context *c); + + +struct mysql_async_context { + /* + This is set to the value that should be returned from foo_start() or + foo_cont() when a call is suspended. + It is also set to the event(s) that triggered when a suspended call is + resumed, eg. whether we woke up due to connection completed or timeout + in mysql_real_connect_cont(). + */ + unsigned int ret_status; + /* + This is set to the result of the whole asynchronous operation when it + completes. It uses a union, as different calls have different return + types. + */ + union { + void *r_ptr; + const void *r_const_ptr; + int r_int; + my_bool r_my_bool; + } ret_result; + /* + The timeout value, for suspended calls that need to wake up on a timeout + (eg. mysql_real_connect_start(). + */ + unsigned int timeout_value; + /* + This flag is set when we are executing inside some asynchronous call + foo_start() or foo_cont(). It is used to decide whether to use the + synchronous or asynchronous version of calls that may block such as + recv(). + + Note that this flag is not set when a call is suspended, eg. after + returning from foo_start() and before re-entering foo_cont(). + */ + my_bool active; + /* + This flag is set when an asynchronous operation is in progress, but + suspended. Ie. it is set when foo_start() or foo_cont() returns because + the operation needs to block, suspending the operation. + + It is used to give an error (rather than crash) if the application + attempts to call some foo_cont() method when no suspended operation foo is + in progress. + */ + my_bool suspended; + /* + If non-NULL, this is a pointer to a callback hook that will be invoked with + the user data argument just before the context is suspended, and just after + it is resumed. + */ + void (*suspend_resume_hook)(my_bool suspend, void *user_data); + void *suspend_resume_hook_user_data; + /* + This is used to save the execution contexts so that we can suspend an + operation and switch back to the application context, to resume the + suspended context later when the application re-invokes us with + foo_cont(). + */ + struct my_context async_context; +}; diff --git a/include/my_dbug.h b/include/my_dbug.h index ef30c95e32a..a58c6588d61 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -83,6 +83,8 @@ extern void _db_lock_file_(void); extern void _db_unlock_file_(void); extern FILE *_db_fp_(void); extern void _db_flush_(); +extern void dbug_swap_code_state(void **code_state_store); +extern void dbug_free_code_state(void **code_state_store); #ifdef __cplusplus diff --git a/include/mysql.h b/include/mysql.h index 19aab89283b..b1ef4720879 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -264,6 +264,8 @@ typedef struct character_set struct st_mysql_methods; struct st_mysql_stmt; +struct st_mysql_extension; + typedef struct st_mysql { NET net; /* Communication parameters */ @@ -318,7 +320,7 @@ typedef struct st_mysql my_bool *unbuffered_fetch_owner; /* needed for embedded server - no net buffer to store the 'info' */ char *info_buffer; - void *extension; + struct st_mysql_extension *extension; } MYSQL; @@ -376,6 +378,19 @@ typedef struct st_mysql_parameters void *extension; } MYSQL_PARAMETERS; +/* + Flag bits, the asynchronous methods return a combination of these ORed + together to let the application know when to resume the suspended operation. +*/ +typedef enum { + MYSQL_WAIT_READ= 1, /* Wait for data to be available on socket to read */ + /* mysql_get_socket_fd() will return socket descriptor*/ + MYSQL_WAIT_WRITE= 2, /* Wait for socket to be ready to write data */ + MYSQL_WAIT_EXCEPT= 4, /* Wait for select() to mark exception on socket */ + MYSQL_WAIT_TIMEOUT= 8 /* Wait until timeout occurs. Value of timeout can be */ + /* obtained from mysql_get_timeout_value() */ +} MYSQL_ASYNC_STATUS; + #if !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY) #define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet) #define net_buffer_length (*mysql_get_parameters()->p_net_buffer_length) @@ -437,6 +452,10 @@ const char * STDCALL mysql_info(MYSQL *mysql); unsigned long STDCALL mysql_thread_id(MYSQL *mysql); const char * STDCALL mysql_character_set_name(MYSQL *mysql); int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname); +int STDCALL mysql_set_character_set_start(int *ret, MYSQL *mysql, + const char *csname); +int STDCALL mysql_set_character_set_cont(int *ret, MYSQL *mysql, + int status); MYSQL * STDCALL mysql_init(MYSQL *mysql); my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, @@ -445,6 +464,12 @@ my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, const char * STDCALL mysql_get_ssl_cipher(MYSQL *mysql); my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, const char *passwd, const char *db); +int STDCALL mysql_change_user_start(my_bool *ret, MYSQL *mysql, + const char *user, + const char *passwd, + const char *db); +int STDCALL mysql_change_user_cont(my_bool *ret, MYSQL *mysql, + int status); MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, @@ -452,13 +477,44 @@ MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host, unsigned int port, const char *unix_socket, unsigned long clientflag); +int STDCALL 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 STDCALL mysql_real_connect_cont(MYSQL **ret, MYSQL *mysql, + int status); int STDCALL mysql_select_db(MYSQL *mysql, const char *db); +int STDCALL mysql_select_db_start(int *ret, MYSQL *mysql, + const char *db); +int STDCALL mysql_select_db_cont(int *ret, MYSQL *mysql, + int status); int STDCALL mysql_query(MYSQL *mysql, const char *q); +int STDCALL mysql_query_start(int *ret, MYSQL *mysql, + const char *q); +int STDCALL mysql_query_cont(int *ret, MYSQL *mysql, + int status); int STDCALL mysql_send_query(MYSQL *mysql, const char *q, unsigned long length); +int STDCALL mysql_send_query_start(int *ret, MYSQL *mysql, + const char *q, + unsigned long length); +int STDCALL mysql_send_query_cont(int *ret, MYSQL *mysql, + int status); int STDCALL mysql_real_query(MYSQL *mysql, const char *q, unsigned long length); +int STDCALL mysql_real_query_start(int *ret, MYSQL *mysql, + const char *q, + unsigned long length); +int STDCALL mysql_real_query_cont(int *ret, MYSQL *mysql, + int status); MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql); +int STDCALL mysql_store_result_start(MYSQL_RES **ret, MYSQL *mysql); +int STDCALL mysql_store_result_cont(MYSQL_RES **ret, MYSQL *mysql, + int status); MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql); /* perform query on master */ @@ -526,15 +582,39 @@ int STDCALL mysql_add_slave(MYSQL* mysql, const char* host, int STDCALL mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level); +int STDCALL mysql_shutdown_start(int *ret, MYSQL *mysql, + enum mysql_enum_shutdown_level + shutdown_level); +int STDCALL mysql_shutdown_cont(int *ret, MYSQL *mysql, + int status); int STDCALL mysql_dump_debug_info(MYSQL *mysql); +int STDCALL mysql_dump_debug_info_start(int *ret, MYSQL *mysql); +int STDCALL mysql_dump_debug_info_cont(int *ret, MYSQL *mysql, + int status); int STDCALL mysql_refresh(MYSQL *mysql, unsigned int refresh_options); +int STDCALL mysql_refresh_start(int *ret, MYSQL *mysql, + unsigned int refresh_options); +int STDCALL mysql_refresh_cont(int *ret, MYSQL *mysql, int status); int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid); +int STDCALL mysql_kill_start(int *ret, MYSQL *mysql, + unsigned long pid); +int STDCALL mysql_kill_cont(int *ret, MYSQL *mysql, int status); int STDCALL mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option); +int STDCALL mysql_set_server_option_start(int *ret, MYSQL *mysql, + enum enum_mysql_set_option + option); +int STDCALL mysql_set_server_option_cont(int *ret, MYSQL *mysql, + int status); int STDCALL mysql_ping(MYSQL *mysql); +int STDCALL mysql_ping_start(int *ret, MYSQL *mysql); +int STDCALL mysql_ping_cont(int *ret, MYSQL *mysql, int status); const char * STDCALL mysql_stat(MYSQL *mysql); +int STDCALL mysql_stat_start(const char **ret, MYSQL *mysql); +int STDCALL mysql_stat_cont(const char **ret, MYSQL *mysql, + int status); const char * STDCALL mysql_get_server_info(MYSQL *mysql); const char * STDCALL mysql_get_server_name(MYSQL *mysql); const char * STDCALL mysql_get_client_info(void); @@ -543,11 +623,25 @@ const char * STDCALL mysql_get_host_info(MYSQL *mysql); unsigned long STDCALL mysql_get_server_version(MYSQL *mysql); unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql); MYSQL_RES * STDCALL mysql_list_dbs(MYSQL *mysql,const char *wild); +int STDCALL mysql_list_dbs_start(MYSQL_RES **ret, MYSQL *mysql, + const char *wild); +int STDCALL mysql_list_dbs_cont(MYSQL_RES **ret, MYSQL *mysql, + int status); MYSQL_RES * STDCALL mysql_list_tables(MYSQL *mysql,const char *wild); +int STDCALL mysql_list_tables_start(MYSQL_RES **ret, MYSQL *mysql, + const char *wild); +int STDCALL mysql_list_tables_cont(MYSQL_RES **ret, MYSQL *mysql, + int status); MYSQL_RES * STDCALL mysql_list_processes(MYSQL *mysql); +int STDCALL mysql_list_processes_start(MYSQL_RES **ret, + MYSQL *mysql); +int STDCALL mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql, + int status); int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg); void STDCALL mysql_free_result(MYSQL_RES *result); +int STDCALL mysql_free_result_start(MYSQL_RES *result); +int STDCALL mysql_free_result_cont(MYSQL_RES *result, int status); void STDCALL mysql_data_seek(MYSQL_RES *result, my_ulonglong offset); MYSQL_ROW_OFFSET STDCALL mysql_row_seek(MYSQL_RES *result, @@ -555,10 +649,19 @@ MYSQL_ROW_OFFSET STDCALL mysql_row_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset); MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); +int STDCALL mysql_fetch_row_start(MYSQL_ROW *ret, + MYSQL_RES *result); +int STDCALL mysql_fetch_row_cont(MYSQL_ROW *ret, MYSQL_RES *result, + int status); unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result); MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result); MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table, const char *wild); +int STDCALL mysql_list_fields_start(MYSQL_RES **ret, MYSQL *mysql, + const char *table, + const char *wild); +int STDCALL mysql_list_fields_cont(MYSQL_RES **ret, MYSQL *mysql, + int status); unsigned long STDCALL mysql_escape_string(char *to,const char *from, unsigned long from_length); unsigned long STDCALL mysql_hex_string(char *to,const char *from, @@ -584,6 +687,10 @@ int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con, char* res_buf, int res_buf_size); my_bool STDCALL mysql_read_query_result(MYSQL *mysql); +int STDCALL mysql_read_query_result_start(my_bool *ret, + MYSQL *mysql); +int STDCALL mysql_read_query_result_cont(my_bool *ret, + MYSQL *mysql, int status); /* @@ -760,16 +867,25 @@ enum enum_stmt_attr_type STMT_ATTR_PREFETCH_ROWS }; - MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql); int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length); +int STDCALL mysql_stmt_prepare_start(int *ret, MYSQL_STMT *stmt, + const char *query, unsigned long length); +int STDCALL mysql_stmt_prepare_cont(int *ret, MYSQL_STMT *stmt, int status); int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_execute_start(int *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_execute_cont(int *ret, MYSQL_STMT *stmt, int status); int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_fetch_start(int *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_fetch_cont(int *ret, MYSQL_STMT *stmt, int status); int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg, unsigned int column, unsigned long offset); int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_store_result_start(int *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_store_result_cont(int *ret, MYSQL_STMT *stmt, + int status); unsigned long STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt); my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type attr_type, @@ -780,12 +896,25 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); my_bool STDCALL mysql_stmt_close(MYSQL_STMT * stmt); +int STDCALL mysql_stmt_close_start(my_bool *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_close_cont(my_bool *ret, MYSQL_STMT * stmt, int status); my_bool STDCALL mysql_stmt_reset(MYSQL_STMT * stmt); +int STDCALL mysql_stmt_reset_start(my_bool *ret, MYSQL_STMT * stmt); +int STDCALL mysql_stmt_reset_cont(my_bool *ret, MYSQL_STMT *stmt, int status); my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_free_result_start(my_bool *ret, MYSQL_STMT *stmt); +int STDCALL mysql_stmt_free_result_cont(my_bool *ret, MYSQL_STMT *stmt, + int status); my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, unsigned int param_number, const char *data, unsigned long length); +int STDCALL mysql_stmt_send_long_data_start(my_bool *ret, MYSQL_STMT *stmt, + unsigned int param_number, + const char *data, + unsigned long len); +int STDCALL mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt, + int status); MYSQL_RES *STDCALL mysql_stmt_result_metadata(MYSQL_STMT *stmt); MYSQL_RES *STDCALL mysql_stmt_param_metadata(MYSQL_STMT *stmt); unsigned int STDCALL mysql_stmt_errno(MYSQL_STMT * stmt); @@ -801,12 +930,24 @@ my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt); unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt); my_bool STDCALL mysql_commit(MYSQL * mysql); +int STDCALL mysql_commit_start(my_bool *ret, MYSQL * mysql); +int STDCALL mysql_commit_cont(my_bool *ret, MYSQL * mysql, int status); my_bool STDCALL mysql_rollback(MYSQL * mysql); +int STDCALL mysql_rollback_start(my_bool *ret, MYSQL * mysql); +int STDCALL mysql_rollback_cont(my_bool *ret, MYSQL * mysql, int status); my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode); +int STDCALL mysql_autocommit_start(my_bool *ret, MYSQL * mysql, + my_bool auto_mode); +int STDCALL mysql_autocommit_cont(my_bool *ret, MYSQL * mysql, int status); my_bool STDCALL mysql_more_results(MYSQL *mysql); int STDCALL mysql_next_result(MYSQL *mysql); +int STDCALL mysql_next_result_start(int *ret, MYSQL *mysql); +int STDCALL mysql_next_result_cont(int *ret, MYSQL *mysql, int status); void STDCALL mysql_close(MYSQL *sock); - +int STDCALL mysql_close_start(MYSQL *sock); +int STDCALL mysql_close_cont(MYSQL *sock, int status); +my_socket STDCALL mysql_get_socket(const MYSQL *mysql); +unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql); /* status return codes */ #define MYSQL_NO_DATA 100 @@ -817,7 +958,20 @@ void STDCALL mysql_close(MYSQL *sock); #ifdef USE_OLD_FUNCTIONS MYSQL * STDCALL mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd); +int STDCALL mysql_connect_start(MYSQL **ret, MYSQL *mysql, + const char *host, const char *user, + const char *passwd); +int STDCALL mysql_connect_cont(MYSQL **ret, MYSQL *mysql, + int status); int STDCALL mysql_create_db(MYSQL *mysql, const char *DB); +int STDCALL mysql_create_db_start(int *ret, MYSQL *mysql, + const char *DB); +int STDCALL mysql_create_db_cont(int *ret, MYSQL *mysql, + int status); +int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB); +int STDCALL mysql_drop_db_start(int *ret, MYSQL *mysql, + const char *DB); +int STDCALL mysql_drop_db_cont(int *ret, MYSQL *mysql, int status); int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB); #define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT) #endif diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 6e71f886eba..f66d92c06a1 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -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); diff --git a/include/sql_common.h b/include/sql_common.h index 6b66ae2fd81..8bb33e3779c 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -26,11 +26,18 @@ extern const char *unknown_sqlstate; extern const char *cant_connect_sqlstate; extern const char *not_error_sqlstate; + +struct mysql_async_context; + struct st_mysql_options_extention { char *plugin_dir; char *default_auth; }; +struct st_mysql_extension { + struct mysql_async_context *async_context; +}; + typedef struct st_mysql_methods { my_bool (*read_query_result)(MYSQL *mysql); @@ -102,6 +109,10 @@ void mysql_client_plugin_deinit(); struct st_mysql_client_plugin; extern struct st_mysql_client_plugin *mysql_client_builtins[]; +/* Non-blocking client API. */ +void my_context_install_suspend_resume_hook(struct mysql_async_context *b, + void (*)(my_bool, void *), void *); + #ifdef __cplusplus } #endif diff --git a/include/violite.h b/include/violite.h index c61ce4855c6..d5c9c083bdd 100644 --- a/include/violite.h +++ b/include/violite.h @@ -194,6 +194,8 @@ struct st_vio char *read_pos; /* start of unfetched data in the read buffer */ char *read_end; /* end of unfetched data */ + struct mysql_async_context *async_context; /* For non-blocking API */ + uint read_timeout, write_timeout; /* function pointers. They are similar for socket/SSL/whatever */ void (*viodelete)(Vio*); int (*vioerrno)(Vio*); |