Commit 32a29afe authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-23238 - remove async client from server code.

It is already in libmariadb, and server (also that client in server)
does not need it.

It does not work in embedded either since it relies on non-blocking sockets
parent 72f0f0db
...@@ -65,9 +65,8 @@ ...@@ -65,9 +65,8 @@
#define SIGNAL_FMT "signal %d" #define SIGNAL_FMT "signal %d"
#endif #endif
#include <my_context.h>
static my_bool non_blocking_api_enabled= 0; static my_bool non_blocking_api_enabled= 0;
#if !defined(EMBEDDED_LIBRARY) && !defined(MY_CONTEXT_DISABLE) #if !defined(EMBEDDED_LIBRARY)
#define WRAP_NONBLOCK_ENABLED non_blocking_api_enabled #define WRAP_NONBLOCK_ENABLED non_blocking_api_enabled
#include "../tests/nonblock-wrappers.h" #include "../tests/nonblock-wrappers.h"
#endif #endif
...@@ -6002,10 +6001,8 @@ void do_connect(struct st_command *command) ...@@ -6002,10 +6001,8 @@ void do_connect(struct st_command *command)
if (opt_connect_timeout) if (opt_connect_timeout)
mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT, mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
(void *) &opt_connect_timeout); (void *) &opt_connect_timeout);
#ifndef MY_CONTEXT_DISABLE
if (mysql_options(con_slot->mysql, MYSQL_OPT_NONBLOCK, 0)) if (mysql_options(con_slot->mysql, MYSQL_OPT_NONBLOCK, 0))
die("Failed to initialise non-blocking API"); die("Failed to initialise non-blocking API");
#endif
if (opt_compress || con_compress) if (opt_compress || con_compress)
mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS); mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_NAME, mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_NAME,
......
/*
Copyright 2011 Kristian Nielsen and Monty Program Ab
This file is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser 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__) && !defined(__ILP32__)
#define MY_CONTEXT_USE_X86_64_GCC_ASM
#elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__)
#define MY_CONTEXT_USE_I386_GCC_ASM
#elif defined(HAVE_UCONTEXT_H)
#define MY_CONTEXT_USE_UCONTEXT
#else
#define MY_CONTEXT_DISABLE
#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_MEMCHECK_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_MEMCHECK_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_MEMCHECK_H
unsigned int valgrind_stack_id;
#endif
#ifndef DBUG_OFF
void *dbug_state;
#endif
};
#endif
#ifdef MY_CONTEXT_DISABLE
struct my_context {
int dummy;
};
#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.
*/
unsigned int events_to_wait_for;
/*
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 events_occurred;
/*
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 (in millisecods), 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;
};
/* Copyright (C) 2012 MariaDB Services and Kristian Nielsen
This program 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; version 2 of the License.
This program 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 program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
/* Common definitions for MariaDB non-blocking client library. */
#ifndef MYSQL_ASYNC_H
#define MYSQL_ASYNC_H
extern int my_connect_async(struct mysql_async_context *b, my_socket fd,
const struct sockaddr *name, uint namelen,
int vio_timeout);
extern ssize_t my_recv_async(struct mysql_async_context *b, my_socket fd,
unsigned char *buf, size_t size, int timeout);
extern ssize_t my_send_async(struct mysql_async_context *b, my_socket fd,
const unsigned char *buf, size_t size,
int timeout);
extern my_bool my_io_wait_async(struct mysql_async_context *b,
enum enum_vio_io_event event, int timeout);
#ifdef HAVE_OPENSSL
extern int my_ssl_read_async(struct mysql_async_context *b, SSL *ssl,
void *buf, int size);
extern int my_ssl_write_async(struct mysql_async_context *b, SSL *ssl,
const void *buf, int size);
#endif
#endif /* MYSQL_ASYNC_H */
...@@ -28,8 +28,6 @@ extern const char *cant_connect_sqlstate; ...@@ -28,8 +28,6 @@ extern const char *cant_connect_sqlstate;
extern const char *not_error_sqlstate; extern const char *not_error_sqlstate;
struct mysql_async_context;
struct st_mysql_options_extention { struct st_mysql_options_extention {
char *plugin_dir; char *plugin_dir;
char *default_auth; char *default_auth;
...@@ -41,7 +39,6 @@ struct st_mysql_options_extention { ...@@ -41,7 +39,6 @@ struct st_mysql_options_extention {
double progress, double progress,
const char *proc_info, const char *proc_info,
uint proc_info_length); uint proc_info_length);
struct mysql_async_context *async_context;
HASH connection_attributes; HASH connection_attributes;
size_t connection_attributes_length; size_t connection_attributes_length;
}; };
...@@ -125,10 +122,6 @@ struct st_mysql_client_plugin; ...@@ -125,10 +122,6 @@ struct st_mysql_client_plugin;
extern struct st_mysql_client_plugin *mysql_client_builtins[]; extern struct st_mysql_client_plugin *mysql_client_builtins[];
uchar * send_client_connect_attrs(MYSQL *mysql, uchar *buf); uchar * send_client_connect_attrs(MYSQL *mysql, uchar *buf);
/* Non-blocking client API. */
void my_context_install_suspend_resume_hook(struct mysql_async_context *b,
void (*)(my_bool, void *), void *);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -249,7 +249,6 @@ struct st_vio ...@@ -249,7 +249,6 @@ struct st_vio
char *read_pos; /* start of unfetched data in the char *read_pos; /* start of unfetched data in the
read buffer */ read buffer */
char *read_end; /* end of unfetched data */ char *read_end; /* end of unfetched data */
struct mysql_async_context *async_context; /* For non-blocking API */
int read_timeout; /* Timeout value (ms) for read ops. */ int read_timeout; /* Timeout value (ms) for read ops. */
int write_timeout; /* Timeout value (ms) for write ops. */ int write_timeout; /* Timeout value (ms) for write ops. */
/* function pointers. They are similar for socket/SSL/whatever */ /* function pointers. They are similar for socket/SSL/whatever */
......
...@@ -43,7 +43,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ...@@ -43,7 +43,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
libmysql.c ../sql-common/errmsg.c libmysql.c ../sql-common/errmsg.c
../sql-common/client.c ../sql-common/client.c
../sql-common/my_user.c ../sql-common/pack.c ../sql-common/my_user.c ../sql-common/pack.c
../sql-common/client_plugin.c ../sql-common/mysql_async.c ../sql-common/client_plugin.c
../sql/password.c ../sql/discover.cc ../sql/derror.cc ../sql/password.c ../sql/discover.cc ../sql/derror.cc
../sql/field.cc ../sql/field_conv.cc ../sql/field_comp.cc ../sql/field.cc ../sql/field_conv.cc ../sql/field_comp.cc
../sql/filesort_utils.cc ../sql/sql_digest.cc ../sql/filesort_utils.cc ../sql/sql_digest.cc
...@@ -309,82 +309,7 @@ mysql_client_register_plugin ...@@ -309,82 +309,7 @@ mysql_client_register_plugin
mysql_load_plugin mysql_load_plugin
mysql_load_plugin_v mysql_load_plugin_v
mysql_plugin_options mysql_plugin_options
# Async API
mysql_get_timeout_value
mysql_get_timeout_value_ms
mysql_get_socket
mysql_autocommit_cont
mysql_autocommit_start
mysql_change_user_cont
mysql_change_user_start
mysql_close_cont
mysql_close_start
mysql_commit_cont
mysql_commit_start
mysql_dump_debug_info_cont
mysql_dump_debug_info_start
mysql_fetch_row_cont
mysql_fetch_row_start
mysql_free_result_cont
mysql_free_result_start
mysql_kill_cont
mysql_kill_start
mysql_list_dbs_cont
mysql_list_dbs_start
mysql_list_fields_cont
mysql_list_fields_start
mysql_list_processes_cont
mysql_list_processes_start
mysql_list_tables_cont
mysql_list_tables_start
mysql_next_result_cont
mysql_next_result_start
mysql_ping_cont
mysql_ping_start
mysql_query_cont
mysql_query_start
mysql_read_query_result_cont
mysql_read_query_result_start
mysql_real_connect_cont
mysql_real_connect_start
mysql_real_query_cont
mysql_real_query_start
mysql_refresh_cont
mysql_refresh_start
mysql_rollback_cont
mysql_rollback_start
mysql_select_db_cont
mysql_select_db_start
mysql_send_query_cont
mysql_send_query_start
mysql_set_character_set_cont
mysql_set_character_set_start
mysql_set_server_option_cont
mysql_set_server_option_start
mysql_shutdown_cont
mysql_shutdown_start
mysql_stat_cont
mysql_stat_start
mysql_stmt_close_cont
mysql_stmt_close_start
mysql_stmt_execute_cont
mysql_stmt_execute_start
mysql_stmt_fetch_cont
mysql_stmt_fetch_start
mysql_stmt_free_result_cont
mysql_stmt_free_result_start
mysql_stmt_next_result_cont
mysql_stmt_next_result_start
mysql_stmt_prepare_cont
mysql_stmt_prepare_start
mysql_stmt_reset_cont
mysql_stmt_reset_start
mysql_stmt_send_long_data_cont
mysql_stmt_send_long_data_start
mysql_stmt_store_result_cont
mysql_stmt_store_result_start
mysql_store_result_cont
mysql_store_result_start
#dynamic columns api #dynamic columns api
dynamic_column_create dynamic_column_create
dynamic_column_create_many dynamic_column_create_many
......
...@@ -43,7 +43,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c my_default.c ...@@ -43,7 +43,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c my_default.c
safemalloc.c my_new.cc safemalloc.c my_new.cc
my_getncpus.c my_safehash.c my_chmod.c my_rnd.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c
my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c ../sql-common/my_time.c my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c ../sql-common/my_time.c
my_rdtsc.c my_context.c psi_noop.c my_rdtsc.c psi_noop.c
my_atomic_writes.c my_cpu.c my_likely.c my_largepage.c my_atomic_writes.c my_cpu.c my_likely.c my_largepage.c
file_logger.c my_dlerror.c) file_logger.c my_dlerror.c)
......
This diff is collapsed.
...@@ -100,8 +100,6 @@ my_bool net_flush(NET *net); ...@@ -100,8 +100,6 @@ my_bool net_flush(NET *net);
#include <ssl_compat.h> #include <ssl_compat.h>
#include <sql_common.h> #include <sql_common.h>
#include <mysql/client_plugin.h> #include <mysql/client_plugin.h>
#include <my_context.h>
#include <mysql_async.h>
typedef enum { typedef enum {
ALWAYS_ACCEPT, /* heuristics is disabled, use CLIENT_LOCAL_FILES */ ALWAYS_ACCEPT, /* heuristics is disabled, use CLIENT_LOCAL_FILES */
...@@ -2607,20 +2605,11 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len, ...@@ -2607,20 +2605,11 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
static int static int
connect_sync_or_async(MYSQL *mysql, NET *net, my_socket fd, connect_sync(MYSQL *mysql, NET *net, my_socket fd,
struct sockaddr *name, uint namelen) struct sockaddr *name, uint namelen)
{ {
int vio_timeout = get_vio_connect_timeout(mysql); int vio_timeout = get_vio_connect_timeout(mysql);
if (mysql->options.extension && mysql->options.extension->async_context &&
mysql->options.extension->async_context->active)
{
my_bool old_mode;
vio_blocking(net->vio, FALSE, &old_mode);
return my_connect_async(mysql->options.extension->async_context, fd,
name, namelen, vio_timeout);
}
return vio_socket_connect(net->vio, name, namelen, vio_timeout); return vio_socket_connect(net->vio, name, namelen, vio_timeout);
} }
...@@ -2787,7 +2776,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -2787,7 +2776,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
bzero((char*) &UNIXaddr, sizeof(UNIXaddr)); bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
UNIXaddr.sun_family= AF_UNIX; UNIXaddr.sun_family= AF_UNIX;
strmake_buf(UNIXaddr.sun_path, unix_socket); strmake_buf(UNIXaddr.sun_path, unix_socket);
if (connect_sync_or_async(mysql, net, sock, if (connect_sync(mysql, net, sock,
(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr))) (struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr)))
{ {
DBUG_PRINT("error",("Got error %d on connect to local server", DBUG_PRINT("error",("Got error %d on connect to local server",
...@@ -2902,7 +2891,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -2902,7 +2891,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
} }
DBUG_PRINT("info", ("Connect socket")); DBUG_PRINT("info", ("Connect socket"));
status= connect_sync_or_async(mysql, net, sock, status= connect_sync(mysql, net, sock,
t_res->ai_addr, (uint)t_res->ai_addrlen); t_res->ai_addr, (uint)t_res->ai_addrlen);
/* /*
Here we rely on my_connect() to return success only if the Here we rely on my_connect() to return success only if the
...@@ -2952,9 +2941,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -2952,9 +2941,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
goto error; goto error;
} }
if (mysql->options.extension && mysql->options.extension->async_context)
net->vio->async_context= mysql->options.extension->async_context;
if (my_net_init(net, net->vio, _current_thd(), MYF(0))) if (my_net_init(net, net->vio, _current_thd(), MYF(0)))
{ {
vio_delete(net->vio); vio_delete(net->vio);
...@@ -3195,42 +3181,16 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -3195,42 +3181,16 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
/* Free alloced memory */ /* Free alloced memory */
end_server(mysql); end_server(mysql);
mysql_close_free(mysql); mysql_close_free(mysql);
if (!(client_flag & CLIENT_REMEMBER_OPTIONS) && if (!(client_flag & CLIENT_REMEMBER_OPTIONS))
!(mysql->options.extension && mysql->options.extension->async_context))
mysql_close_free_options(mysql); mysql_close_free_options(mysql);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
} }
struct my_hook_data {
MYSQL *orig_mysql;
MYSQL *new_mysql;
/* This is always NULL currently, but restoring does not hurt just in case. */
Vio *orig_vio;
};
/*
Callback hook to make the new VIO accessible via the old MYSQL to calling
application when suspending a non-blocking call during automatic reconnect.
*/
static void
my_suspend_hook(my_bool suspend, void *data)
{
struct my_hook_data *hook_data= (struct my_hook_data *)data;
if (suspend)
{
hook_data->orig_vio= hook_data->orig_mysql->net.vio;
hook_data->orig_mysql->net.vio= hook_data->new_mysql->net.vio;
}
else
hook_data->orig_mysql->net.vio= hook_data->orig_vio;
}
my_bool mysql_reconnect(MYSQL *mysql) my_bool mysql_reconnect(MYSQL *mysql)
{ {
MYSQL tmp_mysql; MYSQL tmp_mysql;
struct my_hook_data hook_data;
struct mysql_async_context *ctxt= NULL;
DBUG_ENTER("mysql_reconnect"); DBUG_ENTER("mysql_reconnect");
DBUG_ASSERT(mysql); DBUG_ASSERT(mysql);
DBUG_PRINT("enter", ("mysql->reconnect: %d", mysql->reconnect)); DBUG_PRINT("enter", ("mysql->reconnect: %d", mysql->reconnect));
...@@ -3247,31 +3207,11 @@ my_bool mysql_reconnect(MYSQL *mysql) ...@@ -3247,31 +3207,11 @@ my_bool mysql_reconnect(MYSQL *mysql)
tmp_mysql.options= mysql->options; tmp_mysql.options= mysql->options;
tmp_mysql.options.my_cnf_file= tmp_mysql.options.my_cnf_group= 0; tmp_mysql.options.my_cnf_file= tmp_mysql.options.my_cnf_group= 0;
/*
If we are automatically re-connecting inside a non-blocking API call, we
may need to suspend and yield to the user application during the reconnect.
If so, the user application will need access to the new VIO already then
so that it can correctly wait for I/O to become ready.
To achieve this, we temporarily install a hook that will temporarily put in
the VIO while we are suspended.
(The vio will be put in the original MYSQL permanently once we successfully
reconnect, or be discarded if we fail to reconnect.)
*/
if (mysql->options.extension &&
(ctxt= mysql->options.extension->async_context) &&
mysql->options.extension->async_context->active)
{
hook_data.orig_mysql= mysql;
hook_data.new_mysql= &tmp_mysql;
hook_data.orig_vio= mysql->net.vio;
my_context_install_suspend_resume_hook(ctxt, my_suspend_hook, &hook_data);
}
if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
mysql->db, mysql->port, mysql->unix_socket, mysql->db, mysql->port, mysql->unix_socket,
mysql->client_flag | CLIENT_REMEMBER_OPTIONS)) mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
{ {
if (ctxt)
my_context_install_suspend_resume_hook(ctxt, NULL, NULL);
mysql->net.last_errno= tmp_mysql.net.last_errno; mysql->net.last_errno= tmp_mysql.net.last_errno;
strmov(mysql->net.last_error, tmp_mysql.net.last_error); strmov(mysql->net.last_error, tmp_mysql.net.last_error);
strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate); strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
...@@ -3282,15 +3222,11 @@ my_bool mysql_reconnect(MYSQL *mysql) ...@@ -3282,15 +3222,11 @@ my_bool mysql_reconnect(MYSQL *mysql)
DBUG_PRINT("error", ("mysql_set_character_set() failed")); DBUG_PRINT("error", ("mysql_set_character_set() failed"));
bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options)); bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options));
mysql_close(&tmp_mysql); mysql_close(&tmp_mysql);
if (ctxt)
my_context_install_suspend_resume_hook(ctxt, NULL, NULL);
mysql->net.last_errno= tmp_mysql.net.last_errno; mysql->net.last_errno= tmp_mysql.net.last_errno;
strmov(mysql->net.last_error, tmp_mysql.net.last_error); strmov(mysql->net.last_error, tmp_mysql.net.last_error);
strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate); strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (ctxt)
my_context_install_suspend_resume_hook(ctxt, NULL, NULL);
DBUG_PRINT("info", ("reconnect succeeded")); DBUG_PRINT("info", ("reconnect succeeded"));
tmp_mysql.reconnect= 1; tmp_mysql.reconnect= 1;
...@@ -3365,15 +3301,9 @@ static void mysql_close_free_options(MYSQL *mysql) ...@@ -3365,15 +3301,9 @@ static void mysql_close_free_options(MYSQL *mysql)
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
if (mysql->options.extension) if (mysql->options.extension)
{ {
struct mysql_async_context *ctxt= mysql->options.extension->async_context;
my_free(mysql->options.extension->plugin_dir); my_free(mysql->options.extension->plugin_dir);
my_free(mysql->options.extension->default_auth); my_free(mysql->options.extension->default_auth);
my_hash_free(&mysql->options.extension->connection_attributes); my_hash_free(&mysql->options.extension->connection_attributes);
if (ctxt)
{
my_context_destroy(&ctxt->async_context);
my_free(ctxt);
}
my_free(mysql->options.extension); my_free(mysql->options.extension);
} }
bzero((char*) &mysql->options,sizeof(mysql->options)); bzero((char*) &mysql->options,sizeof(mysql->options));
...@@ -3806,15 +3736,9 @@ mysql_fetch_lengths(MYSQL_RES *res) ...@@ -3806,15 +3736,9 @@ mysql_fetch_lengths(MYSQL_RES *res)
return res->lengths; return res->lengths;
} }
#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15)
int STDCALL int STDCALL
mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
{ {
struct mysql_async_context *ctxt;
size_t stacksize;
DBUG_ENTER("mysql_options"); DBUG_ENTER("mysql_options");
DBUG_PRINT("enter",("option: %d",(int) option)); DBUG_PRINT("enter",("option: %d",(int) option));
switch (option) { switch (option) {
...@@ -3910,39 +3834,6 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) ...@@ -3910,39 +3834,6 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
(void (*)(const MYSQL *, uint, uint, double, const char *, uint)) arg; (void (*)(const MYSQL *, uint, uint, double, const char *, uint)) arg;
break; break;
case MYSQL_OPT_NONBLOCK: case MYSQL_OPT_NONBLOCK:
if (mysql->options.extension &&
(ctxt = mysql->options.extension->async_context) != 0)
{
/*
We must not allow changing the stack size while a non-blocking call is
suspended (as the stack is then in use).
*/
if (ctxt->suspended)
DBUG_RETURN(1);
my_context_destroy(&ctxt->async_context);
my_free(ctxt);
}
if (!(ctxt= (struct mysql_async_context *)
my_malloc(PSI_INSTRUMENT_ME, sizeof(*ctxt), MYF(MY_ZEROFILL))))
{
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(1);
}
stacksize= 0;
if (arg)
stacksize= *(const size_t *)arg;
if (!stacksize)
stacksize= ASYNC_CONTEXT_DEFAULT_STACK_SIZE;
if (my_context_init(&ctxt->async_context, stacksize))
{
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
my_free(ctxt);
DBUG_RETURN(1);
}
ENSURE_EXTENSIONS_PRESENT(&(mysql->options));
mysql->options.extension->async_context= ctxt;
if (mysql->net.vio)
mysql->net.vio->async_context= ctxt;
break; break;
case MYSQL_OPT_SSL_KEY: case MYSQL_OPT_SSL_KEY:
SET_SSL_PATH_OPTION(&mysql->options,ssl_key, arg); SET_SSL_PATH_OPTION(&mysql->options,ssl_key, arg);
......
This diff is collapsed.
...@@ -139,7 +139,6 @@ SET (SQL_SOURCE ...@@ -139,7 +139,6 @@ SET (SQL_SOURCE
opt_index_cond_pushdown.cc opt_subselect.cc opt_index_cond_pushdown.cc opt_subselect.cc
opt_table_elimination.cc sql_expression_cache.cc opt_table_elimination.cc sql_expression_cache.cc
gcalc_slicescan.cc gcalc_tools.cc gcalc_slicescan.cc gcalc_tools.cc
../sql-common/mysql_async.c
my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc
my_json_writer.cc my_json_writer.cc
rpl_gtid.cc rpl_parallel.cc rpl_gtid.cc rpl_parallel.cc
......
...@@ -31,9 +31,8 @@ ...@@ -31,9 +31,8 @@
and use poll()/select() to wait for them to complete. This way we can get and use poll()/select() to wait for them to complete. This way we can get
a good coverage testing of the non-blocking API as well. a good coverage testing of the non-blocking API as well.
*/ */
#include <my_context.h>
static my_bool non_blocking_api_enabled= 0; static my_bool non_blocking_api_enabled= 0;
#if !defined(EMBEDDED_LIBRARY) && !defined(MY_CONTEXT_DISABLE) #if !defined(EMBEDDED_LIBRARY)
#define WRAP_NONBLOCK_ENABLED non_blocking_api_enabled #define WRAP_NONBLOCK_ENABLED non_blocking_api_enabled
#include "nonblock-wrappers.h" #include "nonblock-wrappers.h"
#endif #endif
......
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
#include <mstcpip.h> #include <mstcpip.h>
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
#endif #endif
#include "my_context.h"
#include <mysql_async.h>
#ifdef FIONREAD_IN_SYS_FILIO #ifdef FIONREAD_IN_SYS_FILIO
# include <sys/filio.h> # include <sys/filio.h>
...@@ -171,34 +169,18 @@ size_t vio_read(Vio *vio, uchar *buf, size_t size) ...@@ -171,34 +169,18 @@ size_t vio_read(Vio *vio, uchar *buf, size_t size)
if (vio->read_timeout >= 0) if (vio->read_timeout >= 0)
flags= VIO_DONTWAIT; flags= VIO_DONTWAIT;
if (vio->async_context && vio->async_context->active) while ((ret= mysql_socket_recv(vio->mysql_socket, (SOCKBUF_T *)buf, size,
ret= my_recv_async(vio->async_context, flags)) == -1)
mysql_socket_getfd(vio->mysql_socket),
buf, size, vio->read_timeout);
else
{ {
if (vio->async_context) int error= socket_errno;
{
/*
If switching from non-blocking to blocking API usage, set the socket
back to blocking mode.
*/
my_bool old_mode;
vio_blocking(vio, TRUE, &old_mode);
}
while ((ret= mysql_socket_recv(vio->mysql_socket, (SOCKBUF_T *)buf, size,
flags)) == -1)
{
int error= socket_errno;
/* The operation would block? */ /* The operation would block? */
if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK) if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
break; break;
/* Wait for input data to become available. */ /* Wait for input data to become available. */
if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_READ))) if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_READ)))
break; break;
}
} }
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (ret == -1) if (ret == -1)
...@@ -282,33 +264,17 @@ size_t vio_write(Vio *vio, const uchar* buf, size_t size) ...@@ -282,33 +264,17 @@ size_t vio_write(Vio *vio, const uchar* buf, size_t size)
if (vio->write_timeout >= 0) if (vio->write_timeout >= 0)
flags= VIO_DONTWAIT; flags= VIO_DONTWAIT;
if (vio->async_context && vio->async_context->active) while ((ret= mysql_socket_send(vio->mysql_socket, (SOCKBUF_T *)buf, size,
ret= my_send_async(vio->async_context, flags)) == -1)
mysql_socket_getfd(vio->mysql_socket), buf, size,
vio->write_timeout);
else
{ {
if (vio->async_context) int error= socket_errno;
{ /* The operation would block? */
/* if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
If switching from non-blocking to blocking API usage, set the socket break;
back to blocking mode.
*/ /* Wait for the output buffer to become writable.*/
my_bool old_mode; if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_WRITE)))
vio_blocking(vio, TRUE, &old_mode); break;
}
while ((ret= mysql_socket_send(vio->mysql_socket, (SOCKBUF_T *)buf, size,
flags)) == -1)
{
int error= socket_errno;
/* The operation would block? */
if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
break;
/* Wait for the output buffer to become writable.*/
if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_WRITE)))
break;
}
} }
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (ret == -1) if (ret == -1)
...@@ -953,24 +919,6 @@ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout) ...@@ -953,24 +919,6 @@ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout)
DBUG_ENTER("vio_io_wait"); DBUG_ENTER("vio_io_wait");
DBUG_PRINT("enter", ("timeout: %d", timeout)); DBUG_PRINT("enter", ("timeout: %d", timeout));
/*
Note that if zero timeout, then we will not block, so we do not need to
yield to calling application in the async case.
*/
if (timeout != 0 && vio->async_context && vio->async_context->active)
{
START_SOCKET_WAIT(locker, &state, vio->mysql_socket,
PSI_SOCKET_SELECT, timeout);
ret= my_io_wait_async(vio->async_context, event, timeout);
if (ret == 0)
{
DBUG_PRINT("info", ("timeout"));
errno= SOCKET_ETIMEDOUT;
}
END_SOCKET_WAIT(locker,timeout);
DBUG_RETURN(ret);
}
memset(&pfd, 0, sizeof(pfd)); memset(&pfd, 0, sizeof(pfd));
pfd.fd= sd; pfd.fd= sd;
...@@ -1032,21 +980,6 @@ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout) ...@@ -1032,21 +980,6 @@ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout)
MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */ MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
DBUG_ENTER("vio_io_wait"); DBUG_ENTER("vio_io_wait");
/*
Note that if zero timeout, then we will not block, so we do not need to
yield to calling application in the async case.
*/
if (timeout != 0 && vio->async_context && vio->async_context->active)
{
START_SOCKET_WAIT(locker, &state, vio->mysql_socket,
PSI_SOCKET_SELECT, timeout);
ret= my_io_wait_async(vio->async_context, event, timeout);
if (ret == 0)
WSASetLastError(SOCKET_ETIMEDOUT);
END_SOCKET_WAIT(locker, timeout);
DBUG_RETURN(ret);
}
/* Convert the timeout, in milliseconds, to seconds and microseconds. */ /* Convert the timeout, in milliseconds, to seconds and microseconds. */
if (timeout >= 0) if (timeout >= 0)
{ {
......
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
*/ */
#include "vio_priv.h" #include "vio_priv.h"
#include "my_context.h"
#include <mysql_async.h>
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
...@@ -129,21 +127,17 @@ size_t vio_ssl_read(Vio *vio, uchar *buf, size_t size) ...@@ -129,21 +127,17 @@ size_t vio_ssl_read(Vio *vio, uchar *buf, size_t size)
(int)mysql_socket_getfd(vio->mysql_socket), buf, size, (int)mysql_socket_getfd(vio->mysql_socket), buf, size,
vio->ssl_arg)); vio->ssl_arg));
if (vio->async_context && vio->async_context->active)
ret= my_ssl_read_async(vio->async_context, (SSL *)vio->ssl_arg, buf, (int)size); while ((ret= SSL_read(ssl, buf, (int)size)) < 0)
else
{ {
while ((ret= SSL_read(ssl, buf, (int)size)) < 0) enum enum_vio_io_event event;
{
enum enum_vio_io_event event;
/* Process the SSL I/O error. */ /* Process the SSL I/O error. */
if (!ssl_should_retry(vio, ret, &event)) if (!ssl_should_retry(vio, ret, &event))
break; break;
/* Attempt to wait for an I/O event. */ /* Attempt to wait for an I/O event. */
if (vio_socket_io_wait(vio, event)) if (vio_socket_io_wait(vio, event))
break; break;
}
} }
DBUG_PRINT("exit", ("%d", (int) ret)); DBUG_PRINT("exit", ("%d", (int) ret));
...@@ -160,24 +154,17 @@ size_t vio_ssl_write(Vio *vio, const uchar *buf, size_t size) ...@@ -160,24 +154,17 @@ size_t vio_ssl_write(Vio *vio, const uchar *buf, size_t size)
DBUG_PRINT("enter", ("sd: %d buf: %p size: %zu", DBUG_PRINT("enter", ("sd: %d buf: %p size: %zu",
(int)mysql_socket_getfd(vio->mysql_socket), (int)mysql_socket_getfd(vio->mysql_socket),
buf, size)); buf, size));
while ((ret= SSL_write(ssl, buf, (int)size)) < 0)
if (vio->async_context && vio->async_context->active)
ret= my_ssl_write_async(vio->async_context, (SSL *)vio->ssl_arg, buf,
(int)size);
else
{ {
while ((ret= SSL_write(ssl, buf, (int)size)) < 0) enum enum_vio_io_event event;
{
enum enum_vio_io_event event;
/* Process the SSL I/O error. */ /* Process the SSL I/O error. */
if (!ssl_should_retry(vio, ret, &event)) if (!ssl_should_retry(vio, ret, &event))
break; break;
/* Attempt to wait for an I/O event. */ /* Attempt to wait for an I/O event. */
if (vio_socket_io_wait(vio, event)) if (vio_socket_io_wait(vio, event))
break; break;
}
} }
DBUG_RETURN(ret < 0 ? -1 : ret); DBUG_RETURN(ret < 0 ? -1 : ret);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment