diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2020-08-11 12:11:07 +0000 |
---|---|---|
committer | Vladislav Vaintroub <wlad@mariadb.com> | 2020-08-11 12:11:07 +0000 |
commit | 2f6492c21fb1816a6a40fb9004fb89b7f17adb3f (patch) | |
tree | 3e8c4ef831d68d9144be54348559c3ff7728c374 | |
parent | 09be96ff08bba1f2dd7ca72f2b28925623be6e79 (diff) | |
download | mariadb-git-bb-10.6-MDEV-23238.tar.gz |
MDEV-23238 - remove async client from server code.bb-10.6-MDEV-23238
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
-rw-r--r-- | client/mysqltest.cc | 5 | ||||
-rw-r--r-- | include/my_context.h | 232 | ||||
-rw-r--r-- | include/mysql_async.h | 38 | ||||
-rw-r--r-- | include/sql_common.h | 7 | ||||
-rw-r--r-- | include/violite.h | 1 | ||||
-rw-r--r-- | libmysqld/CMakeLists.txt | 79 | ||||
-rw-r--r-- | mysys/CMakeLists.txt | 2 | ||||
-rw-r--r-- | mysys/my_context.c | 761 | ||||
-rw-r--r-- | sql-common/client.c | 119 | ||||
-rw-r--r-- | sql-common/mysql_async.c | 1995 | ||||
-rw-r--r-- | sql/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/mysql_client_fw.c | 3 | ||||
-rw-r--r-- | vio/viosocket.c | 105 | ||||
-rw-r--r-- | vio/viossl.c | 47 |
14 files changed, 46 insertions, 3349 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 79ca4ed60e7..6b829ccb8be 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -65,9 +65,8 @@ #define SIGNAL_FMT "signal %d" #endif -#include <my_context.h> 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 #include "../tests/nonblock-wrappers.h" #endif @@ -6002,10 +6001,8 @@ void do_connect(struct st_command *command) if (opt_connect_timeout) mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT, (void *) &opt_connect_timeout); -#ifndef MY_CONTEXT_DISABLE if (mysql_options(con_slot->mysql, MYSQL_OPT_NONBLOCK, 0)) die("Failed to initialise non-blocking API"); -#endif if (opt_compress || con_compress) mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS); mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_NAME, diff --git a/include/my_context.h b/include/my_context.h deleted file mode 100644 index ea0e3496887..00000000000 --- a/include/my_context.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - 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; -}; diff --git a/include/mysql_async.h b/include/mysql_async.h deleted file mode 100644 index 3e4cb351bb5..00000000000 --- a/include/mysql_async.h +++ /dev/null @@ -1,38 +0,0 @@ -/* 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 */ diff --git a/include/sql_common.h b/include/sql_common.h index 9836d0c1cdc..9fc983616a0 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -28,8 +28,6 @@ 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; @@ -41,7 +39,6 @@ struct st_mysql_options_extention { double progress, const char *proc_info, uint proc_info_length); - struct mysql_async_context *async_context; HASH connection_attributes; size_t connection_attributes_length; }; @@ -125,10 +122,6 @@ struct st_mysql_client_plugin; extern struct st_mysql_client_plugin *mysql_client_builtins[]; 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 } #endif diff --git a/include/violite.h b/include/violite.h index 6d09621bea6..2599cbf27e8 100644 --- a/include/violite.h +++ b/include/violite.h @@ -249,7 +249,6 @@ 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 */ int read_timeout; /* Timeout value (ms) for read ops. */ int write_timeout; /* Timeout value (ms) for write ops. */ /* function pointers. They are similar for socket/SSL/whatever */ diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 57b468c7245..91cf46c4683 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -43,7 +43,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc libmysql.c ../sql-common/errmsg.c ../sql-common/client.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/field.cc ../sql/field_conv.cc ../sql/field_comp.cc ../sql/filesort_utils.cc ../sql/sql_digest.cc @@ -308,82 +308,7 @@ mysql_client_register_plugin mysql_load_plugin mysql_load_plugin_v 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_column_create dynamic_column_create_many diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 14a4ea9e9bb..3be4bc1b103 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -43,7 +43,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c my_default.c safemalloc.c my_new.cc 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_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 file_logger.c my_dlerror.c) diff --git a/mysys/my_context.c b/mysys/my_context.c deleted file mode 100644 index 5423f59d19b..00000000000 --- a/mysys/my_context.c +++ /dev/null @@ -1,761 +0,0 @@ -/* - Copyright 2011, 2012 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/>. -*/ - -/* - Implementation of async context spawning using Posix ucontext and - swapcontext(). -*/ - -#include "mysys_priv.h" -#include "m_string.h" -#include "my_context.h" - -#ifdef HAVE_VALGRIND_MEMCHECK_H -#include <valgrind/valgrind.h> -#endif - -#ifdef MY_CONTEXT_USE_UCONTEXT -/* - The makecontext() only allows to pass integers into the created context :-( - We want to pass pointers, so we do it this kinda hackish way. - Anyway, it should work everywhere, and at least it does not break strict - aliasing. -*/ -union pass_void_ptr_as_2_int { - int a[2]; - void *p; -}; - - -/* - We use old-style function definition here, as this is passed to - makecontext(). And the type of the makecontext() argument does not match - the actual type (as the actual type can differ from call to call). -*/ -static void -my_context_spawn_internal(i0, i1) -int i0, i1; -{ - int err; - struct my_context *c; - union pass_void_ptr_as_2_int u; - - u.a[0]= i0; - u.a[1]= i1; - c= (struct my_context *)u.p; - - (*c->user_func)(c->user_data); - c->active= 0; - err= setcontext(&c->base_context); - fprintf(stderr, "Aieie, setcontext() failed: %d (errno=%d)\n", err, errno); -} - - -int -my_context_continue(struct my_context *c) -{ - int err; - - if (!c->active) - return 0; - - DBUG_SWAP_CODE_STATE(&c->dbug_state); - err= swapcontext(&c->base_context, &c->spawned_context); - DBUG_SWAP_CODE_STATE(&c->dbug_state); - if (err) - { - fprintf(stderr, "Aieie, swapcontext() failed: %d (errno=%d)\n", - err, errno); - return -1; - } - - return c->active; -} - - -int -my_context_spawn(struct my_context *c, void (*f)(void *), void *d) -{ - int err; - union pass_void_ptr_as_2_int u; - - err= getcontext(&c->spawned_context); - if (err) - return -1; - c->spawned_context.uc_stack.ss_sp= c->stack; - c->spawned_context.uc_stack.ss_size= c->stack_size; - c->spawned_context.uc_link= NULL; - c->user_func= f; - c->user_data= d; - c->active= 1; - u.p= c; - makecontext(&c->spawned_context, my_context_spawn_internal, 2, - u.a[0], u.a[1]); - - return my_context_continue(c); -} - - -int -my_context_yield(struct my_context *c) -{ - int err; - - if (!c->active) - return -1; - - err= swapcontext(&c->spawned_context, &c->base_context); - if (err) - return -1; - return 0; -} - -int -my_context_init(struct my_context *c, size_t stack_size) -{ -#if SIZEOF_CHARP > SIZEOF_INT*2 -#error Error: Unable to store pointer in 2 ints on this architecture -#endif - bzero(c, sizeof(*c)); - if (!(c->stack= malloc(stack_size))) - return -1; /* Out of memory */ - c->stack_size= stack_size; -#ifdef HAVE_VALGRIND_MEMCHECK_H - c->valgrind_stack_id= - VALGRIND_STACK_REGISTER(c->stack, ((unsigned char *)(c->stack))+stack_size); -#endif - return 0; -} - -void -my_context_destroy(struct my_context *c) -{ - if (c->stack) - { -#ifdef HAVE_VALGRIND_MEMCHECK_H - VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id); -#endif - free(c->stack); - } - DBUG_FREE_CODE_STATE(&c->dbug_state); -} - -#endif /* MY_CONTEXT_USE_UCONTEXT */ - - -#ifdef MY_CONTEXT_USE_X86_64_GCC_ASM -/* - GCC-amd64 implementation of my_context. - - This is slightly optimized in the common case where we never yield - (eg. fetch next row and it is already fully received in buffer). In this - case we do not need to restore registers at return (though we still need to - save them as we cannot know if we will yield or not in advance). -*/ - -#include <stdint.h> -#include <stdlib.h> - -/* - Layout of saved registers etc. - Since this is accessed through gcc inline assembler, it is simpler to just - use numbers than to try to define nice constants or structs. - - 0 0 %rsp - 1 8 %rbp - 2 16 %rbx - 3 24 %r12 - 4 32 %r13 - 5 40 %r14 - 6 48 %r15 - 7 56 %rip for done - 8 64 %rip for yield/continue -*/ - -int -my_context_spawn(struct my_context *c, void (*f)(void *), void *d) -{ - int ret; - - DBUG_SWAP_CODE_STATE(&c->dbug_state); - - /* - There are 6 callee-save registers we need to save and restore when - suspending and continuing, plus stack pointer %rsp and instruction pointer - %rip. - - However, if we never suspend, the user-supplied function will in any case - restore the 6 callee-save registers, so we can avoid restoring them in - this case. - */ - __asm__ __volatile__ - ( - "movq %%rsp, (%[save])\n\t" - "movq %[stack], %%rsp\n\t" -#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __clang__) && \ - !defined(__INTEL_COMPILER) - /* - This emits a DWARF DW_CFA_undefined directive to make the return address - undefined. This indicates that this is the top of the stack frame, and - helps tools that use DWARF stack unwinding to obtain stack traces. - (I use numeric constant to avoid a dependency on libdwarf includes). - */ - ".cfi_escape 0x07, 16\n\t" -#endif - "movq %%rbp, 8(%[save])\n\t" - "movq %%rbx, 16(%[save])\n\t" - "movq %%r12, 24(%[save])\n\t" - "movq %%r13, 32(%[save])\n\t" - "movq %%r14, 40(%[save])\n\t" - "movq %%r15, 48(%[save])\n\t" - "leaq 1f(%%rip), %%rax\n\t" - "leaq 2f(%%rip), %%rcx\n\t" - "movq %%rax, 56(%[save])\n\t" - "movq %%rcx, 64(%[save])\n\t" - /* - Constraint below puts the argument to the user function into %rdi, as - needed for the calling convention. - */ - "callq *%[f]\n\t" - "jmpq *56(%[save])\n" - /* - Come here when operation is done. - We do not need to restore callee-save registers, as the called function - will do this for us if needed. - */ - "1:\n\t" - "movq (%[save]), %%rsp\n\t" - "xorl %[ret], %[ret]\n\t" - "jmp 3f\n" - /* Come here when operation was suspended. */ - "2:\n\t" - "movl $1, %[ret]\n" - "3:\n" - : [ret] "=a" (ret), - [f] "+S" (f), - /* Need this in %rdi to follow calling convention. */ - [d] "+D" (d) - : [stack] "a" (c->stack_top), - /* Need this in callee-save register to preserve in function call. */ - [save] "b" (&c->save[0]) - : "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc" - ); - - DBUG_SWAP_CODE_STATE(&c->dbug_state); - - return ret; -} - -int -my_context_continue(struct my_context *c) -{ - int ret; - - DBUG_SWAP_CODE_STATE(&c->dbug_state); - - __asm__ __volatile__ - ( - "movq (%[save]), %%rax\n\t" - "movq %%rsp, (%[save])\n\t" - "movq %%rax, %%rsp\n\t" - "movq 8(%[save]), %%rax\n\t" - "movq %%rbp, 8(%[save])\n\t" - "movq %%rax, %%rbp\n\t" - "movq 24(%[save]), %%rax\n\t" - "movq %%r12, 24(%[save])\n\t" - "movq %%rax, %%r12\n\t" - "movq 32(%[save]), %%rax\n\t" - "movq %%r13, 32(%[save])\n\t" - "movq %%rax, %%r13\n\t" - "movq 40(%[save]), %%rax\n\t" - "movq %%r14, 40(%[save])\n\t" - "movq %%rax, %%r14\n\t" - "movq 48(%[save]), %%rax\n\t" - "movq %%r15, 48(%[save])\n\t" - "movq %%rax, %%r15\n\t" - - "leaq 1f(%%rip), %%rax\n\t" - "leaq 2f(%%rip), %%rcx\n\t" - "movq %%rax, 56(%[save])\n\t" - "movq 64(%[save]), %%rax\n\t" - "movq %%rcx, 64(%[save])\n\t" - - "movq 16(%[save]), %%rcx\n\t" - "movq %%rbx, 16(%[save])\n\t" - "movq %%rcx, %%rbx\n\t" - - "jmpq *%%rax\n" - /* - Come here when operation is done. - Be sure to use the same callee-save register for %[save] here and in - my_context_spawn(), so we preserve the value correctly at this point. - */ - "1:\n\t" - "movq (%[save]), %%rsp\n\t" - "movq 8(%[save]), %%rbp\n\t" - /* %rbx is preserved from my_context_spawn() in this case. */ - "movq 24(%[save]), %%r12\n\t" - "movq 32(%[save]), %%r13\n\t" - "movq 40(%[save]), %%r14\n\t" - "movq 48(%[save]), %%r15\n\t" - "xorl %[ret], %[ret]\n\t" - "jmp 3f\n" - /* Come here when operation is suspended. */ - "2:\n\t" - "movl $1, %[ret]\n" - "3:\n" - : [ret] "=a" (ret) - : /* Need this in callee-save register to preserve in function call. */ - [save] "b" (&c->save[0]) - : "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "memory", "cc" - ); - - DBUG_SWAP_CODE_STATE(&c->dbug_state); - - return ret; -} - -int -my_context_yield(struct my_context *c) -{ - uint64_t *save= &c->save[0]; - __asm__ __volatile__ - ( - "movq (%[save]), %%rax\n\t" - "movq %%rsp, (%[save])\n\t" - "movq %%rax, %%rsp\n\t" - "movq 8(%[save]), %%rax\n\t" - "movq %%rbp, 8(%[save])\n\t" - "movq %%rax, %%rbp\n\t" - "movq 16(%[save]), %%rax\n\t" - "movq %%rbx, 16(%[save])\n\t" - "movq %%rax, %%rbx\n\t" - "movq 24(%[save]), %%rax\n\t" - "movq %%r12, 24(%[save])\n\t" - "movq %%rax, %%r12\n\t" - "movq 32(%[save]), %%rax\n\t" - "movq %%r13, 32(%[save])\n\t" - "movq %%rax, %%r13\n\t" - "movq 40(%[save]), %%rax\n\t" - "movq %%r14, 40(%[save])\n\t" - "movq %%rax, %%r14\n\t" - "movq 48(%[save]), %%rax\n\t" - "movq %%r15, 48(%[save])\n\t" - "movq %%rax, %%r15\n\t" - "movq 64(%[save]), %%rax\n\t" - "leaq 1f(%%rip), %%rcx\n\t" - "movq %%rcx, 64(%[save])\n\t" - - "jmpq *%%rax\n" - - "1:\n" - : [save] "+D" (save) - : - : "rax", "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "memory", "cc" - ); - return 0; -} - -int -my_context_init(struct my_context *c, size_t stack_size) -{ - bzero(c, sizeof(*c)); - - if (!(c->stack_bot= malloc(stack_size))) - return -1; /* Out of memory */ - /* - The x86_64 ABI specifies 16-byte stack alignment. - Also put two zero words at the top of the stack. - */ - c->stack_top= (void *) - (( ((intptr)c->stack_bot + stack_size) & ~(intptr)0xf) - 16); - bzero(c->stack_top, 16); - -#ifdef HAVE_VALGRIND_MEMCHECK_H - c->valgrind_stack_id= - VALGRIND_STACK_REGISTER(c->stack_bot, c->stack_top); -#endif - return 0; -} - -void -my_context_destroy(struct my_context *c) -{ - if (c->stack_bot) - { - free(c->stack_bot); -#ifdef HAVE_VALGRIND_MEMCHECK_H - VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id); -#endif - } - DBUG_FREE_CODE_STATE(&c->dbug_state); -} - -#endif /* MY_CONTEXT_USE_X86_64_GCC_ASM */ - - -#ifdef MY_CONTEXT_USE_I386_GCC_ASM -/* - GCC-i386 implementation of my_context. - - This is slightly optimized in the common case where we never yield - (eg. fetch next row and it is already fully received in buffer). In this - case we do not need to restore registers at return (though we still need to - save them as we cannot know if we will yield or not in advance). -*/ - -#include <stdint.h> -#include <stdlib.h> - -/* - Layout of saved registers etc. - Since this is accessed through gcc inline assembler, it is simpler to just - use numbers than to try to define nice constants or structs. - - 0 0 %esp - 1 4 %ebp - 2 8 %ebx - 3 12 %esi - 4 16 %edi - 5 20 %eip for done - 6 24 %eip for yield/continue -*/ - -int -my_context_spawn(struct my_context *c, void (*f)(void *), void *d) -{ - int ret; - - DBUG_SWAP_CODE_STATE(&c->dbug_state); - - /* - There are 4 callee-save registers we need to save and restore when - suspending and continuing, plus stack pointer %esp and instruction pointer - %eip. - - However, if we never suspend, the user-supplied function will in any case - restore the 4 callee-save registers, so we can avoid restoring them in - this case. - */ - __asm__ __volatile__ - ( - "movl %%esp, (%[save])\n\t" - "movl %[stack], %%esp\n\t" -#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) && !defined(__INTEL_COMPILER) - /* - This emits a DWARF DW_CFA_undefined directive to make the return address - undefined. This indicates that this is the top of the stack frame, and - helps tools that use DWARF stack unwinding to obtain stack traces. - (I use numeric constant to avoid a dependency on libdwarf includes). - */ - ".cfi_escape 0x07, 8\n\t" -#endif - /* Push the parameter on the stack. */ - "pushl %[d]\n\t" - "movl %%ebp, 4(%[save])\n\t" - "movl %%ebx, 8(%[save])\n\t" - "movl %%esi, 12(%[save])\n\t" - "movl %%edi, 16(%[save])\n\t" - /* Get label addresses in -fPIC-compatible way (no pc-relative on 32bit) */ - "call 1f\n" - "1:\n\t" - "popl %%eax\n\t" - "addl $(2f-1b), %%eax\n\t" - "movl %%eax, 20(%[save])\n\t" - "addl $(3f-2f), %%eax\n\t" - "movl %%eax, 24(%[save])\n\t" - "call *%[f]\n\t" - "jmp *20(%[save])\n" - /* - Come here when operation is done. - We do not need to restore callee-save registers, as the called function - will do this for us if needed. - */ - "2:\n\t" - "movl (%[save]), %%esp\n\t" - "xorl %[ret], %[ret]\n\t" - "jmp 4f\n" - /* Come here when operation was suspended. */ - "3:\n\t" - "movl $1, %[ret]\n" - "4:\n" - : [ret] "=a" (ret), - [f] "+c" (f), - [d] "+d" (d) - : [stack] "a" (c->stack_top), - /* Need this in callee-save register to preserve across function call. */ - [save] "D" (&c->save[0]) - : "memory", "cc" - ); - - DBUG_SWAP_CODE_STATE(&c->dbug_state); - - return ret; -} - -int -my_context_continue(struct my_context *c) -{ - int ret; - - DBUG_SWAP_CODE_STATE(&c->dbug_state); - - __asm__ __volatile__ - ( - "movl (%[save]), %%eax\n\t" - "movl %%esp, (%[save])\n\t" - "movl %%eax, %%esp\n\t" - "movl 4(%[save]), %%eax\n\t" - "movl %%ebp, 4(%[save])\n\t" - "movl %%eax, %%ebp\n\t" - "movl 8(%[save]), %%eax\n\t" - "movl %%ebx, 8(%[save])\n\t" - "movl %%eax, %%ebx\n\t" - "movl 12(%[save]), %%eax\n\t" - "movl %%esi, 12(%[save])\n\t" - "movl %%eax, %%esi\n\t" - - "movl 24(%[save]), %%eax\n\t" - "call 1f\n" - "1:\n\t" - "popl %%ecx\n\t" - "addl $(2f-1b), %%ecx\n\t" - "movl %%ecx, 20(%[save])\n\t" - "addl $(3f-2f), %%ecx\n\t" - "movl %%ecx, 24(%[save])\n\t" - - /* Must restore %edi last as it is also our %[save] register. */ - "movl 16(%[save]), %%ecx\n\t" - "movl %%edi, 16(%[save])\n\t" - "movl %%ecx, %%edi\n\t" - - "jmp *%%eax\n" - /* - Come here when operation is done. - Be sure to use the same callee-save register for %[save] here and in - my_context_spawn(), so we preserve the value correctly at this point. - */ - "2:\n\t" - "movl (%[save]), %%esp\n\t" - "movl 4(%[save]), %%ebp\n\t" - "movl 8(%[save]), %%ebx\n\t" - "movl 12(%[save]), %%esi\n\t" - "movl 16(%[save]), %%edi\n\t" - "xorl %[ret], %[ret]\n\t" - "jmp 4f\n" - /* Come here when operation is suspended. */ - "3:\n\t" - "movl $1, %[ret]\n" - "4:\n" - : [ret] "=a" (ret) - : /* Need this in callee-save register to preserve in function call. */ - [save] "D" (&c->save[0]) - : "ecx", "edx", "memory", "cc" - ); - - DBUG_SWAP_CODE_STATE(&c->dbug_state); - - return ret; -} - -int -my_context_yield(struct my_context *c) -{ - uint64_t *save= &c->save[0]; - __asm__ __volatile__ - ( - "movl (%[save]), %%eax\n\t" - "movl %%esp, (%[save])\n\t" - "movl %%eax, %%esp\n\t" - "movl 4(%[save]), %%eax\n\t" - "movl %%ebp, 4(%[save])\n\t" - "movl %%eax, %%ebp\n\t" - "movl 8(%[save]), %%eax\n\t" - "movl %%ebx, 8(%[save])\n\t" - "movl %%eax, %%ebx\n\t" - "movl 12(%[save]), %%eax\n\t" - "movl %%esi, 12(%[save])\n\t" - "movl %%eax, %%esi\n\t" - "movl 16(%[save]), %%eax\n\t" - "movl %%edi, 16(%[save])\n\t" - "movl %%eax, %%edi\n\t" - - "movl 24(%[save]), %%eax\n\t" - "call 1f\n" - "1:\n\t" - "popl %%ecx\n\t" - "addl $(2f-1b), %%ecx\n\t" - "movl %%ecx, 24(%[save])\n\t" - - "jmp *%%eax\n" - - "2:\n" - : [save] "+d" (save) - : - : "eax", "ecx", "memory", "cc" - ); - return 0; -} - -int -my_context_init(struct my_context *c, size_t stack_size) -{ - bzero(c, sizeof(*c)); - if (!(c->stack_bot= malloc(stack_size))) - return -1; /* Out of memory */ - c->stack_top= (void *) - (( ((intptr)c->stack_bot + stack_size) & ~(intptr)0xf) - 16); - bzero(c->stack_top, 16); - -#ifdef HAVE_VALGRIND_MEMCHECK_H - c->valgrind_stack_id= - VALGRIND_STACK_REGISTER(c->stack_bot, c->stack_top); -#endif - return 0; -} - -void -my_context_destroy(struct my_context *c) -{ - if (c->stack_bot) - { - free(c->stack_bot); -#ifdef HAVE_VALGRIND_MEMCHECK_H - VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id); -#endif - } - DBUG_FREE_CODE_STATE(&c->dbug_state); -} - -#endif /* MY_CONTEXT_USE_I386_GCC_ASM */ - - -#ifdef MY_CONTEXT_USE_WIN32_FIBERS -int -my_context_yield(struct my_context *c) -{ - c->return_value= 1; - SwitchToFiber(c->app_fiber); - return 0; -} - - -static void WINAPI -my_context_trampoline(void *p) -{ - struct my_context *c= (struct my_context *)p; - /* - Reuse the Fiber by looping infinitely, each time we are scheduled we - spawn the appropriate function and switch back when it is done. - - This way we avoid the overhead of CreateFiber() for every asynchroneous - operation. - */ - for(;;) - { - (*(c->user_func))(c->user_arg); - c->return_value= 0; - SwitchToFiber(c->app_fiber); - } -} - -int -my_context_init(struct my_context *c, size_t stack_size) -{ - bzero(c, sizeof(*c)); - c->lib_fiber= CreateFiber(stack_size, my_context_trampoline, c); - if (c->lib_fiber) - return 0; - return -1; -} - -void -my_context_destroy(struct my_context *c) -{ - DBUG_FREE_CODE_STATE(&c->dbug_state); - if (c->lib_fiber) - { - DeleteFiber(c->lib_fiber); - c->lib_fiber= NULL; - } -} - -int -my_context_spawn(struct my_context *c, void (*f)(void *), void *d) -{ - c->user_func= f; - c->user_arg= d; - return my_context_continue(c); -} - -int -my_context_continue(struct my_context *c) -{ - /* - This seems to be a common trick to run ConvertThreadToFiber() only on the - first occurrence in a thread, in a way that works on multiple Windows - versions. - */ - void *current_fiber= GetCurrentFiber(); - if (current_fiber == NULL || current_fiber == (void *)0x1e00) - current_fiber= ConvertThreadToFiber(c); - c->app_fiber= current_fiber; - DBUG_SWAP_CODE_STATE(&c->dbug_state); - SwitchToFiber(c->lib_fiber); - DBUG_SWAP_CODE_STATE(&c->dbug_state); - - return c->return_value; -} - -#endif /* MY_CONTEXT_USE_WIN32_FIBERS */ - -#ifdef MY_CONTEXT_DISABLE -int -my_context_continue(struct my_context *c __attribute__((unused))) -{ - return -1; -} - - -int -my_context_spawn(struct my_context *c __attribute__((unused)), - void (*f)(void *) __attribute__((unused)), - void *d __attribute__((unused))) -{ - return -1; -} - - -int -my_context_yield(struct my_context *c __attribute__((unused))) -{ - return -1; -} - -int -my_context_init(struct my_context *c __attribute__((unused)), - size_t stack_size __attribute__((unused))) -{ - return -1; /* Out of memory */ -} - -void -my_context_destroy(struct my_context *c __attribute__((unused))) -{ -} - -#endif diff --git a/sql-common/client.c b/sql-common/client.c index c12b3ef5c0a..5e072a8b538 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -100,8 +100,6 @@ my_bool net_flush(NET *net); #include <ssl_compat.h> #include <sql_common.h> #include <mysql/client_plugin.h> -#include <my_context.h> -#include <mysql_async.h> typedef enum { ALWAYS_ACCEPT, /* heuristics is disabled, use CLIENT_LOCAL_FILES */ @@ -2607,20 +2605,11 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len, 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) { 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); } @@ -2787,7 +2776,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, bzero((char*) &UNIXaddr, sizeof(UNIXaddr)); UNIXaddr.sun_family= AF_UNIX; 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))) { 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, } 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); /* 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, 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))) { vio_delete(net->vio); @@ -3195,42 +3181,16 @@ error: /* Free alloced memory */ end_server(mysql); mysql_close_free(mysql); - if (!(client_flag & CLIENT_REMEMBER_OPTIONS) && - !(mysql->options.extension && mysql->options.extension->async_context)) + if (!(client_flag & CLIENT_REMEMBER_OPTIONS)) mysql_close_free_options(mysql); } 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) { MYSQL tmp_mysql; - struct my_hook_data hook_data; - struct mysql_async_context *ctxt= NULL; DBUG_ENTER("mysql_reconnect"); DBUG_ASSERT(mysql); DBUG_PRINT("enter", ("mysql->reconnect: %d", mysql->reconnect)); @@ -3247,31 +3207,11 @@ my_bool mysql_reconnect(MYSQL *mysql) tmp_mysql.options= mysql->options; 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, mysql->db, mysql->port, mysql->unix_socket, 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; strmov(mysql->net.last_error, tmp_mysql.net.last_error); strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate); @@ -3282,15 +3222,11 @@ my_bool mysql_reconnect(MYSQL *mysql) DBUG_PRINT("error", ("mysql_set_character_set() failed")); bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options)); mysql_close(&tmp_mysql); - if (ctxt) - my_context_install_suspend_resume_hook(ctxt, NULL, NULL); mysql->net.last_errno= tmp_mysql.net.last_errno; strmov(mysql->net.last_error, tmp_mysql.net.last_error); strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate); DBUG_RETURN(1); } - if (ctxt) - my_context_install_suspend_resume_hook(ctxt, NULL, NULL); DBUG_PRINT("info", ("reconnect succeeded")); tmp_mysql.reconnect= 1; @@ -3365,15 +3301,9 @@ static void mysql_close_free_options(MYSQL *mysql) #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ 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->default_auth); my_hash_free(&mysql->options.extension->connection_attributes); - if (ctxt) - { - my_context_destroy(&ctxt->async_context); - my_free(ctxt); - } my_free(mysql->options.extension); } bzero((char*) &mysql->options,sizeof(mysql->options)); @@ -3806,15 +3736,9 @@ mysql_fetch_lengths(MYSQL_RES *res) return res->lengths; } - -#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15) - int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) { - struct mysql_async_context *ctxt; - size_t stacksize; - DBUG_ENTER("mysql_options"); DBUG_PRINT("enter",("option: %d",(int) option)); switch (option) { @@ -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; break; 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; case MYSQL_OPT_SSL_KEY: SET_SSL_PATH_OPTION(&mysql->options,ssl_key, arg); diff --git a/sql-common/mysql_async.c b/sql-common/mysql_async.c deleted file mode 100644 index a19955c49de..00000000000 --- a/sql-common/mysql_async.c +++ /dev/null @@ -1,1995 +0,0 @@ -/* - 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/>. -*/ - -/* - MySQL non-blocking client library functions. -*/ - -#include "my_global.h" -#include "my_sys.h" -#include "mysql.h" -#include "errmsg.h" -#include "sql_common.h" -#include "my_context.h" -#include "violite.h" -#include "mysql_async.h" - - -#ifdef __WIN__ -/* - Windows does not support MSG_DONTWAIT for send()/recv(). So we need to ensure - that the socket is non-blocking at the start of every operation. -*/ -#define WIN_SET_NONBLOCKING(mysql) { \ - my_bool old_mode; \ - if ((mysql)->net.vio) vio_blocking((mysql)->net.vio, FALSE, &old_mode); \ - } -#else -#define WIN_SET_NONBLOCKING(mysql) -#endif - - -void -my_context_install_suspend_resume_hook(struct mysql_async_context *b, - void (*hook)(my_bool, void *), - void *user_data) -{ - b->suspend_resume_hook= hook; - b->suspend_resume_hook_user_data= user_data; -} - - -/* Asynchronous connect(); socket must already be set non-blocking. */ -int -my_connect_async(struct mysql_async_context *b, my_socket fd, - const struct sockaddr *name, uint namelen, int vio_timeout) -{ - int res; - size_socket s_err_size; - - /* Make the socket non-blocking. */ -#ifdef __WIN__ - ulong arg= 1; - ioctlsocket(fd, FIONBIO, (void *)&arg); -#else - fcntl(fd, F_SETFL, O_NONBLOCK); -#endif - - b->events_to_wait_for= 0; - /* - Start to connect asynchronously. - If this will block, we suspend the call and return control to the - application context. The application will then resume us when the socket - polls ready for write, indicating that the connection attempt completed. - */ - res= connect(fd, name, namelen); - if (res != 0) - { -#ifdef __WIN__ - int wsa_err= WSAGetLastError(); - if (wsa_err != WSAEWOULDBLOCK) - return res; - b->events_to_wait_for|= MYSQL_WAIT_EXCEPT; -#else - int err= errno; - if (err != EINPROGRESS && err != EALREADY && err != EAGAIN) - return res; -#endif - b->events_to_wait_for|= MYSQL_WAIT_WRITE; - if (vio_timeout >= 0) - { - b->timeout_value= vio_timeout; - b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT; - } - else - b->timeout_value= 0; - if (b->suspend_resume_hook) - (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data); - my_context_yield(&b->async_context); - if (b->suspend_resume_hook) - (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); - if (b->events_occurred & MYSQL_WAIT_TIMEOUT) - return -1; - - s_err_size= sizeof(res); - if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0) - return -1; - if (res) - { - errno= res; - return -1; - } - } - return res; -} - -#define IS_BLOCKING_ERROR() \ - IF_WIN(WSAGetLastError() != WSAEWOULDBLOCK, \ - (errno != EAGAIN && errno != EINTR)) - -#ifdef _AIX -#ifndef MSG_DONTWAIT -#define MSG_DONTWAIT 0 -#endif -#endif - -ssize_t -my_recv_async(struct mysql_async_context *b, my_socket fd, - unsigned char *buf, size_t size, int timeout) -{ - ssize_t res; - - for (;;) - { - res= recv(fd, buf, (int)size, IF_WIN(0, MSG_DONTWAIT)); - if (res >= 0 || IS_BLOCKING_ERROR()) - return res; - b->events_to_wait_for= MYSQL_WAIT_READ; - if (timeout >= 0) - { - b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT; - b->timeout_value= timeout; - } - if (b->suspend_resume_hook) - (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data); - my_context_yield(&b->async_context); - if (b->suspend_resume_hook) - (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); - if (b->events_occurred & MYSQL_WAIT_TIMEOUT) - return -1; - } -} - - -ssize_t -my_send_async(struct mysql_async_context *b, my_socket fd, - const unsigned char *buf, size_t size, int timeout) -{ - ssize_t res; - - for (;;) - { - res= send(fd, buf, (int)size, IF_WIN(0, MSG_DONTWAIT)); - if (res >= 0 || IS_BLOCKING_ERROR()) - return res; - b->events_to_wait_for= MYSQL_WAIT_WRITE; - if (timeout >= 0) - { - b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT; - b->timeout_value= timeout; - } - if (b->suspend_resume_hook) - (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data); - my_context_yield(&b->async_context); - if (b->suspend_resume_hook) - (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); - if (b->events_occurred & MYSQL_WAIT_TIMEOUT) - return -1; - } -} - - -my_bool -my_io_wait_async(struct mysql_async_context *b, enum enum_vio_io_event event, - int timeout) -{ - switch (event) - { - case VIO_IO_EVENT_READ: - b->events_to_wait_for = MYSQL_WAIT_READ; - break; - case VIO_IO_EVENT_WRITE: - b->events_to_wait_for = MYSQL_WAIT_WRITE; - break; - case VIO_IO_EVENT_CONNECT: - b->events_to_wait_for = MYSQL_WAIT_WRITE | IF_WIN(0, MYSQL_WAIT_EXCEPT); - break; - } - - if (timeout >= 0) - { - b->events_to_wait_for |= MYSQL_WAIT_TIMEOUT; - b->timeout_value= timeout; - } - if (b->suspend_resume_hook) - (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data); - my_context_yield(&b->async_context); - if (b->suspend_resume_hook) - (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); - return (b->events_occurred & MYSQL_WAIT_TIMEOUT) ? 0 : 1; -} - - -#ifdef HAVE_OPENSSL -static my_bool -my_ssl_async_check_result(int res, struct mysql_async_context *b, SSL *ssl) -{ - int ssl_err; - b->events_to_wait_for= 0; - if (res >= 0) - return 1; - ssl_err= SSL_get_error(ssl, res); - if (ssl_err == SSL_ERROR_WANT_READ) - b->events_to_wait_for|= MYSQL_WAIT_READ; - else if (ssl_err == SSL_ERROR_WANT_WRITE) - b->events_to_wait_for|= MYSQL_WAIT_WRITE; - else - return 1; - if (b->suspend_resume_hook) - (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data); - my_context_yield(&b->async_context); - if (b->suspend_resume_hook) - (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); - return 0; -} - -int -my_ssl_read_async(struct mysql_async_context *b, SSL *ssl, - void *buf, int size) -{ - int res; - - for (;;) - { - res= SSL_read(ssl, buf, size); - if (my_ssl_async_check_result(res, b, ssl)) - return res; - } -} - -int -my_ssl_write_async(struct mysql_async_context *b, SSL *ssl, - const void *buf, int size) -{ - int res; - - for (;;) - { - res= SSL_write(ssl, buf, size); - if (my_ssl_async_check_result(res, b, ssl)) - return res; - } -} -#endif /* HAVE_OPENSSL */ - -/* - Legacy support of the MariaDB 5.5 version, where timeouts where only in - seconds resolution. Applications that use this will be asked to set a timeout - at the nearest higher whole-seconds value. -*/ -unsigned int STDCALL -mysql_get_timeout_value(const MYSQL *mysql) -{ - unsigned int timeout= mysql->options.extension->async_context->timeout_value; - /* Avoid overflow. */ - if (timeout > UINT_MAX - 999) - return (timeout - 1)/1000 + 1; - else - return (timeout+999)/1000; -} - - -unsigned int STDCALL -mysql_get_timeout_value_ms(const MYSQL *mysql) -{ - return mysql->options.extension->async_context->timeout_value; -} - - -/* - Now create non-blocking definitions for all the calls that may block. - - Each call FOO gives rise to FOO_start() that prepares the MYSQL object for - doing non-blocking calls that can suspend operation mid-way, and then starts - the call itself. And a FOO_start_internal trampoline to assist with running - the real call in a co-routine that can be suspended. And a FOO_cont() that - can continue a suspended operation. -*/ - -#define MK_ASYNC_INTERNAL_BODY(call, invoke_args, mysql_val, ret_type, ok_val)\ - struct call ## _params *parms= (struct call ## _params *)d; \ - ret_type ret; \ - struct mysql_async_context *b= \ - (mysql_val)->options.extension->async_context; \ - \ - ret= call invoke_args; \ - b->ret_result. ok_val = ret; \ - b->events_to_wait_for= 0; - -#define MK_ASYNC_START_BODY(call, mysql_val, parms_assign, err_val, ok_val, extra1) \ - int res; \ - struct mysql_async_context *b; \ - struct call ## _params parms; \ - \ - extra1 \ - b= mysql_val->options.extension->async_context; \ - parms_assign \ - \ - b->active= 1; \ - res= my_context_spawn(&b->async_context, call ## _start_internal, &parms); \ - b->active= b->suspended= 0; \ - if (res > 0) \ - { \ - /* Suspended. */ \ - b->suspended= 1; \ - return b->events_to_wait_for; \ - } \ - if (res < 0) \ - { \ - set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \ - *ret= err_val; \ - } \ - else \ - *ret= b->ret_result. ok_val; \ - return 0; - -#define MK_ASYNC_CONT_BODY(mysql_val, err_val, ok_val) \ - int res; \ - struct mysql_async_context *b= \ - (mysql_val)->options.extension->async_context; \ - if (!b->suspended) \ - { \ - set_mysql_error((mysql_val), CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); \ - *ret= err_val; \ - return 0; \ - } \ - \ - b->active= 1; \ - b->events_occurred= ready_status; \ - res= my_context_continue(&b->async_context); \ - b->active= 0; \ - if (res > 0) \ - return b->events_to_wait_for; /* (Still) suspended */ \ - b->suspended= 0; \ - if (res < 0) \ - { \ - set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \ - *ret= err_val; \ - } \ - else \ - *ret= b->ret_result. ok_val; /* Finished. */ \ - return 0; - -#define MK_ASYNC_INTERNAL_BODY_VOID_RETURN(call, invoke_args, mysql_val) \ - struct call ## _params *parms= (struct call ## _params *)d; \ - struct mysql_async_context *b= \ - (mysql_val)->options.extension->async_context; \ - \ - call invoke_args; \ - b->events_to_wait_for= 0; - -#define MK_ASYNC_START_BODY_VOID_RETURN(call, mysql_val, parms_assign, extra1)\ - int res; \ - struct mysql_async_context *b; \ - struct call ## _params parms; \ - \ - extra1 \ - b= mysql_val->options.extension->async_context; \ - parms_assign \ - \ - b->active= 1; \ - res= my_context_spawn(&b->async_context, call ## _start_internal, &parms); \ - b->active= b->suspended= 0; \ - if (res > 0) \ - { \ - /* Suspended. */ \ - b->suspended= 1; \ - return b->events_to_wait_for; \ - } \ - if (res < 0) \ - set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \ - return 0; - -#define MK_ASYNC_CONT_BODY_VOID_RETURN(mysql_val) \ - int res; \ - struct mysql_async_context *b= \ - (mysql_val)->options.extension->async_context; \ - if (!b->suspended) \ - { \ - set_mysql_error((mysql_val), CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); \ - return 0; \ - } \ - \ - b->active= 1; \ - b->events_occurred= ready_status; \ - res= my_context_continue(&b->async_context); \ - b->active= 0; \ - if (res > 0) \ - return b->events_to_wait_for; /* (Still) suspended */ \ - b->suspended= 0; \ - if (res < 0) \ - set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \ - return 0; - - -/* Structure used to pass parameters from mysql_real_connect_start(). */ -struct mysql_real_connect_params { - MYSQL *mysql; - const char *host; - const char *user; - const char *passwd; - const char *db; - unsigned int port; - const char *unix_socket; - unsigned long client_flags; -}; -static void -mysql_real_connect_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_real_connect, - (parms->mysql, parms->host, parms->user, parms->passwd, parms->db, - parms->port, parms->unix_socket, parms->client_flags), - parms->mysql, - MYSQL *, - r_ptr) -} -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 client_flags) -{ -MK_ASYNC_START_BODY( - mysql_real_connect, - mysql, - { - parms.mysql= mysql; - parms.host= host; - parms.user= user; - parms.passwd= passwd; - parms.db= db; - parms.port= port; - parms.unix_socket= unix_socket; - /* - async wrapper enforce the CLIENT_REMEMBER_OPTIONS flag to be - functional (otherwise it can't operate) - */ - parms.client_flags= client_flags | CLIENT_REMEMBER_OPTIONS; - }, - NULL, - r_ptr, - /* Nothing */) -} -int STDCALL -mysql_real_connect_cont(MYSQL **ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - NULL, - r_ptr) -} - -/* Structure used to pass parameters from mysql_real_query_start(). */ -struct mysql_real_query_params { - MYSQL *mysql; - const char *stmt_str; - unsigned long length; -}; -static void -mysql_real_query_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_real_query, - (parms->mysql, parms->stmt_str, parms->length), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_real_query_start(int *ret, MYSQL *mysql, const char *stmt_str, unsigned long length) -{ -MK_ASYNC_START_BODY( - mysql_real_query, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.stmt_str= stmt_str; - parms.length= length; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_real_query_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_fetch_row_start(). */ -struct mysql_fetch_row_params { - MYSQL_RES *result; -}; -static void -mysql_fetch_row_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_fetch_row, - (parms->result), - parms->result->handle, - MYSQL_ROW, - r_ptr) -} -int STDCALL -mysql_fetch_row_start(MYSQL_ROW *ret, MYSQL_RES *result) -{ -MK_ASYNC_START_BODY( - mysql_fetch_row, - result->handle, - { - WIN_SET_NONBLOCKING(result->handle) - parms.result= result; - }, - NULL, - r_ptr, - /* - If we already fetched all rows from server (eg. mysql_store_result()), - then result->handle will be NULL and we cannot suspend. But that is fine, - since in this case mysql_fetch_row cannot block anyway. Just return - directly. - */ - if (!result->handle) - { - *ret= mysql_fetch_row(result); - return 0; - }) -} -int STDCALL -mysql_fetch_row_cont(MYSQL_ROW *ret, MYSQL_RES *result, int ready_status) -{ -MK_ASYNC_CONT_BODY( - result->handle, - NULL, - r_ptr) -} - -/* Structure used to pass parameters from mysql_set_character_set_start(). */ -struct mysql_set_character_set_params { - MYSQL *mysql; - const char *csname; -}; -static void -mysql_set_character_set_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_set_character_set, - (parms->mysql, parms->csname), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_set_character_set_start(int *ret, MYSQL *mysql, const char *csname) -{ -MK_ASYNC_START_BODY( - mysql_set_character_set, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.csname= csname; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_set_character_set_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_sekect_db_start(). */ -struct mysql_select_db_params { - MYSQL *mysql; - const char *db; -}; -static void -mysql_select_db_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_select_db, - (parms->mysql, parms->db), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_select_db_start(int *ret, MYSQL *mysql, const char *db) -{ -MK_ASYNC_START_BODY( - mysql_select_db, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.db= db; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_select_db_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_send_query_start(). */ -struct mysql_send_query_params { - MYSQL *mysql; - const char *q; - unsigned long length; -}; -static void -mysql_send_query_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_send_query, - (parms->mysql, parms->q, parms->length), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_send_query_start(int *ret, MYSQL *mysql, const char *q, unsigned long length) -{ -MK_ASYNC_START_BODY( - mysql_send_query, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.q= q; - parms.length= length; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_send_query_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_store_result_start(). */ -struct mysql_store_result_params { - MYSQL *mysql; -}; -static void -mysql_store_result_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_store_result, - (parms->mysql), - parms->mysql, - MYSQL_RES *, - r_ptr) -} -int STDCALL -mysql_store_result_start(MYSQL_RES **ret, MYSQL *mysql) -{ -MK_ASYNC_START_BODY( - mysql_store_result, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - }, - NULL, - r_ptr, - /* Nothing */) -} -int STDCALL -mysql_store_result_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - NULL, - r_ptr) -} - -/* Structure used to pass parameters from mysql_free_result_start(). */ -struct mysql_free_result_params { - MYSQL_RES *result; -}; -static void -mysql_free_result_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY_VOID_RETURN( - mysql_free_result, - (parms->result), - parms->result->handle) -} -int STDCALL -mysql_free_result_start(MYSQL_RES *result) -{ -MK_ASYNC_START_BODY_VOID_RETURN( - mysql_free_result, - result->handle, - { - WIN_SET_NONBLOCKING(result->handle) - parms.result= result; - }, - /* - mysql_free_result() can have NULL in result->handle (this happens when all - rows have been fetched and mysql_fetch_row() returned NULL.) - So we cannot suspend, but it does not matter, as in this case - mysql_free_result() cannot block. - It is also legitimate to have NULL result, which will do nothing. - */ - if (!result || !result->handle) - { - mysql_free_result(result); - return 0; - }) -} -int STDCALL -mysql_free_result_cont(MYSQL_RES *result, int ready_status) -{ -MK_ASYNC_CONT_BODY_VOID_RETURN(result->handle) -} - -/* Structure used to pass parameters from mysql_close_slow_part_start(). */ -struct mysql_close_slow_part_params { - MYSQL *sock; -}; -/* - We need special handling for mysql_close(), as the first part may block, - while the last part needs to free our extra library context stack. - - So we do the first part (mysql_close_slow_part()) non-blocking, but the last - part blocking. -*/ -static void -mysql_close_slow_part_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY_VOID_RETURN( - mysql_close_slow_part, - (parms->sock), - parms->sock) -} -int STDCALL -mysql_close_slow_part_start(MYSQL *sock) -{ -MK_ASYNC_START_BODY_VOID_RETURN( - mysql_close_slow_part, - sock, - { - WIN_SET_NONBLOCKING(sock) - parms.sock= sock; - }, - /* Nothing */) -} -int STDCALL -mysql_close_slow_part_cont(MYSQL *sock, int ready_status) -{ -MK_ASYNC_CONT_BODY_VOID_RETURN(sock) -} -int STDCALL -mysql_close_start(MYSQL *sock) -{ - int res; - - /* It is legitimate to have NULL sock argument, which will do nothing. */ - if (sock) - { - res= mysql_close_slow_part_start(sock); - /* If we need to block, return now and do the rest in mysql_close_cont(). */ - if (res) - return res; - } - mysql_close(sock); - return 0; -} -int STDCALL -mysql_close_cont(MYSQL *sock, int ready_status) -{ - int res; - - res= mysql_close_slow_part_cont(sock, ready_status); - if (res) - return res; - mysql_close(sock); - return 0; -} - -/* - These following are not available inside the server (neither blocking or - non-blocking). -*/ -#ifndef MYSQL_SERVER -/* Structure used to pass parameters from mysql_change_user_start(). */ -struct mysql_change_user_params { - MYSQL *mysql; - const char *user; - const char *passwd; - const char *db; -}; -static void -mysql_change_user_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_change_user, - (parms->mysql, parms->user, parms->passwd, parms->db), - parms->mysql, - my_bool, - r_my_bool) -} -int STDCALL -mysql_change_user_start(my_bool *ret, MYSQL *mysql, const char *user, const char *passwd, const char *db) -{ -MK_ASYNC_START_BODY( - mysql_change_user, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.user= user; - parms.passwd= passwd; - parms.db= db; - }, - TRUE, - r_my_bool, - /* Nothing */) -} -int STDCALL -mysql_change_user_cont(my_bool *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - TRUE, - r_my_bool) -} - -/* Structure used to pass parameters from mysql_query_start(). */ -struct mysql_query_params { - MYSQL *mysql; - const char *q; -}; -static void -mysql_query_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_query, - (parms->mysql, parms->q), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_query_start(int *ret, MYSQL *mysql, const char *q) -{ -MK_ASYNC_START_BODY( - mysql_query, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.q= q; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_query_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_shutdown_start(). */ -struct mysql_shutdown_params { - MYSQL *mysql; - enum mysql_enum_shutdown_level shutdown_level; -}; -static void -mysql_shutdown_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_shutdown, - (parms->mysql, parms->shutdown_level), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_shutdown_start(int *ret, MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level) -{ -MK_ASYNC_START_BODY( - mysql_shutdown, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.shutdown_level= shutdown_level; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_shutdown_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_dump_debug_info_start(). */ -struct mysql_dump_debug_info_params { - MYSQL *mysql; -}; -static void -mysql_dump_debug_info_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_dump_debug_info, - (parms->mysql), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_dump_debug_info_start(int *ret, MYSQL *mysql) -{ -MK_ASYNC_START_BODY( - mysql_dump_debug_info, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_dump_debug_info_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_refresh_start(). */ -struct mysql_refresh_params { - MYSQL *mysql; - unsigned int refresh_options; -}; -static void -mysql_refresh_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_refresh, - (parms->mysql, parms->refresh_options), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_refresh_start(int *ret, MYSQL *mysql, unsigned int refresh_options) -{ -MK_ASYNC_START_BODY( - mysql_refresh, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.refresh_options= refresh_options; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_refresh_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_kill_start(). */ -struct mysql_kill_params { - MYSQL *mysql; - unsigned long pid; -}; -static void -mysql_kill_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_kill, - (parms->mysql, parms->pid), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_kill_start(int *ret, MYSQL *mysql, unsigned long pid) -{ -MK_ASYNC_START_BODY( - mysql_kill, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.pid= pid; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_kill_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_set_server_option_start(). */ -struct mysql_set_server_option_params { - MYSQL *mysql; - enum enum_mysql_set_option option; -}; -static void -mysql_set_server_option_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_set_server_option, - (parms->mysql, parms->option), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_set_server_option_start(int *ret, MYSQL *mysql, - enum enum_mysql_set_option option) -{ -MK_ASYNC_START_BODY( - mysql_set_server_option, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.option= option; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_set_server_option_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_ping_start(). */ -struct mysql_ping_params { - MYSQL *mysql; -}; -static void -mysql_ping_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_ping, - (parms->mysql), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_ping_start(int *ret, MYSQL *mysql) -{ -MK_ASYNC_START_BODY( - mysql_ping, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_ping_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_stat_start(). */ -struct mysql_stat_params { - MYSQL *mysql; -}; -static void -mysql_stat_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_stat, - (parms->mysql), - parms->mysql, - const char *, - r_const_ptr) -} -int STDCALL -mysql_stat_start(const char **ret, MYSQL *mysql) -{ -MK_ASYNC_START_BODY( - mysql_stat, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - }, - NULL, - r_const_ptr, - /* Nothing */) -} -int STDCALL -mysql_stat_cont(const char **ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - NULL, - r_const_ptr) -} - -/* Structure used to pass parameters from mysql_list_dbs_start(). */ -struct mysql_list_dbs_params { - MYSQL *mysql; - const char *wild; -}; -static void -mysql_list_dbs_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_list_dbs, - (parms->mysql, parms->wild), - parms->mysql, - MYSQL_RES *, - r_ptr) -} -int STDCALL -mysql_list_dbs_start(MYSQL_RES **ret, MYSQL *mysql, const char *wild) -{ -MK_ASYNC_START_BODY( - mysql_list_dbs, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.wild= wild; - }, - NULL, - r_ptr, - /* Nothing */) -} -int STDCALL -mysql_list_dbs_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - NULL, - r_ptr) -} - -/* Structure used to pass parameters from mysql_list_tables_start(). */ -struct mysql_list_tables_params { - MYSQL *mysql; - const char *wild; -}; -static void -mysql_list_tables_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_list_tables, - (parms->mysql, parms->wild), - parms->mysql, - MYSQL_RES *, - r_ptr) -} -int STDCALL -mysql_list_tables_start(MYSQL_RES **ret, MYSQL *mysql, const char *wild) -{ -MK_ASYNC_START_BODY( - mysql_list_tables, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.wild= wild; - }, - NULL, - r_ptr, - /* Nothing */) -} -int STDCALL -mysql_list_tables_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - NULL, - r_ptr) -} - -/* Structure used to pass parameters from mysql_list_processes_start(). */ -struct mysql_list_processes_params { - MYSQL *mysql; -}; -static void -mysql_list_processes_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_list_processes, - (parms->mysql), - parms->mysql, - MYSQL_RES *, - r_ptr) -} -int STDCALL -mysql_list_processes_start(MYSQL_RES **ret, MYSQL *mysql) -{ -MK_ASYNC_START_BODY( - mysql_list_processes, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - }, - NULL, - r_ptr, - /* Nothing */) -} -int STDCALL -mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - NULL, - r_ptr) -} - -/* Structure used to pass parameters from mysql_list_fields_start(). */ -struct mysql_list_fields_params { - MYSQL *mysql; - const char *table; - const char *wild; -}; -static void -mysql_list_fields_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_list_fields, - (parms->mysql, parms->table, parms->wild), - parms->mysql, - MYSQL_RES *, - r_ptr) -} -int STDCALL -mysql_list_fields_start(MYSQL_RES **ret, MYSQL *mysql, const char *table, - const char *wild) -{ -MK_ASYNC_START_BODY( - mysql_list_fields, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.table= table; - parms.wild= wild; - }, - NULL, - r_ptr, - /* Nothing */) -} -int STDCALL -mysql_list_fields_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - NULL, - r_ptr) -} - -/* Structure used to pass parameters from mysql_read_query_result_start(). */ -struct mysql_read_query_result_params { - MYSQL *mysql; -}; -static void -mysql_read_query_result_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_read_query_result, - (parms->mysql), - parms->mysql, - my_bool, - r_my_bool) -} -int STDCALL -mysql_read_query_result_start(my_bool *ret, MYSQL *mysql) -{ -MK_ASYNC_START_BODY( - mysql_read_query_result, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - }, - TRUE, - r_my_bool, - /* Nothing */) -} -int STDCALL -mysql_read_query_result_cont(my_bool *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - TRUE, - r_my_bool) -} - -/* Structure used to pass parameters from mysql_stmt_prepare_start(). */ -struct mysql_stmt_prepare_params { - MYSQL_STMT *stmt; - const char *query; - unsigned long length; -}; -static void -mysql_stmt_prepare_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_stmt_prepare, - (parms->stmt, parms->query, parms->length), - parms->stmt->mysql, - int, - r_int) -} -int STDCALL -mysql_stmt_prepare_start(int *ret, MYSQL_STMT *stmt, const char *query, - unsigned long length) -{ -MK_ASYNC_START_BODY( - mysql_stmt_prepare, - stmt->mysql, - { - WIN_SET_NONBLOCKING(stmt->mysql) - parms.stmt= stmt; - parms.query= query; - parms.length= length; - }, - 1, - r_int, - /* If stmt->mysql==NULL then we will not block so can call directly. */ - if (!stmt->mysql) - { - *ret= mysql_stmt_prepare(stmt, query, length); - return 0; - }) -} -int STDCALL -mysql_stmt_prepare_cont(int *ret, MYSQL_STMT *stmt, int ready_status) -{ -MK_ASYNC_CONT_BODY( - stmt->mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_stmt_execute_start(). */ -struct mysql_stmt_execute_params { - MYSQL_STMT *stmt; -}; -static void -mysql_stmt_execute_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_stmt_execute, - (parms->stmt), - parms->stmt->mysql, - int, - r_int) -} -int STDCALL -mysql_stmt_execute_start(int *ret, MYSQL_STMT *stmt) -{ -MK_ASYNC_START_BODY( - mysql_stmt_execute, - stmt->mysql, - { - WIN_SET_NONBLOCKING(stmt->mysql) - parms.stmt= stmt; - }, - 1, - r_int, - /* - If eg. mysql_change_user(), stmt->mysql will be NULL. - In this case, we cannot block. - */ - if (!stmt->mysql) - { - *ret= mysql_stmt_execute(stmt); - return 0; - }) -} -int STDCALL -mysql_stmt_execute_cont(int *ret, MYSQL_STMT *stmt, int ready_status) -{ -MK_ASYNC_CONT_BODY( - stmt->mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_stmt_fetch_start(). */ -struct mysql_stmt_fetch_params { - MYSQL_STMT *stmt; -}; -static void -mysql_stmt_fetch_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_stmt_fetch, - (parms->stmt), - parms->stmt->mysql, - int, - r_int) -} -int STDCALL -mysql_stmt_fetch_start(int *ret, MYSQL_STMT *stmt) -{ -MK_ASYNC_START_BODY( - mysql_stmt_fetch, - stmt->mysql, - { - WIN_SET_NONBLOCKING(stmt->mysql) - parms.stmt= stmt; - }, - 1, - r_int, - /* If stmt->mysql==NULL then we will not block so can call directly. */ - if (!stmt->mysql) - { - *ret= mysql_stmt_fetch(stmt); - return 0; - }) -} -int STDCALL -mysql_stmt_fetch_cont(int *ret, MYSQL_STMT *stmt, int ready_status) -{ -MK_ASYNC_CONT_BODY( - stmt->mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_stmt_store_result_start(). */ -struct mysql_stmt_store_result_params { - MYSQL_STMT *stmt; -}; -static void -mysql_stmt_store_result_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_stmt_store_result, - (parms->stmt), - parms->stmt->mysql, - int, - r_int) -} -int STDCALL -mysql_stmt_store_result_start(int *ret, MYSQL_STMT *stmt) -{ -MK_ASYNC_START_BODY( - mysql_stmt_store_result, - stmt->mysql, - { - WIN_SET_NONBLOCKING(stmt->mysql) - parms.stmt= stmt; - }, - 1, - r_int, - /* If stmt->mysql==NULL then we will not block so can call directly. */ - if (!stmt->mysql) - { - *ret= mysql_stmt_store_result(stmt); - return 0; - }) -} -int STDCALL -mysql_stmt_store_result_cont(int *ret, MYSQL_STMT *stmt, int ready_status) -{ -MK_ASYNC_CONT_BODY( - stmt->mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_stmt_close_start(). */ -struct mysql_stmt_close_params { - MYSQL_STMT *stmt; -}; -static void -mysql_stmt_close_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_stmt_close, - (parms->stmt), - parms->stmt->mysql, - my_bool, - r_my_bool) -} -int STDCALL -mysql_stmt_close_start(my_bool *ret, MYSQL_STMT *stmt) -{ -MK_ASYNC_START_BODY( - mysql_stmt_close, - stmt->mysql, - { - WIN_SET_NONBLOCKING(stmt->mysql) - parms.stmt= stmt; - }, - TRUE, - r_my_bool, - /* If stmt->mysql==NULL then we will not block so can call directly. */ - if (!stmt->mysql) - { - *ret= mysql_stmt_close(stmt); - return 0; - }) -} -int STDCALL -mysql_stmt_close_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status) -{ -MK_ASYNC_CONT_BODY( - stmt->mysql, - TRUE, - r_my_bool) -} - -/* Structure used to pass parameters from mysql_stmt_reset_start(). */ -struct mysql_stmt_reset_params { - MYSQL_STMT *stmt; -}; -static void -mysql_stmt_reset_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_stmt_reset, - (parms->stmt), - parms->stmt->mysql, - my_bool, - r_my_bool) -} -int STDCALL -mysql_stmt_reset_start(my_bool *ret, MYSQL_STMT *stmt) -{ -MK_ASYNC_START_BODY( - mysql_stmt_reset, - stmt->mysql, - { - WIN_SET_NONBLOCKING(stmt->mysql) - parms.stmt= stmt; - }, - TRUE, - r_my_bool, - /* If stmt->mysql==NULL then we will not block so can call directly. */ - if (!stmt->mysql) - { - *ret= mysql_stmt_reset(stmt); - return 0; - }) -} -int STDCALL -mysql_stmt_reset_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status) -{ -MK_ASYNC_CONT_BODY( - stmt->mysql, - TRUE, - r_my_bool) -} - -/* Structure used to pass parameters from mysql_stmt_free_result_start(). */ -struct mysql_stmt_free_result_params { - MYSQL_STMT *stmt; -}; -static void -mysql_stmt_free_result_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_stmt_free_result, - (parms->stmt), - parms->stmt->mysql, - my_bool, - r_my_bool) -} -int STDCALL -mysql_stmt_free_result_start(my_bool *ret, MYSQL_STMT *stmt) -{ -MK_ASYNC_START_BODY( - mysql_stmt_free_result, - stmt->mysql, - { - WIN_SET_NONBLOCKING(stmt->mysql) - parms.stmt= stmt; - }, - TRUE, - r_my_bool, - /* If stmt->mysql==NULL then we will not block so can call directly. */ - if (!stmt->mysql) - { - *ret= mysql_stmt_free_result(stmt); - return 0; - }) -} -int STDCALL -mysql_stmt_free_result_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status) -{ -MK_ASYNC_CONT_BODY( - stmt->mysql, - TRUE, - r_my_bool) -} - -/* Structure used to pass parameters from mysql_stmt_send_long_data_start(). */ -struct mysql_stmt_send_long_data_params { - MYSQL_STMT *stmt; - unsigned int param_number; - const char *data; - unsigned long length; -}; -static void -mysql_stmt_send_long_data_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_stmt_send_long_data, - (parms->stmt, parms->param_number, parms->data, parms->length), - parms->stmt->mysql, - my_bool, - r_my_bool) -} -int STDCALL -mysql_stmt_send_long_data_start(my_bool *ret, MYSQL_STMT *stmt, - unsigned int param_number, - const char *data, unsigned long length) -{ -MK_ASYNC_START_BODY( - mysql_stmt_send_long_data, - stmt->mysql, - { - WIN_SET_NONBLOCKING(stmt->mysql) - parms.stmt= stmt; - parms.param_number= param_number; - parms.data= data; - parms.length= length; - }, - TRUE, - r_my_bool, - /* If stmt->mysql==NULL then we will not block so can call directly. */ - if (!stmt->mysql) - { - *ret= mysql_stmt_send_long_data(stmt, param_number, data, length); - return 0; - }) -} -int STDCALL -mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status) -{ -MK_ASYNC_CONT_BODY( - stmt->mysql, - TRUE, - r_my_bool) -} - -/* Structure used to pass parameters from mysql_commit_start(). */ -struct mysql_commit_params { - MYSQL *mysql; -}; -static void -mysql_commit_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_commit, - (parms->mysql), - parms->mysql, - my_bool, - r_my_bool) -} -int STDCALL -mysql_commit_start(my_bool *ret, MYSQL *mysql) -{ -MK_ASYNC_START_BODY( - mysql_commit, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - }, - TRUE, - r_my_bool, - /* Nothing */) -} -int STDCALL -mysql_commit_cont(my_bool *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - TRUE, - r_my_bool) -} - -/* Structure used to pass parameters from mysql_rollback_start(). */ -struct mysql_rollback_params { - MYSQL *mysql; -}; -static void -mysql_rollback_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_rollback, - (parms->mysql), - parms->mysql, - my_bool, - r_my_bool) -} -int STDCALL -mysql_rollback_start(my_bool *ret, MYSQL *mysql) -{ -MK_ASYNC_START_BODY( - mysql_rollback, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - }, - TRUE, - r_my_bool, - /* Nothing */) -} -int STDCALL -mysql_rollback_cont(my_bool *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - TRUE, - r_my_bool) -} - -/* Structure used to pass parameters from mysql_autocommit_start(). */ -struct mysql_autocommit_params { - MYSQL *mysql; - my_bool auto_mode; -}; -static void -mysql_autocommit_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_autocommit, - (parms->mysql, parms->auto_mode), - parms->mysql, - my_bool, - r_my_bool) -} -int STDCALL -mysql_autocommit_start(my_bool *ret, MYSQL *mysql, my_bool auto_mode) -{ -MK_ASYNC_START_BODY( - mysql_autocommit, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - parms.auto_mode= auto_mode; - }, - TRUE, - r_my_bool, - /* Nothing */) -} -int STDCALL -mysql_autocommit_cont(my_bool *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - TRUE, - r_my_bool) -} - -/* Structure used to pass parameters from mysql_next_result_start(). */ -struct mysql_next_result_params { - MYSQL *mysql; -}; -static void -mysql_next_result_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_next_result, - (parms->mysql), - parms->mysql, - int, - r_int) -} -int STDCALL -mysql_next_result_start(int *ret, MYSQL *mysql) -{ -MK_ASYNC_START_BODY( - mysql_next_result, - mysql, - { - WIN_SET_NONBLOCKING(mysql) - parms.mysql= mysql; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_next_result_cont(int *ret, MYSQL *mysql, int ready_status) -{ -MK_ASYNC_CONT_BODY( - mysql, - 1, - r_int) -} - -/* Structure used to pass parameters from mysql_stmt_next_result_start(). */ -struct mysql_stmt_next_result_params { - MYSQL_STMT *stmt; -}; -static void -mysql_stmt_next_result_start_internal(void *d) -{ -MK_ASYNC_INTERNAL_BODY( - mysql_stmt_next_result, - (parms->stmt), - parms->stmt->mysql, - int, - r_int) -} -int STDCALL -mysql_stmt_next_result_start(int *ret, MYSQL_STMT *stmt) -{ -MK_ASYNC_START_BODY( - mysql_stmt_next_result, - stmt->mysql, - { - WIN_SET_NONBLOCKING(stmt->mysql) - parms.stmt= stmt; - }, - 1, - r_int, - /* Nothing */) -} -int STDCALL -mysql_stmt_next_result_cont(int *ret, MYSQL_STMT *stmt, int ready_status) -{ -MK_ASYNC_CONT_BODY( - stmt->mysql, - 1, - r_int) -} -#endif - - -/* - The following functions are deprecated, and so have no non-blocking version: - - mysql_connect - mysql_create_db - mysql_drop_db -*/ - -/* - The following functions can newer block, and so do not have special - non-blocking versions: - - mysql_num_rows() - mysql_num_fields() - mysql_eof() - mysql_fetch_field_direct() - mysql_fetch_fields() - mysql_row_tell() - mysql_field_tell() - mysql_field_count() - mysql_affected_rows() - mysql_insert_id() - mysql_errno() - mysql_error() - mysql_sqlstate() - mysql_warning_count() - mysql_info() - mysql_thread_id() - mysql_character_set_name() - mysql_init() - mysql_ssl_set() - mysql_get_ssl_cipher() - mysql_use_result() - mysql_get_character_set_info() - mysql_set_local_infile_handler() - mysql_set_local_infile_default() - mysql_get_server_info() - mysql_get_server_name() - mysql_get_client_info() - mysql_get_client_version() - mysql_get_host_info() - mysql_get_server_version() - mysql_get_proto_info() - mysql_options() - mysql_data_seek() - mysql_row_seek() - mysql_field_seek() - mysql_fetch_lengths() - mysql_fetch_field() - mysql_escape_string() - mysql_hex_string() - mysql_real_escape_string() - mysql_debug() - myodbc_remove_escape() - mysql_thread_safe() - mysql_embedded() - mariadb_connection() - mysql_stmt_init() - mysql_stmt_fetch_column() - mysql_stmt_param_count() - mysql_stmt_attr_set() - mysql_stmt_attr_get() - mysql_stmt_bind_param() - mysql_stmt_bind_result() - mysql_stmt_result_metadata() - mysql_stmt_param_metadata() - mysql_stmt_errno() - mysql_stmt_error() - mysql_stmt_sqlstate() - mysql_stmt_row_seek() - mysql_stmt_row_tell() - mysql_stmt_data_seek() - mysql_stmt_num_rows() - mysql_stmt_affected_rows() - mysql_stmt_insert_id() - mysql_stmt_field_count() - mysql_more_results() - mysql_get_socket() - mysql_get_timeout_value() -*/ diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 1a53db4aa61..b11f74aef45 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -139,7 +139,6 @@ SET (SQL_SOURCE opt_index_cond_pushdown.cc opt_subselect.cc opt_table_elimination.cc sql_expression_cache.cc gcalc_slicescan.cc gcalc_tools.cc - ../sql-common/mysql_async.c my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc my_json_writer.cc rpl_gtid.cc rpl_parallel.cc diff --git a/tests/mysql_client_fw.c b/tests/mysql_client_fw.c index aea0562672c..bcf62eb0e18 100644 --- a/tests/mysql_client_fw.c +++ b/tests/mysql_client_fw.c @@ -31,9 +31,8 @@ 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. */ -#include <my_context.h> 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 #include "nonblock-wrappers.h" #endif diff --git a/vio/viosocket.c b/vio/viosocket.c index 9cad035161c..f84d0e0738b 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -31,8 +31,6 @@ #include <mstcpip.h> #pragma comment(lib, "ws2_32.lib") #endif -#include "my_context.h" -#include <mysql_async.h> #ifdef FIONREAD_IN_SYS_FILIO # include <sys/filio.h> @@ -171,34 +169,18 @@ size_t vio_read(Vio *vio, uchar *buf, size_t size) if (vio->read_timeout >= 0) flags= VIO_DONTWAIT; - if (vio->async_context && vio->async_context->active) - ret= my_recv_async(vio->async_context, - mysql_socket_getfd(vio->mysql_socket), - buf, size, vio->read_timeout); - else + while ((ret= mysql_socket_recv(vio->mysql_socket, (SOCKBUF_T *)buf, size, + flags)) == -1) { - if (vio->async_context) - { - /* - 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; + int error= socket_errno; - /* The operation would block? */ - if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK) - break; + /* The operation would block? */ + if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK) + break; - /* Wait for input data to become available. */ - if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_READ))) - break; - } + /* Wait for input data to become available. */ + if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_READ))) + break; } #ifndef DBUG_OFF if (ret == -1) @@ -282,33 +264,17 @@ size_t vio_write(Vio *vio, const uchar* buf, size_t size) if (vio->write_timeout >= 0) flags= VIO_DONTWAIT; - if (vio->async_context && vio->async_context->active) - ret= my_send_async(vio->async_context, - mysql_socket_getfd(vio->mysql_socket), buf, size, - vio->write_timeout); - else + while ((ret= mysql_socket_send(vio->mysql_socket, (SOCKBUF_T *)buf, size, + flags)) == -1) { - if (vio->async_context) - { - /* - 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_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; - } + 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 if (ret == -1) @@ -953,24 +919,6 @@ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout) DBUG_ENTER("vio_io_wait"); 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)); pfd.fd= sd; @@ -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 ';' */ 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. */ if (timeout >= 0) { diff --git a/vio/viossl.c b/vio/viossl.c index a5b3396953e..04bc0e41ae9 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -21,8 +21,6 @@ */ #include "vio_priv.h" -#include "my_context.h" -#include <mysql_async.h> #ifdef HAVE_OPENSSL @@ -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, 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); - else + + while ((ret= SSL_read(ssl, buf, (int)size)) < 0) { - 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. */ - if (!ssl_should_retry(vio, ret, &event)) - break; - /* Attempt to wait for an I/O event. */ - if (vio_socket_io_wait(vio, event)) - break; - } + /* Process the SSL I/O error. */ + if (!ssl_should_retry(vio, ret, &event)) + break; + /* Attempt to wait for an I/O event. */ + if (vio_socket_io_wait(vio, event)) + break; } DBUG_PRINT("exit", ("%d", (int) ret)); @@ -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", (int)mysql_socket_getfd(vio->mysql_socket), buf, size)); - - 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) { - 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. */ - if (!ssl_should_retry(vio, ret, &event)) - break; + /* Process the SSL I/O error. */ + if (!ssl_should_retry(vio, ret, &event)) + break; - /* Attempt to wait for an I/O event. */ - if (vio_socket_io_wait(vio, event)) - break; - } + /* Attempt to wait for an I/O event. */ + if (vio_socket_io_wait(vio, event)) + break; } DBUG_RETURN(ret < 0 ? -1 : ret); |