1
0
mirror of https://github.com/MariaDB/server.git synced 2025-09-02 09:41:40 +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:
unknown
2011-09-20 12:49:25 +02:00
parent 1a344b87e4
commit a5b881594d
41 changed files with 4389 additions and 38 deletions

View File

@@ -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

222
include/my_context.h Normal file
View File

@@ -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;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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*);