1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-07 02:42:49 +03:00

Initial cio implementation

This commit is contained in:
Georg Richter
2015-08-06 13:06:54 +02:00
parent 9e0f506901
commit f886562fb2
19 changed files with 350 additions and 1695 deletions

View File

@@ -21,9 +21,7 @@ ENDIF()
### Options ### ### Options ###
IF(NOT WIN32) IF(NOT WIN32)
OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" ON) OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" ON)
OPTION(WITH_OPENSSL "enables SSL support" ON)
ELSE() ELSE()
OPTION(WITH_OPENSSL "enables SSL support" OFF)
OPTION(WITH_SIGNCODE "digitally sign files" OFF) OPTION(WITH_SIGNCODE "digitally sign files" OFF)
OPTION(WITH_RTC "enables run time checks for debug builds" OFF) OPTION(WITH_RTC "enables run time checks for debug builds" OFF)
ENDIF() ENDIF()
@@ -112,9 +110,9 @@ ENDIF()
IF(UNIX) IF(UNIX)
SEARCH_LIBRARY(DEFAULT_LIB inet_ntoa "c") SEARCH_LIBRARY(DEFAULT_LIB inet_ntoa "c")
IF(NOT DEFAULT_LIB) # IF(NOT DEFAULT_LIB)
SEARCH_LIBRARY(LIBNSL inet_ntoa "nsl_r;nsl") SEARCH_LIBRARY(LIBNSL inet_ntoa "nsl_r;nsl")
ENDIF() # ENDIF()
SEARCH_LIBRARY(DEFAULT_LIB bind "c") SEARCH_LIBRARY(DEFAULT_LIB bind "c")
IF(NOT DEFAULT_LIB) IF(NOT DEFAULT_LIB)
SEARCH_LIBRARY(LIBBIND bind "bind;socket") SEARCH_LIBRARY(LIBBIND bind "bind;socket")
@@ -159,18 +157,35 @@ INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckFunctions.cmake)
# check for various types # check for various types
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckTypes.cmake) INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckTypes.cmake)
# Check for OpenSSL IF(WITH_SSL STREQUAL "OPENSSL")
IF(WITH_OPENSSL)
FIND_PACKAGE(OpenSSL) FIND_PACKAGE(OpenSSL)
IF(OPENSSL_FOUND) IF(OPENSSL_FOUND)
ADD_DEFINITIONS(-DHAVE_OPENSSL) ADD_DEFINITIONS(-DHAVE_OPENSSL -DHAVE_SSL)
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) ADD_DEFINITIONS(-DSSL_PLUGIN=cio_openssl_plugin)
SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES}) SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/plugins/builtin/cio_openssl.c")
IF(OPENSSL_CRYPTO_LIBRARIES) SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
ENDIF()
ELSE() ELSE()
MESSAGE(FATAL_ERROR "OpenSSL not found. Please install OpenSSL or disable SSL support via option -DWITH_OPENSSL=Off") MESSAGE(FATAL "OpenSSL not found")
ENDIF()
ENDIF()
IF(WITH_SSL STREQUAL "GNUTLS")
FIND_PACKAGE(GnuTLS)
IF(GNUTLS_FOUND)
ADD_DEFINITIONS(-DSSL_PLUGIN=cio_gnutls_plugin)
ADD_DEFINITIONS(-DHAVE_GNUTLS -DHAVE_SSL)
SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/plugins/builtin/cio_gnutls.c")
SET(SSL_LIBRARIES ${GNUTLS_LIBRARIES})
ELSE()
MESSAGE(FATAL "GnuTLS not found")
ENDIF()
ENDIF()
IF(WIN32)
IF(WITH_SSL STREQUAL "SCHANNEL")
ADD_DEFINITIONS(-DSSL_PLUGIN=cio_schannel_plugin)
MESSAGE(STATUS "SSL_TYPE ${SSL_TYPE}")
ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_SSL)
SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/plugins/builtin/cio_schannel.c" "${CMAKE_SOURCE_DIR}/plugins/builtin/ma_schannel.c")
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/plugins/cio/")
ENDIF() ENDIF()
ENDIF() ENDIF()
@@ -283,7 +298,7 @@ MESSAGE(STATUS "CPack generation: ${CPACK_GENERATOR}")
IF(CLIENT_DOCS) IF(CLIENT_DOCS)
MESSAGE(STATUS "Documentation included from ${CLIENT_DOCS}") MESSAGE(STATUS "Documentation included from ${CLIENT_DOCS}")
ENDIF() ENDIF()
MESSAGE(STATUS "SSL support: ${WITH_OPENSSL}") MESSAGE(STATUS "SSL support: ${WITH_SSL} Sources: ${SSL_SOURCES}")
MESSAGE(STATUS "Experimental Sqlite support: ${WITH_SQLITE}") MESSAGE(STATUS "Experimental Sqlite support: ${WITH_SQLITE}")
IF(WITH_EXTERNAL_ZLIB) IF(WITH_EXTERNAL_ZLIB)
MESSAGE(STATUS "Zlib support: ${WITH_EXTERNAL_ZLIB}") MESSAGE(STATUS "Zlib support: ${WITH_EXTERNAL_ZLIB}")

View File

@@ -25,6 +25,7 @@ extern "C" {
#endif #endif
void init_client_errs(void); void init_client_errs(void);
extern const char *client_errors[]; /* Error messages */ extern const char *client_errors[]; /* Error messages */
extern const char *mariadb_client_errors[]; /* Error messages */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@@ -32,11 +33,10 @@ extern const char *client_errors[]; /* Error messages */
#define CR_MIN_ERROR 2000 /* For easier client code */ #define CR_MIN_ERROR 2000 /* For easier client code */
#define CR_MAX_ERROR 2999 #define CR_MAX_ERROR 2999
#if defined(OS2) && defined( MYSQL_SERVER) #define CER_MIN_ERROR 5000
#define CER(X) client_errors[(X)-CR_MIN_ERROR] #define CER_MAX_ERROR 5999
#else #define CER(X) mariadb_client_errors[(X)-CER_MIN_ERROR]
#define ER(X) client_errors[(X)-CR_MIN_ERROR] #define ER(X) client_errors[(X)-CR_MIN_ERROR]
#endif
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */ #define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
#define CR_UNKNOWN_ERROR 2000 #define CR_UNKNOWN_ERROR 2000
@@ -66,6 +66,11 @@ extern const char *client_errors[]; /* Error messages */
#define CR_PARAMS_NOT_BOUND 2031 #define CR_PARAMS_NOT_BOUND 2031
#define CR_INVALID_PARAMETER_NO 2034 #define CR_INVALID_PARAMETER_NO 2034
#define CR_UNSUPPORTED_PARAM_TYPE 2036 #define CR_UNSUPPORTED_PARAM_TYPE 2036
#define CR_SHARED_MEMORY_CONNECTION 2037
#define CR_SHARED_MEMORY_CONNECT_ERROR 2038
#define CR_SECURE_AUTH 2049 #define CR_SECURE_AUTH 2049
#define CR_NO_DATA 2051 #define CR_NO_DATA 2051
#define CR_NO_STMT_METADATA 2052 #define CR_NO_STMT_METADATA 2052
@@ -76,6 +81,9 @@ extern const char *client_errors[]; /* Error messages */
#define CR_ALREADY_CONNECTED 2059 #define CR_ALREADY_CONNECTED 2059
#define CR_PLUGIN_FUNCTION_NOT_SUPPORTED 2060 #define CR_PLUGIN_FUNCTION_NOT_SUPPORTED 2060
#define CR_EVENT_CREATE_FAILED 5000
#define CR_BIND_ADDR_FAILED 5001
#define SQLSTATE_UNKNOWN "HY000" #define SQLSTATE_UNKNOWN "HY000"
#endif #endif

View File

@@ -251,7 +251,7 @@ struct st_mysql_options {
my_bool compress,named_pipe; my_bool compress,named_pipe;
my_bool unused_1, unused_2, unused_3, unused_4; my_bool unused_1, unused_2, unused_3, unused_4;
enum mysql_option methods_to_use; enum mysql_option methods_to_use;
char *client_ip; char *bind_address;
my_bool secure_auth; my_bool secure_auth;
my_bool report_data_truncation; my_bool report_data_truncation;
/* function pointers for local infile support */ /* function pointers for local infile support */

View File

@@ -36,14 +36,17 @@
#endif #endif
/* known plugin types */ /* known plugin types */
#define MYSQL_CLIENT_DB_PLUGIN 0 #define MYSQL_CLIENT_GENERIC_PLUGIN 0
#define MYSQL_CLIENT_reserved 1 #define MYSQL_CLIENT_CIO_PLUGIN 1 /* communication IO */
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 #define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 /* authentication */
#define MYSQL_CLIENT_reserved22 3 #define MYSQL_CLIENT_TRACE_PLUGIN 3 /* cio trace */
#define MYSQL_CLIENT_REMOTEIO_PLUGIN 4 #define MYSQL_CLIENT_REMOTEIO_PLUGIN 4
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100 #define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100
#define MYSQL_CLIENT_DB_PLUGIN_INTERFACE_VERSION 0x0100 #define MYSQL_CLIENT_DB_PLUGIN_INTERFACE_VERSION 0x0100
#define MYSQL_CLIENT_CIO_PLUGIN_INTERFACE_VERSION 0x0100
#define MYSQL_CLIENT_SSL_INTERFACE_VERSION 0x0100
#define MYSQL_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION 0x01000
#define MYSQL_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION 0x0100 #define MYSQL_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION 0x0100
#define MYSQL_CLIENT_MAX_PLUGINS 5 #define MYSQL_CLIENT_MAX_PLUGINS 5
@@ -63,9 +66,9 @@
const char *author; \ const char *author; \
const char *desc; \ const char *desc; \
unsigned int version[3]; \ unsigned int version[3]; \
const char *license; \
int (*init)(char *, size_t, int, va_list); \ int (*init)(char *, size_t, int, va_list); \
int (*deinit)(void); int (*deinit)();
struct st_mysql_client_plugin struct st_mysql_client_plugin
{ {
MYSQL_CLIENT_PLUGIN_HEADER MYSQL_CLIENT_PLUGIN_HEADER
@@ -83,6 +86,18 @@ typedef struct st_mariadb_client_plugin_DB
#define MARIADB_DB_DRIVER(a) ((a)->ext_db) #define MARIADB_DB_DRIVER(a) ((a)->ext_db)
/******************* Communication IO plugin *****************/
#include <ma_cio.h>
#include <ma_ssl.h>
typedef struct st_mariadb_client_plugin_CIO
{
MYSQL_CLIENT_PLUGIN_HEADER
struct st_ma_cio_methods *methods;
struct st_ma_cio_ssl_methods *ssl_methods;
void *compress_methods;
} MARIADB_CIO_PLUGIN;
/******** authentication plugin specific declarations *********/ /******** authentication plugin specific declarations *********/
#include <mysql/plugin_auth_common.h> #include <mysql/plugin_auth_common.h>
@@ -92,6 +107,11 @@ struct st_mysql_client_plugin_AUTHENTICATION
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
}; };
/******** trace plugin *******/
struct st_mysql_client_plugin_TRACE
{
MYSQL_CLIENT_PLUGIN_HEADER
};
/** /**
type of the mysql_authentication_dialog_ask function type of the mysql_authentication_dialog_ask function

View File

@@ -1,40 +1,37 @@
/* Copyright (C) 2012 MariaDB Services and Kristian Nielsen /* Copyright (C) 2012 MariaDB Services and Kristian Nielsen
2015 MariaDB Corporation
This library is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or modify
modify it under the terms of the GNU Library General Public it under the terms of the GNU General Public License as published by
License as published by the Free Software Foundation; either the Free Software Foundation; version 2 of the License.
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Library General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU Library General Public You should have received a copy of the GNU General Public License
License along with this library; if not, write to the Free along with this program; if not, write to the Free Software
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
MA 02111-1307, USA */
/* Common definitions for MariaDB non-blocking client library. */ /* Common definitions for MariaDB non-blocking client library. */
#ifndef MYSQL_ASYNC_H #ifndef MYSQL_ASYNC_H
#define MYSQL_ASYNC_H #define MYSQL_ASYNC_H
extern int my_connect_async(struct mysql_async_context *b, my_socket fd, extern int my_connect_async(MARIADB_CIO *cio,
const struct sockaddr *name, uint namelen, const struct sockaddr *name, uint namelen,
int vio_timeout); int vio_timeout);
extern ssize_t my_recv_async(struct mysql_async_context *b, int fd, extern ssize_t my_recv_async(MARIADB_CIO *cio,
unsigned char *buf, size_t size, int timeout); const unsigned char *buf, size_t size, int timeout);
extern ssize_t my_send_async(struct mysql_async_context *b, int fd, extern ssize_t my_send_async(MARIADB_CIO *cio,
const unsigned char *buf, size_t size, const unsigned char *buf, size_t size,
int timeout); int timeout);
extern my_bool my_io_wait_async(struct mysql_async_context *b, extern my_bool my_io_wait_async(struct mysql_async_context *b,
enum enum_vio_io_event event, int timeout); enum enum_cio_io_event event, int timeout);
#ifdef HAVE_OPENSSL #ifdef HAVE_SSL
extern int my_ssl_read_async(struct mysql_async_context *b, SSL *ssl, extern int my_ssl_read_async(struct mysql_async_context *b, MARIADB_SSL *ssl,
void *buf, int size); void *buf, int size);
extern int my_ssl_write_async(struct mysql_async_context *b, SSL *ssl, extern int my_ssl_write_async(struct mysql_async_context *b, MARIADB_SSL *ssl,
const void *buf, int size); const void *buf, int size);
#endif #endif

View File

@@ -216,6 +216,8 @@ class Vio; /* Fill Vio class in C++ */
#else #else
struct st_vio; /* Only C */ struct st_vio; /* Only C */
typedef struct st_vio Vio; typedef struct st_vio Vio;
struct st_ma_cio;
typedef struct st_ma_cio MARIADB_CIO;
#endif #endif
#endif #endif
@@ -233,7 +235,7 @@ typedef struct st_vio Vio;
typedef struct st_net { typedef struct st_net {
Vio *vio; MARIADB_CIO *cio;
unsigned char *buff; unsigned char *buff;
unsigned char *buff_end,*write_pos,*read_pos; unsigned char *buff_end,*write_pos,*read_pos;
my_socket fd; /* For Perl DBI/dbd */ my_socket fd; /* For Perl DBI/dbd */
@@ -324,7 +326,7 @@ extern unsigned long net_buffer_length;
#define net_new_transaction(net) ((net)->pkt_nr=0) #define net_new_transaction(net) ((net)->pkt_nr=0)
int my_net_init(NET *net, Vio *vio); int my_net_init(NET *net, MARIADB_CIO *cio);
void net_end(NET *net); void net_end(NET *net);
void net_clear(NET *net); void net_clear(NET *net);
int net_flush(NET *net); int net_flush(NET *net);

View File

@@ -1,167 +0,0 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA */
/*
* Vio Lite.
* Purpose: include file for Vio that will work with C and C++
*/
#ifndef vio_violite_h_
#define vio_violite_h_
#include "my_net.h" /* needed because of struct in_addr */
#ifdef HAVE_VIO
#include <Vio.h> /* Full VIO interface */
#else
#ifdef HAVE_OPENSSL
#include <openssl/ssl.h>
#endif
enum enum_vio_io_event
{
VIO_IO_EVENT_READ,
VIO_IO_EVENT_WRITE,
VIO_IO_EVENT_CONNECT
};
/* Simple vio interface in C; The functions are implemented in violite.c */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef Vio_defined
#define Vio_defined
struct st_vio; /* Only C */
typedef struct st_vio Vio;
#endif
#ifndef _WIN32
#define HANDLE void *
#endif
/* vio read-ahead cachine */
#define VIO_CACHE_SIZE 16384
#define VIO_CACHE_MIN_SIZE 2048
enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET,
VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL};
Vio* vio_new(my_socket sd,
enum enum_vio_type type,
my_bool localhost);
#ifdef _WIN32
Vio* vio_new_win32pipe(HANDLE hPipe);
#endif
void vio_delete(Vio* vio);
void vio_reset(Vio* vio, enum enum_vio_type type,
my_socket sd, HANDLE hPipe,
my_bool localhost);
/*
* vio_read and vio_write should have the same semantics
* as read(2) and write(2).
*/
size_t vio_read(Vio* vio, gptr buf, size_t size);
my_bool vio_read_peek(Vio *vio, size_t *bytes);
size_t vio_write(Vio* vio, const gptr buf, size_t size);
/*
* Whenever the socket is set to blocking mode or not.
*/
int vio_blocking( Vio* vio,
my_bool onoff,
my_bool *prevmode);
my_bool vio_is_blocking( Vio* vio);
/*
* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible.
*/
int vio_fastsend( Vio* vio);
/*
* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible.
*/
int vio_keepalive( Vio* vio,
my_bool onoff);
/*
* Whenever we should retry the last read/write operation.
*/
my_bool vio_should_retry( Vio* vio);
/*
* When the workday is over...
*/
int vio_close( Vio* vio);
/*
* Short text description of the socket for those, who are curious..
*/
const char* vio_description( Vio* vio);
/* Return the type of the connection */
enum enum_vio_type vio_type(Vio* vio);
/* set timeout */
void vio_read_timeout(Vio *vio, uint seconds);
void vio_write_timeout(Vio *vio, uint seconds);
/* Return last error number */
int vio_errno(Vio *vio);
/* Get socket number */
my_socket vio_fd(Vio *vio);
/*
* Remote peer's address and name in text form.
*/
my_bool vio_peer_addr(Vio * vio, char *buf);
/* Remotes in_addr */
void vio_in_addr(Vio *vio, struct in_addr *in);
/* Return 1 if there is data to be read */
my_bool vio_poll_read(Vio *vio,uint timeout);
int vio_wait_or_timeout(Vio *vio, my_bool is_read, int timeout);
struct st_vio
{
my_socket sd; /* my_socket - real or imaginary */
HANDLE hPipe;
my_bool localhost; /* Are we from localhost? */
int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
struct sockaddr_in local; /* Local internet address */
struct sockaddr_in remote; /* Remote internet address */
struct mysql_async_context *async_context; /* For non-blocking API */
int write_timeout;
int read_timeout;
enum enum_vio_type type; /* Type of connection */
char desc[30]; /* String description */
#ifdef HAVE_OPENSSL
SSL *ssl;
#endif
uchar *cache; /* read-ahead cache to reduce reads (see CONC-79) */
uchar *cache_pos; /* position of read-ahead cached data */
size_t cache_size; /* <= VIO_CACHE_SIZE */
};
#ifdef __cplusplus
}
#endif
#endif /* HAVE_VIO */
#endif /* vio_violite_h_ */

View File

@@ -8,7 +8,9 @@ ADD_DEFINITIONS(-D LIBMARIADB)
ADD_DEFINITIONS(-D THREAD) ADD_DEFINITIONS(-D THREAD)
SET(EXPORT_SYMBOLS SET(EXPORT_SYMBOLS
client_errors
load_defaults load_defaults
ma_cio_register_callback
mariadb_connection mariadb_connection
mariadb_convert_string mariadb_convert_string
mariadb_deinitialize_ssl mariadb_deinitialize_ssl
@@ -247,7 +249,8 @@ bmove.c
bmove_upp.c bmove_upp.c
my_charset.c my_charset.c
hash.c hash.c
violite.c ma_cio.c
ma_ssl.c
net.c net.c
charset.c charset.c
ma_time.c ma_time.c
@@ -321,10 +324,15 @@ my_stmt.c
my_loaddata.c my_loaddata.c
my_stmt_codec.c my_stmt_codec.c
client_plugin.c client_plugin.c
my_auth.c # built in plugins
ma_secure.c ${CMAKE_SOURCE_DIR}/plugins/builtin/my_auth.c
${CMAKE_SOURCE_DIR}/plugins/builtin/cio_socket.c
) )
IF(SSL_SOURCES)
SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} ${SSL_SOURCES})
ENDIF()
IF(WIN32) IF(WIN32)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/win-iconv) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/win-iconv)
SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES}

