mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +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:
@ -60,6 +60,12 @@
|
||||
#define SIGNAL_FMT "signal %d"
|
||||
#endif
|
||||
|
||||
static my_bool non_blocking_api_enabled= 0;
|
||||
#if !defined(EMBEDDED_LIBRARY)
|
||||
#define WRAP_NONBLOCK_ENABLED non_blocking_api_enabled
|
||||
#include "../tests/nonblock-wrappers.h"
|
||||
#endif
|
||||
|
||||
/* Use cygwin for --exec and --system before 5.0 */
|
||||
#if MYSQL_VERSION_ID < 50000
|
||||
#define USE_CYGWIN
|
||||
@ -84,7 +90,7 @@ enum {
|
||||
OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
|
||||
OPT_MAX_CONNECT_RETRIES, OPT_MAX_CONNECTIONS,
|
||||
OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
|
||||
OPT_GLOBAL_SUBST, OPT_MY_CONNECT_TIMEOUT
|
||||
OPT_GLOBAL_SUBST, OPT_MY_CONNECT_TIMEOUT, OPT_NON_BLOCKING_API
|
||||
};
|
||||
|
||||
static int record= 0, opt_sleep= -1;
|
||||
@ -305,6 +311,7 @@ enum enum_commands {
|
||||
Q_LOWERCASE,
|
||||
Q_START_TIMER, Q_END_TIMER,
|
||||
Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
|
||||
Q_ENABLE_NON_BLOCKING_API, Q_DISABLE_NON_BLOCKING_API,
|
||||
Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
|
||||
Q_IF,
|
||||
Q_DISABLE_PARSING, Q_ENABLE_PARSING,
|
||||
@ -386,6 +393,8 @@ const char *command_names[]=
|
||||
"character_set",
|
||||
"disable_ps_protocol",
|
||||
"enable_ps_protocol",
|
||||
"enable_non_blocking_api",
|
||||
"disable_non_blocking_api",
|
||||
"disable_reconnect",
|
||||
"enable_reconnect",
|
||||
"if",
|
||||
@ -5235,7 +5244,10 @@ void do_connect(struct st_command *command)
|
||||
int con_port= opt_port;
|
||||
char *con_options;
|
||||
my_bool con_ssl= 0, con_compress= 0;
|
||||
my_bool con_pipe= 0, con_shm= 0;
|
||||
my_bool con_pipe= 0;
|
||||
#ifdef HAVE_SMEM
|
||||
my_bool con_shm= 0;
|
||||
#endif
|
||||
struct st_connection* con_slot;
|
||||
|
||||
static DYNAMIC_STRING ds_connection_name;
|
||||
@ -5324,7 +5336,11 @@ void do_connect(struct st_command *command)
|
||||
else if (length == 4 && !strncmp(con_options, "PIPE", 4))
|
||||
con_pipe= 1;
|
||||
else if (length == 3 && !strncmp(con_options, "SHM", 3))
|
||||
#ifdef HAVE_SMEM
|
||||
con_shm= 1;
|
||||
#else
|
||||
{ }
|
||||
#endif
|
||||
else
|
||||
die("Illegal option to connect: %.*s",
|
||||
(int) (end - con_options), con_options);
|
||||
@ -6146,6 +6162,10 @@ static struct my_option my_long_options[] =
|
||||
"Use prepared-statement protocol for communication.",
|
||||
&ps_protocol, &ps_protocol, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"non-blocking-api", OPT_NON_BLOCKING_API,
|
||||
"Use the non-blocking client API for communication.",
|
||||
&non_blocking_api_enabled, &non_blocking_api_enabled, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"quiet", 's', "Suppress all normal output.", &silent,
|
||||
&silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"record", 'r', "Record output of test_file into result file.",
|
||||
@ -8130,6 +8150,7 @@ int main(int argc, char **argv)
|
||||
next_con= connections + 1;
|
||||
|
||||
var_set_int("$PS_PROTOCOL", ps_protocol);
|
||||
var_set_int("$NON_BLOCKING_API", non_blocking_api_enabled);
|
||||
var_set_int("$SP_PROTOCOL", sp_protocol);
|
||||
var_set_int("$VIEW_PROTOCOL", view_protocol);
|
||||
var_set_int("$CURSOR_PROTOCOL", cursor_protocol);
|
||||
@ -8538,6 +8559,12 @@ int main(int argc, char **argv)
|
||||
case Q_ENABLE_PS_PROTOCOL:
|
||||
ps_protocol_enabled= ps_protocol;
|
||||
break;
|
||||
case Q_DISABLE_NON_BLOCKING_API:
|
||||
non_blocking_api_enabled= 0;
|
||||
break;
|
||||
case Q_ENABLE_NON_BLOCKING_API:
|
||||
non_blocking_api_enabled= 1;
|
||||
break;
|
||||
case Q_DISABLE_RECONNECT:
|
||||
set_reconnect(cur_con->mysql, 0);
|
||||
break;
|
||||
|
Reference in New Issue
Block a user