View File

@@ -61,28 +61,12 @@ static MEM_ROOT mem_root;
static uint plugin_version[MYSQL_CLIENT_MAX_PLUGINS]= static uint plugin_version[MYSQL_CLIENT_MAX_PLUGINS]=
{ {
MYSQL_CLIENT_DB_PLUGIN_INTERFACE_VERSION, /* these two are taken by Connector/C */ MYSQL_CLIENT_DB_PLUGIN_INTERFACE_VERSION, /* these two are taken by Connector/C */
0, /* these two are taken by Connector/C */ MYSQL_CLIENT_CIO_PLUGIN_INTERFACE_VERSION, /* these two are taken by Connector/C */
MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION, MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
0, MYSQL_CLIENT_TRACE_PLUGIN_INTERFACE_VERSION,
MYSQL_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION MYSQL_CLIENT_REMOTEIO_PLUGIN_INTERFACE_VERSION
}; };
typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
extern auth_plugin_t old_password_client_plugin;
extern auth_plugin_t native_password_client_plugin;
/* built in plugins:
These plugins are part of Connector/C, so no need to
load them
*/
struct st_mysql_client_plugin *mysql_client_builtins[]=
{
(struct st_mysql_client_plugin *)&old_password_client_plugin,
(struct st_mysql_client_plugin *)&native_password_client_plugin,
0
};
/* /*
Loaded plugins are stored in a linked list. Loaded plugins are stored in a linked list.
The list is append-only, the elements are added to the head (like in a stack). The list is append-only, the elements are added to the head (like in a stack).
@@ -96,6 +80,26 @@ struct st_client_plugin_int *plugin_list[MYSQL_CLIENT_MAX_PLUGINS];
static pthread_mutex_t LOCK_load_client_plugin; static pthread_mutex_t LOCK_load_client_plugin;
#endif #endif
extern struct st_mysql_client_plugin old_password_client_plugin;
extern struct st_mysql_client_plugin native_password_client_plugin;
extern MARIADB_CIO_PLUGIN cio_socket_plugin;
#ifdef HAVE_SSL
extern MARIADB_CIO_PLUGIN SSL_PLUGIN;
#endif
struct st_mysql_client_plugin *mysql_client_builtins[]=
{
(struct st_mysql_client_plugin *)&old_password_client_plugin,
(struct st_mysql_client_plugin *)&native_password_client_plugin,
(struct st_mysql_client_plugin *)&cio_socket_plugin,
#ifdef HAVE_SSL
(struct st_mysql_client_plugin *)&SSL_PLUGIN,
#endif
0
};
static int is_not_initialized(MYSQL *mysql, const char *name) static int is_not_initialized(MYSQL *mysql, const char *name)
{ {
if (initialized) if (initialized)
@@ -103,7 +107,7 @@ static int is_not_initialized(MYSQL *mysql, const char *name)
my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
SQLSTATE_UNKNOWN, ER(CR_AUTH_PLUGIN_CANNOT_LOAD), SQLSTATE_UNKNOWN, ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
name ? name : "unknown" , "not initialized"); name, "not initialized");
return 1; return 1;
} }
@@ -130,9 +134,12 @@ static struct st_mysql_client_plugin *find_plugin(const char *name, int type)
for (p= plugin_list[type]; p; p= p->next) for (p= plugin_list[type]; p; p= p->next)
{ {
if (!name) if (name)
return p->plugin; {
if (strcmp(p->plugin->name, name) == 0) if (strcmp(p->plugin->name, name) == 0)
return p->plugin;
}
else if (p->plugin->type == type)
return p->plugin; return p->plugin;
} }
return NULL; return NULL;
@@ -207,10 +214,10 @@ err2:
if (plugin->deinit) if (plugin->deinit)
plugin->deinit(); plugin->deinit();
err1: err1:
if (dlhandle)
(void)dlclose(dlhandle);
my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, SQLSTATE_UNKNOWN, my_set_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD, SQLSTATE_UNKNOWN,
ER(CR_AUTH_PLUGIN_CANNOT_LOAD), plugin->name, errmsg); ER(CR_AUTH_PLUGIN_CANNOT_LOAD), plugin->name, errmsg);
if (dlhandle)
(void)dlclose(dlhandle);
return NULL; return NULL;
} }
@@ -282,7 +289,6 @@ int mysql_client_plugin_init()
initialized= 1; initialized= 1;
pthread_mutex_lock(&LOCK_load_client_plugin); pthread_mutex_lock(&LOCK_load_client_plugin);
for (builtin= mysql_client_builtins; *builtin; builtin++) for (builtin= mysql_client_builtins; *builtin; builtin++)
add_plugin(&mysql, *builtin, 0, 0, unused); add_plugin(&mysql, *builtin, 0, 0, unused);
@@ -386,7 +392,7 @@ mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
mysql->options.extension->plugin_dir : (env_plugin_dir) ? env_plugin_dir : mysql->options.extension->plugin_dir : (env_plugin_dir) ? env_plugin_dir :
PLUGINDIR, "/", PLUGINDIR, "/",
name, SO_EXT, NullS); name, SO_EXT, NullS);
/* Open new dll handle */ /* Open new dll handle */
if (!(dlhandle= dlopen((const char *)dlpath, RTLD_NOW))) if (!(dlhandle= dlopen((const char *)dlpath, RTLD_NOW)))
{ {
@@ -403,7 +409,8 @@ mysql_load_plugin_v(MYSQL *mysql, const char *name, int type,
goto err; goto err;
} }
if (!(sym= dlsym(dlhandle, plugin_declarations_sym)))
if (!(sym= (int *)dlsym(dlhandle, plugin_declarations_sym)))
{ {
errmsg= "not a plugin"; errmsg= "not a plugin";
(void)dlclose(dlhandle); (void)dlclose(dlhandle);

View File

@@ -55,25 +55,25 @@ const char *client_errors[]=
const char *client_errors[]= const char *client_errors[]=
{ {
"Erro desconhecido do MySQL", "Erro desconhecido do MySQL",
"N<EFBFBD>o pode criar 'UNIX socket' (%d)", "N<EFBFBD>o pode criar 'UNIX socket' (%d)",
"N<EFBFBD>o pode se conectar ao servidor MySQL local atrav<61>s do 'socket' '%-.64s' (%d)", "N<EFBFBD>o pode se conectar ao servidor MySQL local atrav<61>s do 'socket' '%-.64s' (%d)",
"N<EFBFBD>o pode se conectar ao servidor MySQL em '%-.64s' (%d)", "N<EFBFBD>o pode se conectar ao servidor MySQL em '%-.64s' (%d)",
"N<EFBFBD>o pode criar 'socket TCP/IP' (%d)", "N<EFBFBD>o pode criar 'socket TCP/IP' (%d)",
"'Host' servidor MySQL '%-.64s' (%d) desconhecido", "'Host' servidor MySQL '%-.64s' (%d) desconhecido",
"Servidor MySQL desapareceu", "Servidor MySQL desapareceu",
"Incompatibilidade de protocolos. Vers<72>o do Servidor: %d - Vers<72>o do Cliente: %d", "Incompatibilidade de protocolos. Vers<72>o do Servidor: %d - Vers<72>o do Cliente: %d",
"Cliente do MySQL com falta de mem<65>ria", "Cliente do MySQL com falta de mem<65>ria",
"Informa<EFBFBD><EFBFBD>o inv<6E>lida de 'host'", "Informa<EFBFBD><EFBFBD>o inv<6E>lida de 'host'",
"Localhost via 'UNIX socket'", "Localhost via 'UNIX socket'",
"%-.64s via 'TCP/IP'", "%-.64s via 'TCP/IP'",
"Erro na negocia<69><61>o de acesso ao servidor", "Erro na negocia<69><61>o de acesso ao servidor",
"Conex<EFBFBD>o perdida com servidor MySQL durante 'query'", "Conex<EFBFBD>o perdida com servidor MySQL durante 'query'",
"Comandos fora de sincronismo. Voc<6F> n<>o pode executar este comando agora", "Comandos fora de sincronismo. Voc<6F> n<>o pode executar este comando agora",
"%-.64s via 'named pipe'", "%-.64s via 'named pipe'",
"N<EFBFBD>o pode esperar pelo 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", "N<EFBFBD>o pode esperar pelo 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"N<EFBFBD>o pode abrir 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", "N<EFBFBD>o pode abrir 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"N<EFBFBD>o pode estabelecer o estado do 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)", "N<EFBFBD>o pode estabelecer o estado do 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"N<EFBFBD>o pode inicializar conjunto de caracteres %-.64s (caminho %-.64s)", "N<EFBFBD>o pode inicializar conjunto de caracteres %-.64s (caminho %-.64s)",
"Obteve pacote maior do que 'max_allowed_packet'" "Obteve pacote maior do que 'max_allowed_packet'"
}; };
@@ -117,8 +117,8 @@ const char *client_errors[]=
/* 2034 */ "", /* 2034 */ "",
/* 2035 */ "", /* 2035 */ "",
/* 2036 */ "Buffer type is not supported", /* 2036 */ "Buffer type is not supported",
/* 2037 */ "", /* 2037 */ "Shared memory: %-.64s",
/* 2038 */ "", /* 2038 */ "Shared memory connection failed during %s. (%lu)",
/* 2039 */ "", /* 2039 */ "",
/* 2040 */ "", /* 2040 */ "",
/* 2041 */ "", /* 2041 */ "",
@@ -145,6 +145,12 @@ const char *client_errors[]=
}; };
#endif #endif
const char *mariadb_client_errors[] =
{
/* 5000 */ "Creating an event failed (Errorcode: %d)",
/* 5001 */ "Bind to local interface '-.%64s' failed (Errorcode: %d)",
""
};
void init_client_errs(void) void init_client_errs(void)
{ {

View File

@@ -62,15 +62,11 @@
#define INADDR_NONE -1 #define INADDR_NONE -1
#endif #endif
#include <sha1.h> #include <sha1.h>
#include <violite.h> #include <ma_cio.h>
#ifdef HAVE_OPENSSL
#include <ma_secure.h>
#endif
#ifndef _WIN32 #ifndef _WIN32
#include <poll.h> #include <poll.h>
#endif #endif
#include <ma_dyncol.h> #include <ma_dyncol.h>
#include <mysql_async.h>
#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15) #define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15)
@@ -91,6 +87,8 @@ extern const CHARSET_INFO * mysql_find_charset_name(const char * const name);
extern int run_plugin_auth(MYSQL *mysql, char *data, uint data_len, extern int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
const char *data_plugin, const char *db); const char *data_plugin, const char *db);
extern LIST *cio_callback;
/* prepare statement methods from my_stmt.c */ /* prepare statement methods from my_stmt.c */
extern my_bool mthd_supported_buffer_type(enum enum_field_types type); extern my_bool mthd_supported_buffer_type(enum enum_field_types type);
extern my_bool mthd_stmt_read_prepare_response(MYSQL_STMT *stmt); extern my_bool mthd_stmt_read_prepare_response(MYSQL_STMT *stmt);
@@ -130,216 +128,11 @@ static void mysql_close_memory(MYSQL *mysql);
void read_user_name(char *name); void read_user_name(char *name);
static void append_wild(char *to,char *end,const char *wild); static void append_wild(char *to,char *end,const char *wild);
static my_bool mysql_reconnect(MYSQL *mysql); static my_bool mysql_reconnect(MYSQL *mysql);
static sig_handler pipe_sig_handler(int sig);
static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length); static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length);
extern int mysql_client_plugin_init(); extern int mysql_client_plugin_init();
extern void mysql_client_plugin_deinit(); extern void mysql_client_plugin_deinit();
/*
Let the user specify that we don't want SIGPIPE; This doesn't however work
with threaded applications as we can have multiple read in progress.
*/
#if !defined(_WIN32) && defined(SIGPIPE) && !defined(THREAD)
#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0;
#define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler)
#define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler);
#else
#define init_sigpipe_variables
#define set_sigpipe(mysql)
#define reset_sigpipe(mysql)
#endif
/****************************************************************************
* A modified version of connect(). connect2() allows you to specify
* a timeout value, in seconds, that we should wait until we
* derermine we can't connect to a particular host. If timeout is 0,
* connect2() will behave exactly like connect().
*
* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
*****************************************************************************/
int socket_block(my_socket s,my_bool blocked)
{
#ifdef _WIN32
unsigned long socket_blocked= blocked ? 0 : 1;
return ioctlsocket(s, FIONBIO, &socket_blocked);
#else
int flags= fcntl(s, F_GETFL, 0);
if (blocked)
flags&= ~O_NONBLOCK;
else
flags|= O_NONBLOCK;
return fcntl(s, F_SETFL, flags);
#endif
}
static int connect2(my_socket s, const struct sockaddr *name, size_t namelen,
uint timeout)
{
int res, s_err;
socklen_t s_err_size = sizeof(uint);
#ifndef _WIN32
struct pollfd poll_fd;
#else
FD_SET sfds, efds;
struct timeval tv;
#endif
if (!timeout)
return connect(s, (struct sockaddr*) name, (int)namelen);
/* set socket to non blocking */
if (socket_block(s, 0) == SOCKET_ERROR)
return -1;
res= connect(s, (struct sockaddr*) name, (int)namelen);
if (res == 0)
return res;
#ifdef _WIN32
if (GetLastError() != WSAEWOULDBLOCK &&
GetLastError() != WSAEINPROGRESS)
#else
if (errno != EINPROGRESS)
#endif
return -1;
#ifndef _WIN32
memset(&poll_fd, 0, sizeof(struct pollfd));
poll_fd.events= POLLOUT | POLLERR;
poll_fd.fd= s;
/* connection timeout in milliseconds */
res= poll(&poll_fd, 1, timeout);
switch(res)
{
/* Error= - 1, timeout = 0 */
case -1:
break;
case 0:
errno= ETIMEDOUT;
break;
}
#else
FD_ZERO(&sfds);
FD_ZERO(&efds);
FD_SET(s, &sfds);
FD_SET(s, &efds);
memset(&tv, 0, sizeof(struct timeval));
tv.tv_sec= timeout;
res= select((int)s+1, NULL, &sfds, &efds, &tv);
if (res < 1)
return -1;
#endif
s_err=0;
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
return(-1);
if (s_err)
{ /* getsockopt could succeed */
errno = s_err;
return(-1); /* but return an error... */
}
return (0); /* ok */
}
static int
connect_sync_or_async(MYSQL *mysql, NET *net, my_socket fd,
const struct sockaddr *name, uint namelen)
{
int vio_timeout= (mysql->options.connect_timeout >= 0) ?
mysql->options.connect_timeout * 1000 : -1;
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 connect2(fd, name, namelen, vio_timeout);
}
/*
** Create a named pipe connection
*/
#ifdef _WIN32
HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host,
char **arg_unix_socket)
{
HANDLE hPipe=INVALID_HANDLE_VALUE;
char szPipeName [ 257 ];
DWORD dwMode;
int i;
my_bool testing_named_pipes=0;
char *host= *arg_host, *unix_socket= *arg_unix_socket;
if ( ! unix_socket || (unix_socket)[0] == 0x00)
unix_socket = mysql_unix_port;
if (!host || !strcmp(host,LOCAL_HOST))
host=LOCAL_HOST_NAMEDPIPE;
sprintf( szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket);
DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s",
host, unix_socket));
for (i=0 ; i < 100 ; i++) /* Don't retry forever */
{
if ((hPipe = CreateFile(szPipeName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL )) != INVALID_HANDLE_VALUE)
break;
if (GetLastError() != ERROR_PIPE_BUSY)
{
net->last_errno=CR_NAMEDPIPEOPEN_ERROR;
sprintf(net->last_error,ER(net->last_errno),host, unix_socket,
(ulong) GetLastError());
return INVALID_HANDLE_VALUE;
}
/* wait for for an other instance */
if (! WaitNamedPipe(szPipeName, connect_timeout) )
{
net->last_errno=CR_NAMEDPIPEWAIT_ERROR;
sprintf(net->last_error,ER(net->last_errno),host, unix_socket,
(ulong) GetLastError());
return INVALID_HANDLE_VALUE;
}
}
if (hPipe == INVALID_HANDLE_VALUE)
{
net->last_errno=CR_NAMEDPIPEOPEN_ERROR;
sprintf(net->last_error,ER(net->last_errno),host, unix_socket,
(ulong) GetLastError());
return INVALID_HANDLE_VALUE;
}
dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) )
{
CloseHandle( hPipe );
net->last_errno=CR_NAMEDPIPESETSTATE_ERROR;
sprintf(net->last_error,ER(net->last_errno),host, unix_socket,
(ulong) GetLastError());
return INVALID_HANDLE_VALUE;
}
*arg_host=host ; *arg_unix_socket=unix_socket; /* connect arg */
return (hPipe);
}
#endif
/* net_get_error */ /* net_get_error */
void net_get_error(char *buf, size_t buf_len, void net_get_error(char *buf, size_t buf_len,
char *error, size_t error_len, char *error, size_t error_len,
@@ -382,14 +175,10 @@ net_safe_read(MYSQL *mysql)
{ {
NET *net= &mysql->net; NET *net= &mysql->net;
ulong len=0; ulong len=0;
init_sigpipe_variables
restart: restart:
/* Don't give sigpipe errors if the client doesn't want them */ if (net->cio != 0)
set_sigpipe(mysql);
if (net->vio != 0)
len=my_net_read(net); len=my_net_read(net);
reset_sigpipe(mysql);
if (len == packet_error || len == 0) if (len == packet_error || len == 0)
{ {
@@ -560,15 +349,12 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
{ {
NET *net= &mysql->net; NET *net= &mysql->net;
int result= -1; int result= -1;
init_sigpipe_variables
DBUG_ENTER("mthd_my_send_command"); DBUG_ENTER("mthd_my_send_command");
DBUG_PRINT("info", ("server_command: %d packet_size: %u", command, length)); DBUG_PRINT("info", ("server_command: %d packet_size: %u", command, length));
/* Don't give sigpipe errors if the client doesn't want them */ if (mysql->net.cio == 0)
set_sigpipe(mysql);
if (mysql->net.vio == 0)
{ /* Do reconnect if possible */ { /* Do reconnect if possible */
if (mysql_reconnect(mysql)) if (mysql_reconnect(mysql))
{ {
@@ -617,7 +403,6 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
DBUG_PRINT("info", ("packet_length=%llu", mysql->packet_length)); DBUG_PRINT("info", ("packet_length=%llu", mysql->packet_length));
} }
end: end:
reset_sigpipe(mysql);
DBUG_RETURN(result); DBUG_RETURN(result);
} }
@@ -782,13 +567,10 @@ static void
end_server(MYSQL *mysql) end_server(MYSQL *mysql)
{ {
DBUG_ENTER("end_server"); DBUG_ENTER("end_server");
if (mysql->net.vio != 0) if (mysql->net.cio != 0)
{ {
init_sigpipe_variables ma_cio_close(mysql->net.cio);
set_sigpipe(mysql); mysql->net.cio= 0; /* Marker */
vio_delete(mysql->net.vio);
reset_sigpipe(mysql);
mysql->net.vio= 0; /* Marker */
} }
net_end(&mysql->net); net_end(&mysql->net);
free_old_query(mysql); free_old_query(mysql);
@@ -845,7 +627,7 @@ static const char *default_options[]=
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name", "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
"multi-results", "multi-statements", "multi-queries", "secure-auth", "multi-results", "multi-statements", "multi-queries", "secure-auth",
"report-data-truncation", "plugin-dir", "default-auth", "database-type", "report-data-truncation", "plugin-dir", "default-auth", "database-type",
"ssl-fp", "ssl-fp-list", "ssl-fp", "ssl-fp-list", "bind-address",
NULL NULL
}; };
@@ -860,7 +642,7 @@ enum option_val
OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name, OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name,
OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth, OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth,
OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth, OPT_db_type, OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth, OPT_db_type,
OPT_ssl_fp, OPT_ssl_fp_list OPT_ssl_fp, OPT_ssl_fp_list, OPT_bind_address
}; };
#define CHECK_OPT_EXTENSION_SET(OPTS)\ #define CHECK_OPT_EXTENSION_SET(OPTS)\
@@ -869,13 +651,15 @@ enum option_val
my_malloc(sizeof(struct st_mysql_options_extension), \ my_malloc(sizeof(struct st_mysql_options_extension), \
MYF(MY_WME | MY_ZEROFILL)); \ MYF(MY_WME | MY_ZEROFILL)); \
#define OPT_SET_EXTENDED_VALUE(OPTS, KEY, VAL, IS_STRING) \ #define OPT_SET_EXTENDED_VALUE_STR(OPTS, KEY, VAL) \
CHECK_OPT_EXTENSION_SET(OPTS) \ CHECK_OPT_EXTENSION_SET(OPTS) \
if (IS_STRING) { \ my_free((gptr)(OPTS)->extension->KEY);\
my_free((OPTS)->extension->KEY); \ (OPTS)->extension->KEY= my_strdup((char *)(VAL), MYF(MY_WME))
(OPTS)->extension->KEY= my_strdup((char *)(VAL), MYF(MY_WME)); \
} else \ #define OPT_SET_EXTENDED_VALUE_INT(OPTS, KEY, VAL) \
(OPTS)->extension->KEY= (VAL); CHECK_OPT_EXTENSION_SET(OPTS) \
+ (OPTS)->extension->KEY= (VAL)
static TYPELIB option_types={array_elements(default_options)-1, static TYPELIB option_types={array_elements(default_options)-1,
"options",default_options}; "options",default_options};
@@ -993,7 +777,7 @@ static void mysql_read_default_options(struct st_mysql_options *options,
case OPT_return_found_rows: case OPT_return_found_rows:
options->client_flag|=CLIENT_FOUND_ROWS; options->client_flag|=CLIENT_FOUND_ROWS;
break; break;
#ifdef HAVE_OPENSSL #ifdef HAVE_SSL
case OPT_ssl_key: case OPT_ssl_key:
my_free(options->ssl_key); my_free(options->ssl_key);
options->ssl_key = my_strdup(opt_arg, MYF(MY_WME)); options->ssl_key = my_strdup(opt_arg, MYF(MY_WME));
@@ -1013,10 +797,10 @@ static void mysql_read_default_options(struct st_mysql_options *options,
case OPT_ssl_cipher: case OPT_ssl_cipher:
break; break;
case OPT_ssl_fp: case OPT_ssl_fp:
OPT_SET_EXTENDED_VALUE(options, ssl_fp, opt_arg, 1); OPT_SET_EXTENDED_VALUE_STR(options, ssl_fp, opt_arg);
break; break;
case OPT_ssl_fp_list: case OPT_ssl_fp_list:
OPT_SET_EXTENDED_VALUE(options, ssl_fp_list, opt_arg, 1); OPT_SET_EXTENDED_VALUE_STR(options, ssl_fp_list, opt_arg);
break; break;
#else #else
case OPT_ssl_key: case OPT_ssl_key:
@@ -1027,7 +811,7 @@ static void mysql_read_default_options(struct st_mysql_options *options,
case OPT_ssl_fp: case OPT_ssl_fp:
case OPT_ssl_fp_list: case OPT_ssl_fp_list:
break; break;
#endif /* HAVE_OPENSSL */ #endif /* HAVE_SSL */
case OPT_charset_dir: case OPT_charset_dir:
my_free(options->charset_dir); my_free(options->charset_dir);
options->charset_dir = my_strdup(opt_arg, MYF(MY_WME)); options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
@@ -1088,12 +872,16 @@ static void mysql_read_default_options(struct st_mysql_options *options,
if (strlen(opt_arg) >= FN_REFLEN) if (strlen(opt_arg) >= FN_REFLEN)
opt_arg[FN_REFLEN]= 0; opt_arg[FN_REFLEN]= 0;
if (!my_realpath(directory, opt_arg, 0)) if (!my_realpath(directory, opt_arg, 0))
OPT_SET_EXTENDED_VALUE(options, plugin_dir, convert_dirname(directory), 1); OPT_SET_EXTENDED_VALUE_STR(options, plugin_dir, convert_dirname(directory));
} }
break; break;
case OPT_default_auth: case OPT_default_auth:
OPT_SET_EXTENDED_VALUE(options, default_auth, opt_arg, 1); OPT_SET_EXTENDED_VALUE_STR(options, default_auth, opt_arg);
break; break;
case OPT_bind_address:
my_free(options->bind_address);
options->bind_address= my_strdup(opt_arg, MYF(MY_WME));
break;
default: default:
DBUG_PRINT("warning",("unknown option: %s",option[0])); DBUG_PRINT("warning",("unknown option: %s",option[0]));
} }
@@ -1346,7 +1134,7 @@ mysql_init(MYSQL *mysql)
if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL)))) if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
return 0; return 0;
mysql->free_me=1; mysql->free_me=1;
mysql->net.vio= 0; mysql->net.cio= 0;
} }
else else
bzero((char*) (mysql),sizeof(*(mysql))); bzero((char*) (mysql),sizeof(*(mysql)));
@@ -1391,10 +1179,10 @@ mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert,
const char * STDCALL const char * STDCALL
mysql_get_ssl_cipher(MYSQL *mysql) mysql_get_ssl_cipher(MYSQL *mysql)
{ {
#ifdef HAVE_OPENSSL #ifdef HAVE_SSL
if (mysql->net.vio && mysql->net.vio->ssl) if (mysql->net.cio && mysql->net.cio->cssl)
{ {
return SSL_get_cipher_name(mysql->net.vio->ssl); return ma_cio_ssl_cipher(mysql->net.cio->cssl);
} }
#endif #endif
return(NULL); return(NULL);
@@ -1516,18 +1304,12 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
char buff[NAME_LEN+USERNAME_LENGTH+100]; char buff[NAME_LEN+USERNAME_LENGTH+100];
char *end, *end_pkt, *host_info, char *end, *end_pkt, *host_info,
*charset_name= NULL; *charset_name= NULL;
my_socket sock; MA_CIO_CINFO cinfo= {NULL, NULL, 0, -1, NULL};
MARIADB_CIO *cio= NULL;
char *scramble_data; char *scramble_data;
const char *scramble_plugin; const char *scramble_plugin;
uint pkt_length, scramble_len, pkt_scramble_len= 0; uint pkt_length, scramble_len, pkt_scramble_len= 0;
NET *net= &mysql->net; NET *net= &mysql->net;
#ifdef _WIN32
HANDLE hPipe=INVALID_HANDLE_VALUE;
#endif
#ifdef HAVE_SYS_UN_H
struct sockaddr_un UNIXaddr;
#endif
init_sigpipe_variables
DBUG_ENTER("mysql_real_connect"); DBUG_ENTER("mysql_real_connect");
DBUG_PRINT("enter",("host: %s db: %s user: %s", DBUG_PRINT("enter",("host: %s db: %s user: %s",
@@ -1537,15 +1319,12 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
ma_set_connect_attrs(mysql); ma_set_connect_attrs(mysql);
if (net->vio) /* check if we are already connected */ if (net->cio) /* check if we are already connected */
{ {
SET_CLIENT_ERROR(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0); SET_CLIENT_ERROR(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0);
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
} }
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
/* use default options */ /* use default options */
if (mysql->options.my_cnf_file || mysql->options.my_cnf_group) if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
{ {
@@ -1583,192 +1362,75 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
mysql->reconnect=1; */ mysql->reconnect=1; */
mysql->server_status=SERVER_STATUS_AUTOCOMMIT; mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
/* try to connect via cio_init */
cinfo.host= host;
cinfo.unix_socket= unix_socket;
cinfo.port= port;
cinfo.mysql= mysql;
/* /*
** Grab a socket and connect it to the server ** Grab a socket and connect it to the server
*/ */
#ifndef _WIN32
#if defined(HAVE_SYS_UN_H) #if defined(HAVE_SYS_UN_H)
if ((!host || strcmp(host,LOCAL_HOST) == 0) && if ((!host || strcmp(host,LOCAL_HOST) == 0) &&
mysql->options.protocol != MYSQL_PROTOCOL_TCP && mysql->options.protocol != MYSQL_PROTOCOL_TCP &&
(unix_socket || mysql_unix_port)) (unix_socket || mysql_unix_port))
{ {
host=LOCAL_HOST; cinfo.host= LOCAL_HOST;
if (!unix_socket) cinfo.unix_socket= (unix_socket) ? unix_socket : mysql_unix_port;
unix_socket=mysql_unix_port; cinfo.type= CIO_TYPE_UNIXSOCKET;
host_info=(char*) ER(CR_LOCALHOST_CONNECTION); sprintf(host_info=buff,ER(CR_LOCALHOST_CONNECTION),cinfo.host);
DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket));
if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR)
{
net->last_errno=CR_SOCKET_CREATE_ERROR;
sprintf(net->last_error,ER(net->last_errno),socket_errno);
goto error;
}
net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE);
bzero((char*) &UNIXaddr,sizeof(UNIXaddr));
UNIXaddr.sun_family = AF_UNIX;
strmov(UNIXaddr.sun_path, unix_socket);
if (connect_sync_or_async(mysql, net, sock,
(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr)))
{
DBUG_PRINT("error",("Got error %d on connect to local server",socket_errno));
my_set_error(mysql, CR_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_CONNECTION_ERROR),
unix_socket, socket_errno);
goto error;
}
if (socket_block(sock, 1) == SOCKET_ERROR)
goto error;
} }
else else
#elif defined(_WIN32) #endif
#else
/* named pipe */
if ((unix_socket ||
(!host && is_NT()) ||
(host && strcmp(host,LOCAL_HOST_NAMEDPIPE) == 0) ||
mysql->options.named_pipe ||
!have_tcpip) &&
mysql->options.protocol != MYSQL_PROTOCOL_TCP)
{ {
if ((unix_socket || cinfo.type= CIO_TYPE_NAMEDPIPE;
(!host && is_NT()) || sprintf(host_info=buff,ER(CR_NAMEDPIPE_CONNECTION),cinfo.host);
(host && strcmp(host,LOCAL_HOST_NAMEDPIPE) == 0) ||
mysql->options.named_pipe ||
!have_tcpip) &&
mysql->options.protocol != MYSQL_PROTOCOL_TCP)
{
sock=0;
if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout,
(char**) &host, (char**) &unix_socket)) ==
INVALID_HANDLE_VALUE)
{
DBUG_PRINT("error",
("host: '%s' socket: '%s' named_pipe: %d have_tcpip: %d",
host ? host : "<null>",
unix_socket ? unix_socket : "<null>",
(int) mysql->options.named_pipe,
(int) have_tcpip));
if (mysql->options.named_pipe ||
(host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
(unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE)))
goto error; /* User only requested named pipes */
/* Try also with TCP/IP */
}
else
{
net->vio=vio_new_win32pipe(hPipe);
sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host,
unix_socket);
}
}
} }
if (hPipe == INVALID_HANDLE_VALUE) else
#endif #endif
{ {
struct addrinfo hints, *save_res= 0, *res= 0; cinfo.unix_socket=0; /* This is not used */
char server_port[NI_MAXSERV];
int gai_rc;
int rc;
unix_socket=0; /* This is not used */
if (!port) if (!port)
port=mysql_port; port=mysql_port;
if (!host) if (!host)
host=LOCAL_HOST; host=LOCAL_HOST;
sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); cinfo.host= host;
bzero(&server_port, NI_MAXSERV); cinfo.port= port;
cinfo.type= CIO_TYPE_SOCKET;
DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); sprintf(host_info=buff,ER(CR_TCP_CONNECTION), cinfo.host);
my_snprintf(server_port, NI_MAXSERV, "%d", port);
/* set hints for getaddrinfo */
bzero(&hints, sizeof(hints));
hints.ai_protocol= IPPROTO_TCP; /* TCP connections only */
hints.ai_family= AF_UNSPEC; /* includes: IPv4, IPv6 or hostname */
hints.ai_socktype= SOCK_STREAM;
/* Get the address information for the server using getaddrinfo() */
gai_rc= getaddrinfo(host, server_port, &hints, &res);
if (gai_rc != 0)
{
my_set_error(mysql, CR_UNKNOWN_HOST, SQLSTATE_UNKNOWN,
ER(CR_UNKNOWN_HOST), host, gai_rc);
goto error;
}
/* res is a linked list of addresses. If connect to an address fails we will not return
an error, instead we will try the next address */
for (save_res= res; save_res; save_res= save_res->ai_next)
{
sock= socket(save_res->ai_family, save_res->ai_socktype,
save_res->ai_protocol);
if (sock == SOCKET_ERROR)
/* we do error handling after for loop only for last call */
continue;
if (!(net->vio= vio_new(sock, VIO_TYPE_TCPIP, FALSE)))
{
my_set_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
closesocket(sock);
freeaddrinfo(res);
goto error;
}
rc= connect_sync_or_async(mysql, net, sock,
save_res->ai_addr, save_res->ai_addrlen);
if (!rc)
{
if (mysql->options.extension && mysql->options.extension->async_context &&
mysql->options.extension->async_context->active)
break;
else if (socket_block(sock, 1) == SOCKET_ERROR)
{
closesocket(sock);
continue;
}
break; /* success! */
}
vio_delete(mysql->net.vio);
mysql->net.vio= NULL;
}
freeaddrinfo(res);
if (sock == SOCKET_ERROR)
{
my_set_error(mysql, CR_IPSOCK_ERROR, SQLSTATE_UNKNOWN, ER(CR_IPSOCK_ERROR),
socket_errno);
goto error;
}
/* last call to connect 2 failed */
if (rc)
{
my_set_error(mysql, CR_CONN_HOST_ERROR, SQLSTATE_UNKNOWN, ER(CR_CONN_HOST_ERROR),
host, socket_errno);
goto error;
}
} }
/* Initialize and load cio plugin */
if (!(cio= ma_cio_init(&cinfo)))
goto error;
/* set timeouts */ /* try to connect */
net->vio->read_timeout= mysql->options.read_timeout; if (ma_cio_connect(cio, &cinfo) != 0)
net->vio->write_timeout= mysql->options.write_timeout;
if (mysql->options.extension && mysql->options.extension->async_context)
net->vio->async_context= mysql->options.extension->async_context;
if (!net->vio || my_net_init(net, net->vio))
{ {
vio_delete(net->vio); ma_cio_close(cio);
net->vio = 0;
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
goto error; goto error;
} }
vio_keepalive(net->vio,TRUE);
if (my_net_init(net, cio))
goto error;
ma_cio_keepalive(net->cio);
strmov(mysql->net.sqlstate, "00000"); strmov(mysql->net.sqlstate, "00000");
/* set read timeout */
if (mysql->options.read_timeout >= 0)
vio_read_timeout(net->vio, mysql->options.read_timeout);
/* set write timeout */
if (mysql->options.write_timeout >= 0)
vio_write_timeout(net->vio, mysql->options.read_timeout);
/* Get version info */ /* Get version info */
mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */
if (mysql->options.connect_timeout >= 0 && /*
vio_wait_or_timeout(net->vio, FALSE, mysql->options.connect_timeout * 1000) < 1) if (ma_cio_wait_io_or_timeout(net->cio, FALSE, 0) < 1)
{ {
my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN, my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
ER(CR_SERVER_LOST_EXTENDED), ER(CR_SERVER_LOST_EXTENDED),
@@ -1776,6 +1438,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
errno); errno);
goto error; goto error;
} }
*/
if ((pkt_length=net_safe_read(mysql)) == packet_error) if ((pkt_length=net_safe_read(mysql)) == packet_error)
{ {
if (mysql->net.last_errno == CR_SERVER_LOST) if (mysql->net.last_errno == CR_SERVER_LOST)
@@ -1821,9 +1484,9 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
if (!my_multi_malloc(MYF(0), if (!my_multi_malloc(MYF(0),
&mysql->host_info, (uint) strlen(host_info)+1, &mysql->host_info, (uint) strlen(host_info)+1,
&mysql->host, (uint) strlen(host)+1, &mysql->host, (uint) strlen(cinfo.host)+1,
&mysql->unix_socket,unix_socket ? &mysql->unix_socket, cinfo.unix_socket ?
(uint) strlen(unix_socket)+1 : (uint) 1, (uint) strlen(cinfo.unix_socket)+1 : (uint) 1,
&mysql->server_version, (uint) (end - (char*) net->read_pos), &mysql->server_version, (uint) (end - (char*) net->read_pos),
NullS) || NullS) ||
!(mysql->user=my_strdup(user,MYF(0))) || !(mysql->user=my_strdup(user,MYF(0))) ||
@@ -1833,9 +1496,9 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
goto error; goto error;
} }
strmov(mysql->host_info,host_info); strmov(mysql->host_info,host_info);
strmov(mysql->host,host); strmov(mysql->host, cinfo.host);
if (unix_socket) if (cinfo.unix_socket)
strmov(mysql->unix_socket,unix_socket); strmov(mysql->unix_socket, cinfo.unix_socket);
else else
mysql->unix_socket=0; mysql->unix_socket=0;
mysql->port=port; mysql->port=port;
@@ -1985,11 +1648,9 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
strmov(mysql->net.sqlstate, "00000"); strmov(mysql->net.sqlstate, "00000");
DBUG_PRINT("exit",("Mysql handler: %lx",mysql)); DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
reset_sigpipe(mysql);
DBUG_RETURN(mysql); DBUG_RETURN(mysql);
error: error:
reset_sigpipe(mysql);
DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error)); DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error));
{ {
/* Free alloced memory */ /* Free alloced memory */
@@ -2002,7 +1663,6 @@ error:
DBUG_RETURN(0); DBUG_RETURN(0);
} }
static my_bool mysql_reconnect(MYSQL *mysql) static my_bool mysql_reconnect(MYSQL *mysql)
{ {
MYSQL tmp_mysql; MYSQL tmp_mysql;
@@ -2025,13 +1685,13 @@ static my_bool mysql_reconnect(MYSQL *mysql)
tmp_mysql.options.my_cnf_group= tmp_mysql.options.my_cnf_file= NULL; tmp_mysql.options.my_cnf_group= tmp_mysql.options.my_cnf_file= NULL;
/* make sure that we reconnect with the same character set */ /* make sure that we reconnect with the same character set */
if (!tmp_mysql.options.charset_name || /* if (!tmp_mysql.options.charset_name ||
strcmp(tmp_mysql.options.charset_name, mysql->charset->csname)) strcmp(tmp_mysql.options.charset_name, mysql->charset->csname))
{ {
my_free(tmp_mysql.options.charset_name); my_free(tmp_mysql.options.charset_name);
tmp_mysql.options.charset_name= my_strdup(mysql->charset->csname, MYF(MY_WME)); tmp_mysql.options.charset_name= my_strdup(mysql->charset->csname, MYF(MY_WME));
} }
*/
tmp_mysql.reconnect= mysql->reconnect; tmp_mysql.reconnect= mysql->reconnect;
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,
@@ -2252,7 +1912,7 @@ void my_set_error(MYSQL *mysql,
void mysql_close_slow_part(MYSQL *mysql) void mysql_close_slow_part(MYSQL *mysql)
{ {
if (mysql->net.vio) if (mysql->net.cio)
{ {
free_old_query(mysql); free_old_query(mysql);
mysql->status=MYSQL_STATUS_READY; /* Force command */ mysql->status=MYSQL_STATUS_READY; /* Force command */
@@ -2288,7 +1948,7 @@ mysql_close(MYSQL *mysql)
/* Clear pointers for better safety */ /* Clear pointers for better safety */
bzero((char*) &mysql->options,sizeof(mysql->options)); bzero((char*) &mysql->options,sizeof(mysql->options));
mysql->net.vio= 0; mysql->net.cio= 0;
if (mysql->free_me) if (mysql->free_me)
my_free(mysql); my_free(mysql);
} }
@@ -2931,7 +2591,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
#else #else
if (*(uint *)arg1 > MYSQL_PROTOCOL_SOCKET) if (*(uint *)arg1 > MYSQL_PROTOCOL_SOCKET)
#endif #endif
DBUG_RETURN(-1); goto end;
mysql->options.protocol= *(uint *)arg1; mysql->options.protocol= *(uint *)arg1;
break; break;
case MYSQL_OPT_READ_TIMEOUT: case MYSQL_OPT_READ_TIMEOUT:
@@ -2953,11 +2613,12 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
(void (*)(const MYSQL *, uint, uint, double, const char *, uint)) arg1; (void (*)(const MYSQL *, uint, uint, double, const char *, uint)) arg1;
break; break;
case MYSQL_PLUGIN_DIR: case MYSQL_PLUGIN_DIR:
OPT_SET_EXTENDED_VALUE(&mysql->options, plugin_dir, (char *)arg1, 1); OPT_SET_EXTENDED_VALUE_STR(&mysql->options, plugin_dir, (char *)arg1);
break; break;
case MYSQL_DEFAULT_AUTH: case MYSQL_DEFAULT_AUTH:
OPT_SET_EXTENDED_VALUE(&mysql->options, default_auth, (char *)arg1, 1); OPT_SET_EXTENDED_VALUE_STR(&mysql->options, default_auth, (char *)arg1);
break; break;
/*
case MYSQL_DATABASE_DRIVER: case MYSQL_DATABASE_DRIVER:
{ {
MARIADB_DB_PLUGIN *db_plugin; MARIADB_DB_PLUGIN *db_plugin;
@@ -2981,6 +2642,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
} }
} }
break; break;
*/
case MYSQL_OPT_NONBLOCK: case MYSQL_OPT_NONBLOCK:
if (mysql->options.extension && if (mysql->options.extension &&
(ctxt = mysql->options.extension->async_context) != 0) (ctxt = mysql->options.extension->async_context) != 0)
@@ -2990,7 +2652,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
suspended (as the stack is then in use). suspended (as the stack is then in use).
*/ */
if (ctxt->suspended) if (ctxt->suspended)
DBUG_RETURN(1); goto end;
my_context_destroy(&ctxt->async_context); my_context_destroy(&ctxt->async_context);
my_free(ctxt); my_free(ctxt);
} }
@@ -2998,7 +2660,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
my_malloc(sizeof(*ctxt), MYF(MY_ZEROFILL)))) my_malloc(sizeof(*ctxt), MYF(MY_ZEROFILL))))
{ {
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
DBUG_RETURN(1); goto end;
} }
stacksize= 0; stacksize= 0;
if (arg1) if (arg1)
@@ -3008,7 +2670,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
if (my_context_init(&ctxt->async_context, stacksize)) if (my_context_init(&ctxt->async_context, stacksize))
{ {
my_free(ctxt); my_free(ctxt);
DBUG_RETURN(1); goto end;
} }
if (!mysql->options.extension) if (!mysql->options.extension)
if(!(mysql->options.extension= (struct st_mysql_options_extension *) if(!(mysql->options.extension= (struct st_mysql_options_extension *)
@@ -3016,11 +2678,11 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
MYF(MY_WME | MY_ZEROFILL)))) MYF(MY_WME | MY_ZEROFILL))))
{ {
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
DBUG_RETURN(1); goto end;
} }
mysql->options.extension->async_context= ctxt; mysql->options.extension->async_context= ctxt;
if (mysql->net.vio) if (mysql->net.cio)
mysql->net.vio->async_context= ctxt; mysql->net.cio->async_context= ctxt;
break; break;
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
@@ -3050,16 +2712,10 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
mysql->options.ssl_cipher=my_strdup((char *)arg1,MYF(MY_WME)); mysql->options.ssl_cipher=my_strdup((char *)arg1,MYF(MY_WME));
break; break;
case MYSQL_OPT_SSL_CRL: case MYSQL_OPT_SSL_CRL:
OPT_SET_EXTENDED_VALUE(&mysql->options, ssl_crl, (char *)arg1, 1); OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_crl, (char *)arg1);
break; break;
case MYSQL_OPT_SSL_CRLPATH: case MYSQL_OPT_SSL_CRLPATH:
OPT_SET_EXTENDED_VALUE(&mysql->options, ssl_crlpath, (char *)arg1, 1); OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_crlpath, (char *)arg1);
break;
case MARIADB_OPT_SSL_FP:
OPT_SET_EXTENDED_VALUE(&mysql->options, ssl_fp, (char *)arg1, 1);
break;
case MARIADB_OPT_SSL_FP_LIST:
OPT_SET_EXTENDED_VALUE(&mysql->options, ssl_fp_list, (char *)arg1, 1);
break; break;
case MYSQL_OPT_CONNECT_ATTR_DELETE: case MYSQL_OPT_CONNECT_ATTR_DELETE:
{ {
@@ -3148,6 +2804,10 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
case MYSQL_SECURE_AUTH: case MYSQL_SECURE_AUTH:
mysql->options.secure_auth= *(my_bool *)arg1; mysql->options.secure_auth= *(my_bool *)arg1;
break; break;
case MYSQL_OPT_BIND:
my_free(mysql->options.bind_address);
mysql->options.bind_address= my_strdup(arg1, MYF(MY_WME));
break;
default: default:
va_end(ap); va_end(ap);
DBUG_RETURN(-1); DBUG_RETURN(-1);
@@ -3452,9 +3112,6 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)),
mysql_unix_port = env; mysql_unix_port = env;
} }
mysql_debug(NullS); mysql_debug(NullS);
#if defined(SIGPIPE) && !defined(THREAD) && !defined(_WIN32)
(void) signal(SIGPIPE,SIG_IGN);
#endif
} }
#ifdef THREAD #ifdef THREAD
else else
@@ -3469,12 +3126,10 @@ void STDCALL mysql_server_end()
{ {
if (!mysql_client_init) if (!mysql_client_init)
return; return;
#ifdef HAVE_OPENSSL
my_ssl_end();
#endif
mysql_client_plugin_deinit(); mysql_client_plugin_deinit();
list_free(cio_callback, 0);
if (my_init_done) if (my_init_done)
my_end(0); my_end(0);
mysql_client_init= 0; mysql_client_init= 0;
@@ -3550,9 +3205,13 @@ mysql_get_parameters(void)
my_socket STDCALL my_socket STDCALL
mysql_get_socket(const MYSQL *mysql) mysql_get_socket(const MYSQL *mysql)
{ {
if (mysql->net.vio) my_socket sock;
return vio_fd(mysql->net.vio); if (mysql->net.cio)
return MARIADB_INVALID_SOCKET; {
ma_cio_get_handle(mysql->net.cio, &sock);
return sock;
}
return INVALID_SOCKET;
} }
/* /*

View File

@@ -53,7 +53,7 @@
#include "mysql_version.h" #include "mysql_version.h"
#include "mysqld_error.h" #include "mysqld_error.h"
#include "errmsg.h" #include "errmsg.h"
#include <violite.h> #include <ma_cio.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
@@ -988,7 +988,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
{ {
DBUG_ENTER("mysql_stmt_close"); DBUG_ENTER("mysql_stmt_close");
if (stmt && stmt->mysql && stmt->mysql->net.vio) if (stmt && stmt->mysql && stmt->mysql->net.cio)
mysql_stmt_reset(stmt); mysql_stmt_reset(stmt);
net_stmt_close(stmt, 1); net_stmt_close(stmt, 1);

View File

@@ -30,8 +30,9 @@
#include "ma_common.h" #include "ma_common.h"
#endif #endif
#include "my_context.h" #include "my_context.h"
#include "violite.h" #include "ma_cio.h"
#include "mysql_async.h" #include "mysql_async.h"
#include <string.h>
#ifdef _WIN32 #ifdef _WIN32
@@ -41,7 +42,7 @@
*/ */
#define WIN_SET_NONBLOCKING(mysql) { \ #define WIN_SET_NONBLOCKING(mysql) { \
my_bool old_mode; \ my_bool old_mode; \
if ((mysql)->net.vio) vio_blocking((mysql)->net.vio, FALSE, &old_mode); \ if ((mysql)->net.cio) ma_cio_blocking((mysql)->net.cio, FALSE, &old_mode); \
} }
#else #else
#define WIN_SET_NONBLOCKING(mysql) #define WIN_SET_NONBLOCKING(mysql)
@@ -62,19 +63,18 @@ my_context_install_suspend_resume_hook(struct mysql_async_context *b,
/* Asynchronous connect(); socket must already be set non-blocking. */ /* Asynchronous connect(); socket must already be set non-blocking. */
int int
my_connect_async(struct mysql_async_context *b, my_socket fd, my_connect_async(MARIADB_CIO *cio,
const struct sockaddr *name, uint namelen, int vio_timeout) const struct sockaddr *name, uint namelen, int vio_timeout)
{ {
int res; int res;
size_socket s_err_size; size_socket s_err_size;
struct mysql_async_context *b= cio->mysql->options.extension->async_context;
my_socket sock;
ma_cio_get_handle(cio, &sock);
/* Make the socket non-blocking. */ /* Make the socket non-blocking. */
#ifdef _WIN32 ma_cio_blocking(cio, 0, 0);
ulong arg= 1;
ioctlsocket(fd, FIONBIO, (void *)&arg);
#else
fcntl(fd, F_SETFL, O_NONBLOCK);
#endif
b->events_to_wait_for= 0; b->events_to_wait_for= 0;
/* /*
@@ -83,7 +83,7 @@ my_connect_async(struct mysql_async_context *b, my_socket fd,
application context. The application will then resume us when the socket application context. The application will then resume us when the socket
polls ready for write, indicating that the connection attempt completed. polls ready for write, indicating that the connection attempt completed.
*/ */
res= connect(fd, name, namelen); res= connect(sock, name, namelen);
if (res != 0) if (res != 0)
{ {
#ifdef _WIN32 #ifdef _WIN32
@@ -113,7 +113,7 @@ my_connect_async(struct mysql_async_context *b, my_socket fd,
return -1; return -1;
s_err_size= sizeof(res); s_err_size= sizeof(res);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0) if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0)
return -1; return -1;
if (res) if (res)
{ {
@@ -135,14 +135,15 @@ my_connect_async(struct mysql_async_context *b, my_socket fd,
#endif #endif
ssize_t ssize_t
my_recv_async(struct mysql_async_context *b, int fd, my_recv_async(MARIADB_CIO *cio, const unsigned char *buf, size_t size, int timeout)
unsigned char *buf, size_t size, int timeout)
{ {
ssize_t res; ssize_t res;
struct mysql_async_context *b= cio->async_context;
for (;;) for (;;)
{ {
res= recv(fd, buf, size, IF_WIN(0, MSG_DONTWAIT)); /* todo: async */
if (cio->methods->async_read)
res= cio->methods->async_read(cio, buf, size);
if (res >= 0 || IS_BLOCKING_ERROR()) if (res >= 0 || IS_BLOCKING_ERROR())
return res; return res;
b->events_to_wait_for= MYSQL_WAIT_READ; b->events_to_wait_for= MYSQL_WAIT_READ;
@@ -163,14 +164,15 @@ my_recv_async(struct mysql_async_context *b, int fd,
ssize_t ssize_t
my_send_async(struct mysql_async_context *b, int fd, my_send_async(MARIADB_CIO *cio, const unsigned char *buf, size_t size, int timeout)
const unsigned char *buf, size_t size, int timeout)
{ {
ssize_t res; ssize_t res;
struct mysql_async_context *b= cio->async_context;
for (;;) for (;;)
{ {
res= send(fd, buf, size, IF_WIN(0, MSG_DONTWAIT)); if (cio->methods->async_write)
res= cio->methods->async_write(cio, buf, size);
if (res >= 0 || IS_BLOCKING_ERROR()) if (res >= 0 || IS_BLOCKING_ERROR())
return res; return res;
b->events_to_wait_for= MYSQL_WAIT_WRITE; b->events_to_wait_for= MYSQL_WAIT_WRITE;
@@ -191,7 +193,7 @@ my_send_async(struct mysql_async_context *b, int fd,
my_bool my_bool
my_io_wait_async(struct mysql_async_context *b, enum enum_vio_io_event event, my_io_wait_async(struct mysql_async_context *b, enum enum_cio_io_event event,
int timeout) int timeout)
{ {
switch (event) switch (event)
@@ -221,9 +223,9 @@ my_io_wait_async(struct mysql_async_context *b, enum enum_vio_io_event event,
} }
#ifdef HAVE_OPENSSL #ifdef HAVE_SSL_FIXME
static my_bool static my_bool
my_ssl_async_check_result(int res, struct mysql_async_context *b, SSL *ssl) my_ssl_async_check_result(int res, struct mysql_async_context *b, MARIADB_SSL *cssl)
{ {
int ssl_err; int ssl_err;
b->events_to_wait_for= 0; b->events_to_wait_for= 0;
@@ -496,18 +498,36 @@ MK_ASYNC_INTERNAL_BODY(
int STDCALL int STDCALL
mysql_real_query_start(int *ret, MYSQL *mysql, const char *stmt_str, unsigned long length) mysql_real_query_start(int *ret, MYSQL *mysql, const char *stmt_str, unsigned long length)
{ {
MK_ASYNC_START_BODY( int res;
mysql_real_query, struct mysql_async_context *b;
mysql, struct mysql_real_query_params parms;
b= mysql->options.extension->async_context;
{ {
WIN_SET_NONBLOCKING(mysql) WIN_SET_NONBLOCKING(mysql)
parms.mysql= mysql; parms.mysql= mysql;
parms.stmt_str= stmt_str; parms.stmt_str= stmt_str;
parms.length= length; parms.length= length;
}, }
1,
r_int, b->active= 1;
/* Nothing */) res= my_context_spawn(&b->async_context, mysql_real_query_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), CR_OUT_OF_MEMORY, unknown_sqlstate);
*ret= 1;
}
else
*ret= b->ret_result.r_int;
return 0;
} }
int STDCALL int STDCALL
mysql_real_query_cont(int *ret, MYSQL *mysql, int ready_status) mysql_real_query_cont(int *ret, MYSQL *mysql, int ready_status)

View File

@@ -22,8 +22,10 @@
** 3 byte length & 1 byte package-number. ** 3 byte length & 1 byte package-number.
*/ */
#include <my_global.h> #include <my_global.h>
#include <violite.h> #include <mysql.h>
#include <ma_cio.h>
#include <my_sys.h> #include <my_sys.h>
#include <m_string.h> #include <m_string.h>
#include "mysql.h" #include "mysql.h"
@@ -31,6 +33,7 @@
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
#include <ma_cio.h>
#ifndef _WIN32 #ifndef _WIN32
#include <poll.h> #include <poll.h>
#endif #endif
@@ -46,7 +49,7 @@
ulong max_allowed_packet=1024L * 1024L * 1024L; ulong max_allowed_packet=1024L * 1024L * 1024L;
ulong net_read_timeout= NET_READ_TIMEOUT; ulong net_read_timeout= NET_READ_TIMEOUT;
ulong net_write_timeout= NET_WRITE_TIMEOUT; ulong net_write_timeout= NET_WRITE_TIMEOUT;
ulong net_buffer_length=8192; /* Default length. Enlarged if necessary */ ulong net_buffer_length= 8192; /* Default length. Enlarged if necessary */
#if !defined(_WIN32) && !defined(MSDOS) #if !defined(_WIN32) && !defined(MSDOS)
#include <sys/socket.h> #include <sys/socket.h>
@@ -110,13 +113,13 @@ static int net_write_buff(NET *net,const char *packet, size_t len);
/* Init with packet info */ /* Init with packet info */
int my_net_init(NET *net, Vio* vio) int my_net_init(NET *net, MARIADB_CIO* cio)
{ {
if (!(net->buff=(uchar*) my_malloc(net_buffer_length,MYF(MY_WME | MY_ZEROFILL)))) if (!(net->buff=(uchar*) my_malloc(net_buffer_length,MYF(MY_WME | MY_ZEROFILL))))
return 1; return 1;
max_allowed_packet= net->max_packet_size= MAX(net_buffer_length, max_allowed_packet); max_allowed_packet= net->max_packet_size= MAX(net_buffer_length, max_allowed_packet);
net->buff_end=net->buff+(net->max_packet=net_buffer_length); net->buff_end=net->buff+(net->max_packet=net_buffer_length);
net->vio = vio; net->cio = cio;
net->error=0; net->return_status=0; net->error=0; net->return_status=0;
net->read_timeout=(uint) net_read_timeout; /* Timeout for read */ net->read_timeout=(uint) net_read_timeout; /* Timeout for read */
net->compress_pkt_nr= net->pkt_nr= 0; net->compress_pkt_nr= net->pkt_nr= 0;
@@ -127,21 +130,18 @@ int my_net_init(NET *net, Vio* vio)
net->where_b = net->remain_in_buf=0; net->where_b = net->remain_in_buf=0;
net->last_errno=0; net->last_errno=0;
if (vio != 0) /* If real connection */ if (cio != 0) /* If real connection */
{ {
net->fd = vio_fd(vio); /* For perl DBI/DBD */ ma_cio_get_handle(cio, &net->fd);
#if defined(MYSQL_SERVER) && !defined(__WIN32) && !defined(__EMX__) && !defined(OS2) ma_cio_blocking(cio, 1, 0);
if (!(test_flags & TEST_BLOCKING)) ma_cio_fast_send(cio);
vio_blocking(vio, FALSE, 0);
#endif
vio_fastsend(vio);
} }
return 0; return 0;
} }
void net_end(NET *net) void net_end(NET *net)
{ {
my_free(net->buff); my_free((gptr) net->buff);
net->buff=0; net->buff=0;
} }
@@ -219,15 +219,17 @@ static my_bool net_check_socket_status(my_socket sock)
void net_clear(NET *net) void net_clear(NET *net)
{ {
my_socket sock;
DBUG_ENTER("net_clear"); DBUG_ENTER("net_clear");
ma_cio_get_handle(net->cio, &sock);
/* see conc-71: we need to check the socket status first: /* see conc-71: we need to check the socket status first:
if the socket is dead we set net->error, so net_flush if the socket is dead we set net->error, so net_flush
will report an error */ will report an error */
while (net_check_socket_status(net->vio->sd)) while (net_check_socket_status(sock))
{ {
/* vio_read returns size_t. so casting to long is required to check for -1 */ if ((ssize_t)ma_cio_cache_read(net->cio, (gptr)net->buff, (size_t) net->max_packet) <= 0)
if ((long)vio_read(net->vio, (gptr)net->buff, (size_t) net->max_packet) <= 0)
{ {
net->error= 2; net->error= 2;
DBUG_PRINT("info", ("socket disconnected")); DBUG_PRINT("info", ("socket disconnected"));
@@ -384,12 +386,6 @@ net_real_write(NET *net,const char *packet,size_t len)
{ {
size_t length; size_t length;
char *pos,*end; char *pos,*end;
thr_alarm_t alarmed;
#if !defined(_WIN32) && !defined(__EMX__) && !defined(OS2)
ALARM alarm_buff;
#endif
uint retry_count=0;
my_bool net_blocking = vio_is_blocking(net->vio);
DBUG_ENTER("net_real_write"); DBUG_ENTER("net_real_write");
if (net->error == 2) if (net->error == 2)
@@ -426,79 +422,23 @@ net_real_write(NET *net,const char *packet,size_t len)
} }
#endif /* HAVE_COMPRESS */ #endif /* HAVE_COMPRESS */
alarmed=0;
pos=(char*) packet; end=pos+len; pos=(char*) packet; end=pos+len;
while (pos != end) while (pos != end)
{ {
if ((long) (length=vio_write(net->vio,pos,(size_t) (end-pos))) <= 0) if ((ssize_t) (length=ma_cio_write(net->cio,pos,(size_t) (end-pos))) <= 0)
{ {
my_bool interrupted = vio_should_retry(net->vio);
#if (!defined(_WIN32) && !defined(__EMX__) && !defined(OS2))
if ((interrupted || length==0) && !thr_alarm_in_use(&alarmed))
{
if (!thr_alarm(&alarmed,(uint) net_write_timeout,&alarm_buff))
{ /* Always true for client */
if (!vio_is_blocking(net->vio))
{
while (vio_blocking(net->vio, TRUE, 0) < 0)
{
if (vio_should_retry(net->vio) && retry_count++ < RETRY_COUNT)
continue;
#ifdef EXTRA_DEBUG
fprintf(stderr,
"%s: my_net_write: fcntl returned error %d, aborting thread\n",
my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */
net->error=2; /* Close socket */
net->last_errno= (interrupted ?
ER_NET_WRITE_INTERRUPTED : ER_NET_ERROR_ON_WRITE);
goto end;
}
}
retry_count=0;
continue;
}
}
else
#endif /* (!defined(_WIN32) && !defined(__EMX__)) */
if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) &&
interrupted)
{
if (retry_count++ < RETRY_COUNT)
continue;
#ifdef EXTRA_DEBUG
fprintf(stderr, "%s: write looped, aborting thread\n",
my_progname);
#endif /* EXTRA_DEBUG */
}
#if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER)
if (vio_errno(net->vio) == SOCKET_EINTR)
{
DBUG_PRINT("warning",("Interrupted write. Retrying..."));
continue;
}
#endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */
net->error=2; /* Close socket */ net->error=2; /* Close socket */
net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED : net->last_errno= ER_NET_ERROR_ON_WRITE;
ER_NET_ERROR_ON_WRITE); net->reading_or_writing=0;
break; DBUG_RETURN(1);
} }
pos+=length; pos+=length;
statistic_add(bytes_sent,length,&LOCK_bytes_sent); statistic_add(bytes_sent,length,&LOCK_bytes_sent);
} }
#ifndef _WIN32
end:
#endif
#ifdef HAVE_COMPRESS #ifdef HAVE_COMPRESS
if (net->compress) if (net->compress)
my_free((void *)packet); my_free((char*) packet);
#endif #endif
if (thr_alarm_in_use(&alarmed))
{
thr_end_alarm(&alarmed);
vio_blocking(net->vio, net_blocking, 0);
}
net->reading_or_writing=0; net->reading_or_writing=0;
DBUG_RETURN(((int) (pos != end))); DBUG_RETURN(((int) (pos != end)));
} }
@@ -507,66 +447,18 @@ net_real_write(NET *net,const char *packet,size_t len)
/***************************************************************************** /*****************************************************************************
** Read something from server/clinet ** Read something from server/clinet
*****************************************************************************/ *****************************************************************************/
#ifdef MYSQL_SERVER
/*
Help function to clear the commuication buffer when we get a too
big packet
*/
static void my_net_skip_rest(NET *net, ulong remain, thr_alarm_t *alarmed,
ALARM *alarm_buff)
{
uint retry_count=0;
if (!thr_alarm_in_use(alarmed))
{
if (thr_alarm(alarmed,net->timeout,alarm_buff) ||
(!vio_is_blocking(net->vio) && vio_blocking(net->vio,TRUE, 0) < 0))
return; /* Can't setup, abort */
}
while (remain > 0)
{
ulong length;
if ((int) (length=vio_read(net->vio,(char*) net->buff,remain)) <= 0L)
{
my_bool interrupted = vio_should_retry(net->vio);
if (!thr_got_alarm(alarmed) && interrupted)
{ /* Probably in MIT threads */
if (retry_count++ < RETRY_COUNT)
continue;
}
return;
}
remain -=(ulong) length;
statistic_add(bytes_received,(ulong) length,&LOCK_bytes_received);
}
}
#endif /* MYSQL_SERVER */
static ulong static ulong
my_real_read(NET *net, size_t *complen) my_real_read(NET *net, size_t *complen)
{ {
uchar *pos; uchar *pos;
size_t length; size_t length;
uint i,retry_count=0; uint i;
ulong len=packet_error; ulong len=packet_error;
thr_alarm_t alarmed;
#if (!defined(_WIN32) && !defined(__EMX__) && !defined(OS2)) || defined(MYSQL_SERVER)
ALARM alarm_buff;
#endif
my_bool net_blocking=vio_is_blocking(net->vio);
size_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE : size_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
NET_HEADER_SIZE); NET_HEADER_SIZE);
*complen = 0; *complen = 0;
net->reading_or_writing=1; net->reading_or_writing=1;
thr_alarm_init(&alarmed);
#ifdef MYSQL_SERVER
if (net_blocking)
thr_alarm(&alarmed,net->timeout,&alarm_buff);
#endif /* MYSQL_SERVER */
pos = net->buff + net->where_b; /* net->packet -4 */ pos = net->buff + net->where_b; /* net->packet -4 */
for (i=0 ; i < 2 ; i++) for (i=0 ; i < 2 ; i++)
@@ -574,68 +466,8 @@ my_real_read(NET *net, size_t *complen)
while (remain > 0) while (remain > 0)
{ {
/* First read is done with non blocking mode */ /* First read is done with non blocking mode */
if ((long) (length=vio_read(net->vio,(char*) pos,remain)) <= 0L) if ((ssize_t) (length=ma_cio_cache_read(net->cio,(char*) pos,remain)) <= 0L)
{ {
my_bool interrupted = vio_should_retry(net->vio);
DBUG_PRINT("info",("vio_read returned %d, errno: %d",
length, vio_errno(net->vio)));
#if (!defined(_WIN32) && !defined(__EMX__) && !defined(OS2)) || defined(MYSQL_SERVER)
/*
We got an error that there was no data on the socket. We now set up
an alarm to not 'read forever', change the socket to non blocking
mode and try again
*/
if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed))
{
if (!thr_alarm(&alarmed,net->read_timeout,&alarm_buff)) /* Don't wait too long */
{
if (!vio_is_blocking(net->vio))
{
while (vio_blocking(net->vio,TRUE, 0) < 0)
{
if (vio_should_retry(net->vio) &&
retry_count++ < RETRY_COUNT)
continue;
DBUG_PRINT("error",
("fcntl returned error %d, aborting thread",
vio_errno(net->vio)));
#ifdef EXTRA_DEBUG
fprintf(stderr,
"%s: read: fcntl returned error %d, aborting thread\n",
my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */
len= packet_error;
net->error=2; /* Close socket */
#ifdef MYSQL_SERVER
net->last_errno=ER_NET_FCNTL_ERROR;
#endif
goto end;
}
}
retry_count=0;
continue;
}
}
#endif /* (!defined(_WIN32) && !defined(__EMX__)) || defined(MYSQL_SERVER) */
if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) &&
interrupted)
{ /* Probably in MIT threads */
if (retry_count++ < RETRY_COUNT)
continue;
#ifdef EXTRA_DEBUG
fprintf(stderr, "%s: read looped with error %d, aborting thread\n",
my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */
}
#if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER)
if (vio_should_retry(net->vio))
{
DBUG_PRINT("warning",("Interrupted read. Retrying..."));
continue;
}
#endif
DBUG_PRINT("error",("Couldn't read packet: remain: %d errno: %d length: %d alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
len= packet_error; len= packet_error;
net->error=2; /* Close socket */ net->error=2; /* Close socket */
goto end; goto end;
@@ -662,9 +494,6 @@ my_real_read(NET *net, size_t *complen)
#endif #endif
} }
len= packet_error; len= packet_error;
#ifdef MYSQL_SERVER
net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER;
#endif
goto end; goto end;
} }
net->compress_pkt_nr= ++net->pkt_nr; net->compress_pkt_nr= ++net->pkt_nr;
@@ -685,10 +514,6 @@ my_real_read(NET *net, size_t *complen)
{ {
if (net_realloc(net,helping)) if (net_realloc(net,helping))
{ {
#ifdef MYSQL_SERVER
if (i == 1)
my_net_skip_rest(net, len, &alarmed, &alarm_buff);
#endif
len= packet_error; /* Return error */ len= packet_error; /* Return error */
goto end; goto end;
} }
@@ -699,11 +524,6 @@ my_real_read(NET *net, size_t *complen)
} }
end: end:
if (thr_alarm_in_use(&alarmed))
{
thr_end_alarm(&alarmed);
vio_blocking(net->vio, net_blocking, 0);
}
net->reading_or_writing=0; net->reading_or_writing=0;
return(len); return(len);
} }

View File

@@ -1,713 +0,0 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA */
/*
Note that we can't have assertion on file descriptors; The reason for
this is that during mysql shutdown, another thread can close a file
we are working on. In this case we should just return read errors from
the file descriptior.
*/
#ifndef HAVE_VIO /* is Vio suppored by the Vio lib ? */
#include <my_global.h>
#include <errno.h>
#include <assert.h>
#include <violite.h>
#include <my_sys.h>
#include <my_net.h>
#include <m_string.h>
#ifdef HAVE_POLL
#include <sys/poll.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_OPENSSL
#include <ma_secure.h>
#endif
#ifdef _WIN32
#define socklen_t int
#pragma comment (lib, "ws2_32")
#endif
#if !defined(MSDOS) && !defined(_WIN32) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__) && !defined(__FreeBSD__)
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#if !defined(alpha_linux_port)
#include <netinet/tcp.h>
#endif
#endif
#if defined(__EMX__) || defined(OS2)
#define ioctlsocket ioctl
#endif /* defined(__EMX__) */
#if defined(MSDOS) || defined(_WIN32)
#define O_NONBLOCK 1 /* For emulation of fcntl() */
#endif
#ifndef EWOULDBLOCK
#define SOCKET_EWOULDBLOCK SOCKET_EAGAIN
#endif
#include <mysql_async.h>
#include <my_context.h>
#ifdef _WIN32
#define ma_get_error() WSAGetLastError()
#else
#define ma_get_error() errno
#endif
typedef void *vio_ptr;
typedef char *vio_cstring;
/*
* Helper to fill most of the Vio* with defaults.
*/
void vio_reset(Vio* vio, enum enum_vio_type type,
my_socket sd, HANDLE hPipe,
my_bool localhost)
{
uchar *save_cache= vio->cache;
int save_timeouts[2]= {vio->read_timeout, vio->write_timeout};
bzero((char*) vio, sizeof(*vio));
vio->type= type;
vio->sd= sd;
vio->hPipe= hPipe;
vio->localhost= localhost;
/* do not clear cache */
vio->cache= vio->cache_pos= save_cache;
vio->cache_size= 0;
vio->read_timeout= save_timeouts[0];
vio->write_timeout= save_timeouts[1];
}
void vio_timeout(Vio *vio, int type, uint timeval)
{
#ifdef _WIN32
uint timeout= timeval; /* milli secs */
#else
struct timeval timeout;
timeout.tv_sec= timeval;
timeout.tv_usec= (timeval % 1000) * 1000;
#endif
if (setsockopt(vio->sd, SOL_SOCKET, type,
#ifdef _WIN32
(const char *)&timeout,
#else
(const void *)&timeout,
#endif
sizeof(timeout)))
{
DBUG_PRINT("error", ("setsockopt failed. Errno: %d", errno));
}
}
void vio_read_timeout(Vio *vio, uint timeout)
{
vio->read_timeout= (timeout >= 0) ? timeout * 1000 : -1;
vio_timeout(vio, SO_RCVTIMEO, vio->read_timeout);
}
void vio_write_timeout(Vio *vio, uint timeout)
{
vio->write_timeout= (timeout >= 0) ? timeout * 1000 : -1;
vio_timeout(vio, SO_SNDTIMEO, vio->write_timeout);
}
/* Open the socket or TCP/IP connection and read the fnctl() status */
Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
{
Vio *vio;
DBUG_ENTER("vio_new");
DBUG_PRINT("enter", ("sd=%d", sd));
if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
{
vio_reset(vio, type, sd, 0, localhost);
sprintf(vio->desc,
(vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
vio->sd);
#if !defined(__WIN32) && !defined(__EMX__) && !defined(OS2)
#if !defined(NO_FCNTL_NONBLOCK)
vio->fcntl_mode = fcntl(sd, F_GETFL);
#elif defined(HAVE_SYS_IOCTL_H) /* hpux */
/* Non blocking sockets doesn't work good on HPUX 11.0 */
(void) ioctl(sd,FIOSNBIO,0);
#endif
#else /* !defined(_WIN32) && !defined(__EMX__) */
{
/* set to blocking mode by default */
ulong arg=0, r;
r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg/*, sizeof(arg)*/);
}
#endif
}
if (!(vio->cache= my_malloc(VIO_CACHE_SIZE, MYF(MY_WME))))
{
my_free(vio);
vio= NULL;
}
vio->cache_size= 0;
vio->cache_pos= vio->cache;
DBUG_RETURN(vio);
}
#ifdef _WIN32
Vio *vio_new_win32pipe(HANDLE hPipe)
{
Vio *vio;
DBUG_ENTER("vio_new_handle");
if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_ZEROFILL))))
{
vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE);
strmov(vio->desc, "named pipe");
}
DBUG_RETURN(vio);
}
#endif
void vio_delete(Vio * vio)
{
/* It must be safe to delete null pointers. */
/* This matches the semantics of C++'s delete operator. */
if (vio)
{
if (vio->type != VIO_CLOSED)
vio_close(vio);
my_free(vio->cache);
my_free(vio);
}
}
int vio_errno(Vio *vio __attribute__((unused)))
{
return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
}
int vio_wait_or_timeout(Vio *vio, my_bool is_read, int timeout)
{
int rc;
#ifndef _WIN32
struct pollfd p_fd;
#else
struct timeval tv= {0,0};
fd_set fds, exc_fds;
#endif
/* we don't support it via named pipes yet.
* maybe this could be handled via PeekNamedPipe somehow !? */
if (vio->type == VIO_TYPE_NAMEDPIPE)
return 1;
/*
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)
{
rc= my_io_wait_async(vio->async_context,
(is_read) ? VIO_IO_EVENT_READ : VIO_IO_EVENT_WRITE,
timeout);
return(rc);
}
else
{
#ifndef _WIN32
p_fd.fd= vio->sd;
p_fd.events= (is_read) ? POLLIN : POLLOUT;
do {
rc= poll(&p_fd, 1, timeout);
} while (rc == -1 || errno == EINTR);
if (rc == 0)
errno= ETIMEDOUT;
#else
FD_ZERO(&fds);
FD_ZERO(&exc_fds);
FD_SET(vio->sd, &fds);
FD_SET(vio->sd, &exc_fds);
if (timeout >= 0)
{
tv.tv_sec= timeout / 1000;
tv.tv_usec= (timeout % 1000) * 1000;
}
rc= select(0, (is_read) ? &fds : NULL,
(is_read) ? NULL : &fds,
&exc_fds,
(timeout >= 0) ? &tv : NULL);
if (rc == SOCKET_ERROR)
errno= WSAGetLastError();
if (rc == 0)
errno= ETIMEDOUT;
#endif
}
return rc;
}
size_t vio_real_read(Vio *vio, gptr buf, size_t size)
{
size_t r;
switch(vio->type) {
#ifdef HAVE_OPENSSL
case VIO_TYPE_SSL:
return my_ssl_read(vio, (char *)buf, size);
break;
#endif
#ifdef _WIN32
case VIO_TYPE_NAMEDPIPE:
{
DWORD length= 0;
if (!ReadFile(vio->hPipe, buf, (DWORD)size, &length, NULL))
return -1;
return length;
}
break;
#endif
default:
if (vio->async_context && vio->async_context->active)
r= my_recv_async(vio->async_context,
vio->sd,
buf, size, vio->read_timeout);
else
{
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);
}
#ifndef _WIN32
do {
r= read(vio->sd, buf, size);
} while (r == -1 && errno == EINTR);
while (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
&& vio->read_timeout > 0)
{
if (vio_wait_or_timeout(vio, TRUE, vio->write_timeout) < 1)
return 0;
do {
r= read(vio->sd, buf, size);
} while (r == -1 && errno == EINTR);
}
#else
{
WSABUF wsaData;
DWORD dwBytes = 0;
DWORD flags = 0;
wsaData.len= size;
wsaData.buf= buf;
if (WSARecv(vio->sd, &wsaData, 1, &dwBytes, &flags, NULL, NULL) == SOCKET_ERROR)
{
errno= WSAGetLastError();
return 0;
}
r= (size_t)dwBytes;
}
#endif
}
break;
}
return r;
}
size_t vio_read(Vio * vio, gptr buf, size_t size)
{
size_t r;
DBUG_ENTER("vio_read");
DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size));
if (!vio->cache)
DBUG_RETURN(vio_real_read(vio, buf, size));
if (vio->cache + vio->cache_size > vio->cache_pos)
{
r= MIN(size, vio->cache + vio->cache_size - vio->cache_pos);
memcpy(buf, vio->cache_pos, r);
vio->cache_pos+= r;
}
else if (size >= VIO_CACHE_MIN_SIZE)
{
r= vio_real_read(vio, buf, size);
}
else
{
r= vio_real_read(vio, vio->cache, VIO_CACHE_SIZE);
if (r > 0)
{
if (size < r)
{
vio->cache_size= r; /* might be < VIO_CACHE_SIZE */
vio->cache_pos= vio->cache + size;
r= size;
}
memcpy(buf, vio->cache, r);
}
}
#ifndef DBUG_OFF
if ((size_t)r == -1)
{
DBUG_PRINT("vio_error", ("Got error %d during read",socket_errno));
}
#endif /* DBUG_OFF */
DBUG_PRINT("exit", ("%u", (uint)r));
DBUG_RETURN(r);
}
/*
Return data from the beginning of the receive queue without removing
that data from the queue. A subsequent receive call will return the same data.
*/
my_bool vio_read_peek(Vio *vio, size_t *bytes)
{
#ifdef _WIN32
if (ioctlsocket(vio->sd, FIONREAD, (unsigned long*)bytes))
return TRUE;
#else
char buffer[1024];
ssize_t length;
vio_blocking(vio, 0, 0);
length= recv(vio->sd, &buffer, sizeof(buffer), MSG_PEEK);
if (length < 0)
return TRUE;
*bytes= length;
#endif
return FALSE;
}
size_t vio_write(Vio * vio, const gptr buf, size_t size)
{
size_t r;
DBUG_ENTER("vio_write");
DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size));
#ifdef HAVE_OPENSSL
if (vio->type == VIO_TYPE_SSL)
{
r= my_ssl_write(vio, (uchar *)buf, size);
DBUG_RETURN(r);
}
#endif
#ifdef _WIN32
if ( vio->type == VIO_TYPE_NAMEDPIPE)
{
DWORD length;
if (!WriteFile(vio->hPipe, (char*) buf, (DWORD)size, &length, NULL))
DBUG_RETURN(-1);
DBUG_RETURN(length);
}
#endif
if (vio->async_context && vio->async_context->active)
r= my_send_async(vio->async_context, vio->sd, buf, size,
vio->write_timeout);
else
{
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);
}
#ifndef _WIN32
do {
r= send(vio->sd, buf, size, vio->write_timeout ? MSG_DONTWAIT : MSG_WAITALL);
} while (r == -1 && errno == EINTR);
while (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
vio->write_timeout > 0)
{
if (vio_wait_or_timeout(vio, FALSE, vio->write_timeout) < 1)
return 0;
do {
r= send(vio->sd, buf, size, vio->write_timeout ? MSG_DONTWAIT : MSG_WAITALL);
} while (r == -1 && errno == EINTR);
}
#else
{
WSABUF wsaData;
DWORD dwBytes = 0;
wsaData.len= size;
wsaData.buf= (char *)buf;
if (WSASend(vio->sd, &wsaData, 1, &dwBytes, 0, NULL, NULL) == SOCKET_ERROR)
{
errno= WSAGetLastError();
DBUG_RETURN(0);
}
r= (size_t)dwBytes;
}
#endif
}
#ifndef DBUG_OFF
if ((size_t)r == -1)
{
DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno));
}
#endif /* DBUG_OFF */
DBUG_PRINT("exit", ("%u", (uint)r));
DBUG_RETURN(r);
}
int vio_blocking(Vio *vio, my_bool block, my_bool *previous_mode)
{
int *sd_flags= &vio->fcntl_mode;
int save_flags= vio->fcntl_mode;
my_bool tmp;
my_socket sock= vio->sd;
if (vio->type == VIO_TYPE_NAMEDPIPE)
return 0;
if (!previous_mode)
previous_mode= &tmp;
#ifdef _WIN32
*previous_mode= (*sd_flags & O_NONBLOCK) != 0;
*sd_flags = (block) ? *sd_flags & ~O_NONBLOCK : *sd_flags | O_NONBLOCK;
{
ulong arg= 1 - block;
if (ioctlsocket(sock, FIONBIO, (void *)&arg))
{
vio->fcntl_mode= save_flags;
return(WSAGetLastError());
}
}
#else
#if defined(O_NONBLOCK)
*previous_mode= (*sd_flags & O_NONBLOCK) != 0;
*sd_flags = (block) ? *sd_flags & ~O_NONBLOCK : *sd_flags | O_NONBLOCK;
#elif defined(O_NDELAY)
*previous_mode= (*sd_flags & O_NODELAY) != 0;
*sd_flags = (block) ? *sd_flags & ~O_NODELAY : *sd_flags | O_NODELAY;
#elif defined(FNDELAY)
*previous_mode= (*sd_flags & O_FNDELAY) != 0;
*sd_flags = (block) ? *sd_flags & ~O_FNDELAY : *sd_flags | O_FNDELAY;
#else
#error socket blocking is not supported on this platform
#endif
if (fcntl(sock, F_SETFL, *sd_flags) == -1)
{
vio->fcntl_mode= save_flags;
return errno;
}
#endif
return 0;
}
my_bool
vio_is_blocking(Vio * vio)
{
my_bool r;
DBUG_ENTER("vio_is_blocking");
r = !(vio->fcntl_mode & O_NONBLOCK);
DBUG_PRINT("exit", ("%d", (int) r));
DBUG_RETURN(r);
}
int vio_fastsend(Vio * vio __attribute__((unused)))
{
int r=0;
DBUG_ENTER("vio_fastsend");
#ifdef IPTOS_THROUGHPUT
{
#ifndef __EMX__
int tos = IPTOS_THROUGHPUT;
if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)))
#endif /* !__EMX__ */
{
int nodelay = 1;
if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay,
sizeof(nodelay))) {
DBUG_PRINT("warning",
("Couldn't set socket option for fast send"));
r= -1;
}
}
}
#endif /* IPTOS_THROUGHPUT */
DBUG_PRINT("exit", ("%d", r));
DBUG_RETURN(r);
}
int vio_keepalive(Vio* vio, my_bool set_keep_alive)
{
int r=0;
uint opt = 0;
DBUG_ENTER("vio_keepalive");
DBUG_PRINT("enter", ("sd=%d set_keep_alive=%d", vio->sd, (int)
set_keep_alive));
if (vio->type != VIO_TYPE_NAMEDPIPE)
{
if (set_keep_alive)
opt = 1;
r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
sizeof(opt));
}
DBUG_RETURN(r);
}
my_bool
vio_should_retry(Vio * vio __attribute__((unused)))
{
int en = socket_errno;
return en == SOCKET_EAGAIN || en == SOCKET_EINTR || en == SOCKET_EWOULDBLOCK;
}
int vio_close(Vio * vio)
{
int r;
DBUG_ENTER("vio_close");
#ifdef HAVE_OPENSSL
if (vio->type == VIO_TYPE_SSL)
{
r = my_ssl_close(vio);
}
#endif
#ifdef _WIN32
if (vio->type == VIO_TYPE_NAMEDPIPE)
{
r=CloseHandle(vio->hPipe);
}
else if (vio->type != VIO_CLOSED)
#endif /* _WIN32 */
{
r=0;
if (shutdown(vio->sd,2))
r= -1;
if (closesocket(vio->sd))
r= -1;
}
if (r)
{
DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno));
/* FIXME: error handling (not critical for MySQL) */
}
vio->type= VIO_CLOSED;
vio->sd= -1;
DBUG_RETURN(r);
}
const char *vio_description(Vio * vio)
{
return vio->desc;
}
enum enum_vio_type vio_type(Vio* vio)
{
return vio->type;
}
my_socket vio_fd(Vio* vio)
{
return vio->sd;
}
my_bool vio_peer_addr(Vio * vio, char *buf)
{
DBUG_ENTER("vio_peer_addr");
DBUG_PRINT("enter", ("sd=%d", vio->sd));
if (vio->localhost)
{
strmov(buf,"127.0.0.1");
}
else
{
socklen_t addrLen = sizeof(struct sockaddr);
if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)),
&addrLen) != 0)
{
DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno));
DBUG_RETURN(1);
}
my_inet_ntoa(vio->remote.sin_addr,buf);
}
DBUG_PRINT("exit", ("addr=%s", buf));
DBUG_RETURN(0);
}
void vio_in_addr(Vio *vio, struct in_addr *in)
{
DBUG_ENTER("vio_in_addr");
if (vio->localhost)
bzero((char*) in, sizeof(*in)); /* This should never be executed */
else
*in=vio->remote.sin_addr;
DBUG_VOID_RETURN;
}
/* Return 0 if there is data to be read */
/*
my_bool vio_poll_read(Vio *vio,uint timeout)
{
#ifndef HAVE_POLL
return 0;
#else
struct pollfd fds;
int res;
DBUG_ENTER("vio_poll");
fds.fd=vio->sd;
fds.events=POLLIN;
fds.revents=0;
if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
{
DBUG_RETURN(res < 0 ? 0 : 1);
}
DBUG_RETURN(fds.revents & POLLIN ? 0 : 1);
#endif
}
*/
#endif /* HAVE_VIO */

View File

@@ -94,6 +94,7 @@ mysql_declare_client_plugin(REMOTEIO)
"Georg Richter", "Georg Richter",
"Remote IO plugin", "Remote IO plugin",
{0,1,0}, {0,1,0},
"LGPL",
ma_rio_init, ma_rio_init,
ma_rio_deinit, ma_rio_deinit,
&ma_rio_methods &ma_rio_methods

View File

@@ -62,7 +62,7 @@ ENDIF()
FOREACH(API_TEST ${API_TESTS}) FOREACH(API_TEST ${API_TESTS})
ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c) ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c)
TARGET_LINK_LIBRARIES(${API_TEST} mytap mariadbclient ${EXTRA_LIBS}) TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb ${EXTRA_LIBS})
ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST}) ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST})
SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120) SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120)
ENDFOREACH(API_TEST) ENDFOREACH(API_TEST)

View File

@@ -177,35 +177,6 @@ static int test_bug31418(MYSQL *mysql)
return OK; return OK;
} }
/*
Altough mysql_create_db(), mysql_rm_db() are deprecated since 4.0 they
should not crash server and should not hang in case of errors.
Since those functions can't be seen in modern API (unless client library
was compiled with USE_OLD_FUNCTIONS define) we use simple_command() macro.
*/
static int test_bug6081(MYSQL *mysql)
{
int rc;
if (mysql_get_server_version(mysql) < 50100) {
diag("Test requires MySQL Server version 5.1 or above");
return SKIP;
}
rc= simple_command(mysql, MYSQL_COM_DROP_DB, (char*) schema,
(ulong)strlen(schema), 0U, NULL);
FAIL_IF(!rc, "Error expected");
rc= simple_command(mysql, MYSQL_COM_CREATE_DB, (char*) schema,
(ulong)strlen(schema), 0U, NULL);
FAIL_IF(!rc, "Error expected");
rc= mysql_select_db(mysql, schema);
check_mysql_rc(rc, mysql);
return OK;
}
/* Query processing */ /* Query processing */
static int test_debug_example(MYSQL *mysql) static int test_debug_example(MYSQL *mysql)
@@ -1051,8 +1022,8 @@ static int test_remote2(MYSQL *my)
struct my_tests_st my_tests[] = { struct my_tests_st my_tests[] = {
{"test_remote1", test_remote1, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_remote1", test_remote1, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_remote2", test_remote2, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_remote2", test_remote2, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_conc117", test_conc117, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc117", test_conc117, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_conc_114", test_conc_114, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc_114", test_conc_114, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_connect_attrs", test_connect_attrs, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_connect_attrs", test_connect_attrs, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_conc49", test_conc49, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc49", test_conc49, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
@@ -1061,7 +1032,6 @@ struct my_tests_st my_tests[] = {
{"test_debug_example", test_debug_example, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_debug_example", test_debug_example, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_bug29692", test_bug29692, TEST_CONNECTION_NEW, CLIENT_FOUND_ROWS, NULL, NULL}, {"test_bug29692", test_bug29692, TEST_CONNECTION_NEW, CLIENT_FOUND_ROWS, NULL, NULL},
{"test_bug31418", test_bug31418, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_bug31418", test_bug31418, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_bug6081", test_bug6081, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_frm_bug", test_frm_bug, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_frm_bug", test_frm_bug, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_wl4166_1", test_wl4166_1, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_wl4166_1", test_wl4166_1, TEST_CONNECTION_NEW, 0, NULL, NULL},
{"test_wl4166_2", test_wl4166_2, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_wl4166_2", test_wl4166_2, TEST_CONNECTION_NEW, 0, NULL, NULL},

View File

@@ -507,7 +507,9 @@ void run_tests(struct my_tests_st *test) {
return; /* default doesn't work anymore */ return; /* default doesn't work anymore */
} }
else if (mysql && !(test[i].connection & TEST_CONNECTION_DONT_CLOSE)) else if (mysql && !(test[i].connection & TEST_CONNECTION_DONT_CLOSE))
{
mysql_close(mysql); mysql_close(mysql);
}
} else { } else {
skip(1, "%s", test[i].skipmsg); skip(1, "%s", test[i].skipmsg);
} }