You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-07 02:42:49 +03:00
Initial aurora implementation
This commit is contained in:
@@ -21,6 +21,14 @@ IF(COMMAND CMAKE_POLICY)
|
|||||||
CMAKE_POLICY(SET CMP0003 NEW)
|
CMAKE_POLICY(SET CMP0003 NEW)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
#Allow access to non existing targets
|
||||||
|
IF(CMAKE_VERSION VERSION_GREATER "2.9.9")
|
||||||
|
CMAKE_POLICY(SET CMP0026 OLD)
|
||||||
|
CMAKE_POLICY(SET CMP0042 OLD)
|
||||||
|
CMAKE_POLICY(SET CMP0045 OLD)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2015 MariaDB Corporation Ab")
|
SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2015 MariaDB Corporation Ab")
|
||||||
|
|
||||||
### Options ###
|
### Options ###
|
||||||
@@ -149,6 +157,10 @@ IF(CMAKE_HAVE_PTHREAD_H)
|
|||||||
SET(CMAKE_REQUIRED_INCLUDES pthread.h)
|
SET(CMAKE_REQUIRED_INCLUDES pthread.h)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
IF(DBUG_OFF)
|
||||||
|
ADD_DEFINITIONS(-DDBUG_OFF=1)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
SET(HAVE_THREADS 1)
|
SET(HAVE_THREADS 1)
|
||||||
ADD_DEFINITIONS(-DHAVE_DLOPEN)
|
ADD_DEFINITIONS(-DHAVE_DLOPEN)
|
||||||
|
@@ -1,12 +1,16 @@
|
|||||||
# plugin configuration
|
# plugin configuration
|
||||||
|
|
||||||
MACRO(REGISTER_PLUGIN name source struct type target allow)
|
MACRO(REGISTER_PLUGIN name source struct type target allow)
|
||||||
|
SET(PLUGIN_TYPE ${${name}})
|
||||||
|
IF(NOT PLUGIN_TYPE STREQUAL "OFF")
|
||||||
|
SET(PLUGIN_TYPE ${type})
|
||||||
|
ENDIF()
|
||||||
IF(PLUGINS)
|
IF(PLUGINS)
|
||||||
LIST(REMOVE_ITEM PLUGINS ${name})
|
LIST(REMOVE_ITEM PLUGINS ${name})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
SET(${name}_PLUGIN_SOURCE ${source})
|
SET(${name}_PLUGIN_SOURCE ${source})
|
||||||
MARK_AS_ADVANCED(${name}_PLUGIN_SOURCE})
|
MARK_AS_ADVANCED(${name}_PLUGIN_SOURCE})
|
||||||
SET(${name}_PLUGIN_TYPE ${type})
|
SET(${name}_PLUGIN_TYPE ${PLUGIN_TYPE})
|
||||||
IF(NOT ${target} STREQUAL "")
|
IF(NOT ${target} STREQUAL "")
|
||||||
SET(${name}_PLUGIN_TARGET ${target})
|
SET(${name}_PLUGIN_TARGET ${target})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
@@ -41,6 +45,7 @@ REGISTER_PLUGIN("TRACE_EXAMPLE" "${CMAKE_SOURCE_DIR}/plugins/trace/trace_example
|
|||||||
|
|
||||||
#Connection
|
#Connection
|
||||||
REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "STATIC" "" 1)
|
REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "STATIC" "" 1)
|
||||||
|
REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "STATIC" "" 1)
|
||||||
|
|
||||||
# Allow registration of additional plugins
|
# Allow registration of additional plugins
|
||||||
IF(PLUGIN_CONF_FILE)
|
IF(PLUGIN_CONF_FILE)
|
||||||
@@ -50,7 +55,7 @@ ENDIF()
|
|||||||
|
|
||||||
SET(LIBMARIADB_SOURCES "")
|
SET(LIBMARIADB_SOURCES "")
|
||||||
|
|
||||||
MESSAGE(STATUS "Plugin configuration")
|
MESSAGE(STATUS "Plugin configuration:")
|
||||||
FOREACH(PLUGIN ${PLUGINS})
|
FOREACH(PLUGIN ${PLUGINS})
|
||||||
IF(WITH_${PLUGIN}_PLUGIN AND ${${PLUGIN}_PLUGIN_CHG} GREATER 0)
|
IF(WITH_${PLUGIN}_PLUGIN AND ${${PLUGIN}_PLUGIN_CHG} GREATER 0)
|
||||||
SET(${PLUGIN}_PLUGIN_TYPE ${WITH_${PLUGIN}_PLUGIN})
|
SET(${PLUGIN}_PLUGIN_TYPE ${WITH_${PLUGIN}_PLUGIN})
|
||||||
@@ -72,6 +77,6 @@ ENDIF()
|
|||||||
LIST(REMOVE_DUPLICATES LIBMARIADB_SOURCES)
|
LIST(REMOVE_DUPLICATES LIBMARIADB_SOURCES)
|
||||||
|
|
||||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/libmariadb/client_plugin.c.in
|
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/libmariadb/client_plugin.c.in
|
||||||
${CMAKE_BINARY_DIR}/libmariadb/client_plugin.c)
|
${CMAKE_BINARY_DIR}/libmariadb/client_plugin.c)
|
||||||
|
|
||||||
MARK_AS_ADVANCED(LIBMARIADB_SOURCES)
|
MARK_AS_ADVANCED(LIBMARIADB_SOURCES)
|
||||||
|
@@ -48,10 +48,12 @@ struct st_mysql_options_extension {
|
|||||||
double progress,
|
double progress,
|
||||||
const char *proc_info,
|
const char *proc_info,
|
||||||
unsigned int proc_info_length);
|
unsigned int proc_info_length);
|
||||||
MARIADB_DB_DRIVER *db_driver;
|
MARIADB_DB_DRIVER *db_driver;
|
||||||
char *ssl_fp; /* finger print of server certificate */
|
char *ssl_fp; /* finger print of server certificate */
|
||||||
char *ssl_fp_list; /* white list of finger prints */
|
char *ssl_fp_list; /* white list of finger prints */
|
||||||
char *ssl_pw; /* password for encrypted certificates */
|
char *ssl_pw; /* password for encrypted certificates */
|
||||||
|
char *url; /* for connection handler we need to save URL for reconnect */
|
||||||
|
my_bool read_only;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define OPT_HAS_EXT_VAL(a,key) \
|
#define OPT_HAS_EXT_VAL(a,key) \
|
||||||
|
@@ -482,8 +482,8 @@ const char * STDCALL mysql_get_client_info(void);
|
|||||||
unsigned long STDCALL mysql_get_client_version(void);
|
unsigned long STDCALL mysql_get_client_version(void);
|
||||||
my_bool STDCALL mariadb_connection(MYSQL *mysql);
|
my_bool STDCALL mariadb_connection(MYSQL *mysql);
|
||||||
const char * STDCALL mysql_get_server_name(MYSQL *mysql);
|
const char * STDCALL mysql_get_server_name(MYSQL *mysql);
|
||||||
CHARSET_INFO * STDCALL mysql_get_charset_by_name(const char *csname);
|
CHARSET_INFO * STDCALL mariadb_get_charset_by_name(const char *csname);
|
||||||
CHARSET_INFO * STDCALL mysql_get_charset_by_nr(unsigned int csnr);
|
CHARSET_INFO * STDCALL mariadb_get_charset_by_nr(unsigned int csnr);
|
||||||
size_t STDCALL mariadb_convert_string(const char *from, size_t *from_len, CHARSET_INFO *from_cs,
|
size_t STDCALL mariadb_convert_string(const char *from, size_t *from_len, CHARSET_INFO *from_cs,
|
||||||
char *to, size_t *to_len, CHARSET_INFO *to_cs, int *errorcode);
|
char *to, size_t *to_len, CHARSET_INFO *to_cs, int *errorcode);
|
||||||
int STDCALL mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...);
|
int STDCALL mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...);
|
||||||
@@ -493,6 +493,7 @@ my_socket STDCALL mysql_get_socket(const MYSQL *mysql);
|
|||||||
unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql);
|
unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql);
|
||||||
unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql);
|
unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql);
|
||||||
int STDCALL mariadb_get_connection_type(MYSQL *mysql);
|
int STDCALL mariadb_get_connection_type(MYSQL *mysql);
|
||||||
|
my_bool STDCALL mysql_reconnect(MYSQL *mysql);
|
||||||
|
|
||||||
/* Async API */
|
/* Async API */
|
||||||
int STDCALL mysql_close_start(MYSQL *sock);
|
int STDCALL mysql_close_start(MYSQL *sock);
|
||||||
@@ -628,6 +629,7 @@ struct st_mysql_methods {
|
|||||||
int (*db_stmt_fetch_to_bind)(MYSQL_STMT *stmt, unsigned char *row);
|
int (*db_stmt_fetch_to_bind)(MYSQL_STMT *stmt, unsigned char *row);
|
||||||
void (*db_stmt_flush_unbuffered)(MYSQL_STMT *stmt);
|
void (*db_stmt_flush_unbuffered)(MYSQL_STMT *stmt);
|
||||||
void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...);
|
void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...);
|
||||||
|
my_bool (*reconnect)(MYSQL *mysql);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* synonyms/aliases functions */
|
/* synonyms/aliases functions */
|
||||||
|
@@ -95,6 +95,7 @@ typedef struct st_ma_connection_plugin
|
|||||||
int (*options)(MYSQL *mysql, enum mysql_option, void *arg);
|
int (*options)(MYSQL *mysql, enum mysql_option, void *arg);
|
||||||
int (*set_connection)(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
int (*set_connection)(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||||
size_t length, my_bool skipp_check, void *opt_arg);
|
size_t length, my_bool skipp_check, void *opt_arg);
|
||||||
|
my_bool (*reconnect)(MYSQL *mysql);
|
||||||
} MARIADB_CONNECTION_PLUGIN;
|
} MARIADB_CONNECTION_PLUGIN;
|
||||||
|
|
||||||
#define MARIADB_DB_DRIVER(a) ((a)->ext_db)
|
#define MARIADB_DB_DRIVER(a) ((a)->ext_db)
|
||||||
|
@@ -230,6 +230,7 @@ typedef struct st_connection_handler
|
|||||||
{
|
{
|
||||||
struct st_ma_connection_plugin *plugin;
|
struct st_ma_connection_plugin *plugin;
|
||||||
void *data;
|
void *data;
|
||||||
|
my_bool active;
|
||||||
my_bool free_data;
|
my_bool free_data;
|
||||||
} MA_CONNECTION_HANDLER;
|
} MA_CONNECTION_HANDLER;
|
||||||
|
|
||||||
|
@@ -34,6 +34,8 @@ SET(EXPORT_SYMBOLS
|
|||||||
mariadb_dyncol_val_double
|
mariadb_dyncol_val_double
|
||||||
mariadb_dyncol_val_long
|
mariadb_dyncol_val_long
|
||||||
mariadb_dyncol_val_str
|
mariadb_dyncol_val_str
|
||||||
|
mariadb_get_charset_by_name
|
||||||
|
mariadb_get_charset_by_nr
|
||||||
mariadb_get_connection_type
|
mariadb_get_connection_type
|
||||||
mysql_affected_rows
|
mysql_affected_rows
|
||||||
mysql_autocommit
|
mysql_autocommit
|
||||||
@@ -124,6 +126,7 @@ SET(EXPORT_SYMBOLS
|
|||||||
mysql_query
|
mysql_query
|
||||||
mysql_query_cont
|
mysql_query_cont
|
||||||
mysql_query_start
|
mysql_query_start
|
||||||
|
mysql_reconnect
|
||||||
mysql_read_query_result
|
mysql_read_query_result
|
||||||
mysql_read_query_result_cont
|
mysql_read_query_result_cont
|
||||||
mysql_read_query_result_start
|
mysql_read_query_result_start
|
||||||
|
@@ -124,11 +124,14 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS;
|
|||||||
|
|
||||||
#define native_password_plugin_name "mysql_native_password"
|
#define native_password_plugin_name "mysql_native_password"
|
||||||
|
|
||||||
|
#define IS_CONNHDLR_ACTIVE(mysql)\
|
||||||
|
((mysql)->net.conn_hdlr && (mysql)->net.conn_hdlr->active)
|
||||||
|
|
||||||
static void end_server(MYSQL *mysql);
|
static void end_server(MYSQL *mysql);
|
||||||
static void mysql_close_memory(MYSQL *mysql);
|
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);
|
my_bool mysql_reconnect(MYSQL *mysql);
|
||||||
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();
|
||||||
@@ -354,13 +357,6 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
|||||||
|
|
||||||
DBUG_PRINT("info", ("server_command: %d packet_size: %u", command, length));
|
DBUG_PRINT("info", ("server_command: %d packet_size: %u", command, length));
|
||||||
|
|
||||||
if (mysql->net.conn_hdlr && mysql->net.conn_hdlr->data)
|
|
||||||
{
|
|
||||||
result= mysql->net.conn_hdlr->plugin->set_connection(mysql, command, arg, length, skipp_check, opt_arg);
|
|
||||||
if (result== -1)
|
|
||||||
DBUG_RETURN(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mysql->net.pvio == 0)
|
if (mysql->net.pvio == 0)
|
||||||
{ /* Do reconnect if possible */
|
{ /* Do reconnect if possible */
|
||||||
if (mysql_reconnect(mysql))
|
if (mysql_reconnect(mysql))
|
||||||
@@ -376,6 +372,14 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_CONNHDLR_ACTIVE(mysql))
|
||||||
|
{
|
||||||
|
result= mysql->net.conn_hdlr->plugin->set_connection(mysql, command, arg, length, skipp_check, opt_arg);
|
||||||
|
if (result== -1)
|
||||||
|
DBUG_RETURN(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CLEAR_CLIENT_ERROR(mysql);
|
CLEAR_CLIENT_ERROR(mysql);
|
||||||
|
|
||||||
mysql->info=0;
|
mysql->info=0;
|
||||||
@@ -384,13 +388,6 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
|||||||
if (!arg)
|
if (!arg)
|
||||||
arg="";
|
arg="";
|
||||||
|
|
||||||
/* check if connection kills itself */
|
|
||||||
if (command == COM_PROCESS_KILL)
|
|
||||||
{
|
|
||||||
unsigned long thread_id= uint4korr(arg);
|
|
||||||
if (thread_id == mysql->thread_id)
|
|
||||||
skipp_check= 1;
|
|
||||||
}
|
|
||||||
if (net_write_command(net,(uchar) command,arg,
|
if (net_write_command(net,(uchar) command,arg,
|
||||||
length ? length : (ulong) strlen(arg)))
|
length ? length : (ulong) strlen(arg)))
|
||||||
{
|
{
|
||||||
@@ -660,7 +657,7 @@ enum option_val
|
|||||||
|
|
||||||
#define OPT_SET_EXTENDED_VALUE_INT(OPTS, KEY, VAL) \
|
#define OPT_SET_EXTENDED_VALUE_INT(OPTS, KEY, VAL) \
|
||||||
CHECK_OPT_EXTENSION_SET(OPTS) \
|
CHECK_OPT_EXTENSION_SET(OPTS) \
|
||||||
+ (OPTS)->extension->KEY= (VAL)
|
(OPTS)->extension->KEY= (VAL)
|
||||||
|
|
||||||
|
|
||||||
static TYPELIB option_types={array_elements(default_options)-1,
|
static TYPELIB option_types={array_elements(default_options)-1,
|
||||||
@@ -1145,6 +1142,7 @@ mysql_init(MYSQL *mysql)
|
|||||||
bzero((char*) (mysql),sizeof(*(mysql)));
|
bzero((char*) (mysql),sizeof(*(mysql)));
|
||||||
mysql->options.connect_timeout=CONNECT_TIMEOUT;
|
mysql->options.connect_timeout=CONNECT_TIMEOUT;
|
||||||
mysql->charset= default_charset_info;
|
mysql->charset= default_charset_info;
|
||||||
|
mysql->methods= &MARIADB_DEFAULT_METHODS;
|
||||||
strmov(mysql->net.sqlstate, "00000");
|
strmov(mysql->net.sqlstate, "00000");
|
||||||
mysql->net.last_error[0]= mysql->net.last_errno= 0;
|
mysql->net.last_error[0]= mysql->net.last_errno= 0;
|
||||||
|
|
||||||
@@ -1291,9 +1289,38 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
|
|||||||
const char *passwd, const char *db,
|
const char *passwd, const char *db,
|
||||||
uint port, const char *unix_socket,unsigned long client_flag)
|
uint port, const char *unix_socket,unsigned long client_flag)
|
||||||
{
|
{
|
||||||
|
char *end;
|
||||||
|
|
||||||
if (!mysql->methods)
|
if (!mysql->methods)
|
||||||
mysql->methods= &MARIADB_DEFAULT_METHODS;
|
mysql->methods= &MARIADB_DEFAULT_METHODS;
|
||||||
|
|
||||||
|
if (host && (end= strstr(host, "://")))
|
||||||
|
{
|
||||||
|
MARIADB_CONNECTION_PLUGIN *plugin;
|
||||||
|
char plugin_name[64];
|
||||||
|
|
||||||
|
bzero(plugin_name, 64);
|
||||||
|
strncpy(plugin_name, host, MIN(end - host, 63));
|
||||||
|
end+= 3;
|
||||||
|
|
||||||
|
if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!(mysql->net.conn_hdlr= (MA_CONNECTION_HANDLER *)my_malloc(sizeof(MA_CONNECTION_HANDLER), MYF(MY_ZEROFILL))))
|
||||||
|
{
|
||||||
|
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* save URL for reconnect */
|
||||||
|
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, url, host);
|
||||||
|
|
||||||
|
mysql->net.conn_hdlr->plugin= plugin;
|
||||||
|
|
||||||
|
if (plugin && plugin->connect)
|
||||||
|
return plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag);
|
||||||
|
}
|
||||||
|
|
||||||
return mysql->methods->db_connect(mysql, host, user, passwd,
|
return mysql->methods->db_connect(mysql, host, user, passwd,
|
||||||
db, port, unix_socket, client_flag);
|
db, port, unix_socket, client_flag);
|
||||||
}
|
}
|
||||||
@@ -1320,32 +1347,6 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
|||||||
|
|
||||||
if (!mysql->methods)
|
if (!mysql->methods)
|
||||||
mysql->methods= &MARIADB_DEFAULT_METHODS;
|
mysql->methods= &MARIADB_DEFAULT_METHODS;
|
||||||
/* special case:
|
|
||||||
* If hostname contains "://", e.g. "repl://localhost", we need to process connection
|
|
||||||
* by connection plugin
|
|
||||||
*/
|
|
||||||
if (host && (end= strstr(host, "://")))
|
|
||||||
{
|
|
||||||
MARIADB_CONNECTION_PLUGIN *plugin;
|
|
||||||
char plugin_name[64];
|
|
||||||
|
|
||||||
bzero(plugin_name, 64);
|
|
||||||
strncpy(plugin_name, host, MIN(end - host, 63));
|
|
||||||
end+= 3;
|
|
||||||
if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN)))
|
|
||||||
DBUG_RETURN(NULL);
|
|
||||||
|
|
||||||
if (!(mysql->net.conn_hdlr= (MA_CONNECTION_HANDLER *)my_malloc(sizeof(MA_CONNECTION_HANDLER), MYF(MY_ZEROFILL))))
|
|
||||||
{
|
|
||||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
|
||||||
DBUG_RETURN(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
mysql->net.conn_hdlr->plugin= plugin;
|
|
||||||
|
|
||||||
if (plugin->connect)
|
|
||||||
return plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
ma_set_connect_attrs(mysql);
|
ma_set_connect_attrs(mysql);
|
||||||
|
|
||||||
@@ -1659,7 +1660,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
|||||||
mysql->reconnect= 0;
|
mysql->reconnect= 0;
|
||||||
|
|
||||||
for (;begin < end; begin++)
|
for (;begin < end; begin++)
|
||||||
{
|
{
|
||||||
if (mysql_real_query(mysql, *begin, (unsigned long)strlen(*begin)))
|
if (mysql_real_query(mysql, *begin, (unsigned long)strlen(*begin)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@@ -1715,14 +1716,22 @@ my_suspend_hook(my_bool suspend, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static my_bool mysql_reconnect(MYSQL *mysql)
|
my_bool STDCALL mysql_reconnect(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
MYSQL tmp_mysql;
|
MYSQL tmp_mysql;
|
||||||
struct my_hook_data hook_data;
|
struct my_hook_data hook_data;
|
||||||
struct mysql_async_context *ctxt= NULL;
|
struct mysql_async_context *ctxt= NULL;
|
||||||
|
LIST *li_stmt= mysql->stmts;
|
||||||
|
|
||||||
DBUG_ENTER("mysql_reconnect");
|
DBUG_ENTER("mysql_reconnect");
|
||||||
|
|
||||||
|
/* check if connection handler is active */
|
||||||
|
if (IS_CONNHDLR_ACTIVE(mysql))
|
||||||
|
{
|
||||||
|
if (mysql->net.conn_hdlr->plugin && mysql->net.conn_hdlr->plugin->connect)
|
||||||
|
DBUG_RETURN(mysql->net.conn_hdlr->plugin->reconnect(mysql));
|
||||||
|
}
|
||||||
|
|
||||||
if (!mysql->reconnect ||
|
if (!mysql->reconnect ||
|
||||||
(mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
|
(mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
|
||||||
{
|
{
|
||||||
@@ -1734,6 +1743,13 @@ static my_bool mysql_reconnect(MYSQL *mysql)
|
|||||||
|
|
||||||
mysql_init(&tmp_mysql);
|
mysql_init(&tmp_mysql);
|
||||||
tmp_mysql.options=mysql->options;
|
tmp_mysql.options=mysql->options;
|
||||||
|
if (mysql->net.conn_hdlr)
|
||||||
|
{
|
||||||
|
tmp_mysql.net.conn_hdlr= mysql->net.conn_hdlr;
|
||||||
|
mysql->net.conn_hdlr= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* don't reread options from configuration files */
|
/* don't reread options from configuration files */
|
||||||
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;
|
||||||
@@ -1762,6 +1778,17 @@ static my_bool mysql_reconnect(MYSQL *mysql)
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (;li_stmt;li_stmt= li_stmt->next)
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data;
|
||||||
|
|
||||||
|
if (stmt->state != MYSQL_STMT_INITTED)
|
||||||
|
{
|
||||||
|
stmt->state= MYSQL_STMT_INITTED;
|
||||||
|
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tmp_mysql.reconnect= mysql->reconnect;
|
tmp_mysql.reconnect= mysql->reconnect;
|
||||||
tmp_mysql.free_me= mysql->free_me;
|
tmp_mysql.free_me= mysql->free_me;
|
||||||
tmp_mysql.stmts= mysql->stmts;
|
tmp_mysql.stmts= mysql->stmts;
|
||||||
@@ -1923,6 +1950,7 @@ static void mysql_close_options(MYSQL *mysql)
|
|||||||
my_free(mysql->options.extension->ssl_fp);
|
my_free(mysql->options.extension->ssl_fp);
|
||||||
my_free(mysql->options.extension->ssl_fp_list);
|
my_free(mysql->options.extension->ssl_fp_list);
|
||||||
my_free(mysql->options.extension->ssl_pw);
|
my_free(mysql->options.extension->ssl_pw);
|
||||||
|
my_free(mysql->options.extension->url);
|
||||||
if(hash_inited(&mysql->options.extension->connect_attrs))
|
if(hash_inited(&mysql->options.extension->connect_attrs))
|
||||||
hash_free(&mysql->options.extension->connect_attrs);
|
hash_free(&mysql->options.extension->connect_attrs);
|
||||||
if ((ctxt = mysql->options.extension->async_context) != 0)
|
if ((ctxt = mysql->options.extension->async_context) != 0)
|
||||||
@@ -1985,7 +2013,8 @@ mysql_close(MYSQL *mysql)
|
|||||||
DBUG_ENTER("mysql_close");
|
DBUG_ENTER("mysql_close");
|
||||||
if (mysql) /* Some simple safety */
|
if (mysql) /* Some simple safety */
|
||||||
{
|
{
|
||||||
if (mysql->net.conn_hdlr && mysql->net.conn_hdlr->data)
|
|
||||||
|
if (IS_CONNHDLR_ACTIVE(mysql))
|
||||||
{
|
{
|
||||||
void *p= (void *)mysql->net.conn_hdlr;
|
void *p= (void *)mysql->net.conn_hdlr;
|
||||||
mysql->net.conn_hdlr->plugin->close(mysql);
|
mysql->net.conn_hdlr->plugin->close(mysql);
|
||||||
@@ -1998,6 +2027,7 @@ mysql_close(MYSQL *mysql)
|
|||||||
|
|
||||||
/* reset the connection in all active statements */
|
/* reset the connection in all active statements */
|
||||||
ma_invalidate_stmts(mysql, "mysql_close()");
|
ma_invalidate_stmts(mysql, "mysql_close()");
|
||||||
|
|
||||||
mysql_close_memory(mysql);
|
mysql_close_memory(mysql);
|
||||||
mysql_close_options(mysql);
|
mysql_close_options(mysql);
|
||||||
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
|
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
|
||||||
@@ -2048,7 +2078,9 @@ int mthd_my_read_query_result(MYSQL *mysql)
|
|||||||
DBUG_ENTER("mthd_my_read_query_result");
|
DBUG_ENTER("mthd_my_read_query_result");
|
||||||
|
|
||||||
if (!mysql || (length = net_safe_read(mysql)) == packet_error)
|
if (!mysql || (length = net_safe_read(mysql)) == packet_error)
|
||||||
|
{
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
free_old_query(mysql); /* Free old result */
|
free_old_query(mysql); /* Free old result */
|
||||||
get_info:
|
get_info:
|
||||||
pos=(uchar*) mysql->net.read_pos;
|
pos=(uchar*) mysql->net.read_pos;
|
||||||
@@ -2496,7 +2528,6 @@ mysql_stat(MYSQL *mysql)
|
|||||||
DBUG_RETURN((char*) mysql->net.read_pos);
|
DBUG_RETURN((char*) mysql->net.read_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int STDCALL
|
int STDCALL
|
||||||
mysql_ping(MYSQL *mysql)
|
mysql_ping(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
@@ -2510,7 +2541,6 @@ mysql_ping(MYSQL *mysql)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char * STDCALL
|
char * STDCALL
|
||||||
mysql_get_server_info(MYSQL *mysql)
|
mysql_get_server_info(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
@@ -2878,10 +2908,8 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
|
|||||||
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_pw, (char *)arg1);
|
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_pw, (char *)arg1);
|
||||||
break;
|
break;
|
||||||
case MARIADB_OPT_CONNECTION_READ_ONLY:
|
case MARIADB_OPT_CONNECTION_READ_ONLY:
|
||||||
if (mysql->net.conn_hdlr)
|
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, read_only, *(my_bool *)arg1);
|
||||||
DBUG_RETURN(mysql->net.conn_hdlr->plugin->options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, arg1));
|
break;
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
default:
|
default:
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
@@ -3278,6 +3306,15 @@ int STDCALL mariadb_get_connection_type(MYSQL *mysql)
|
|||||||
return (int)mysql->net.pvio->type;
|
return (int)mysql->net.pvio->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHARSET_INFO * STDCALL mariadb_get_charset_by_name(const char *csname)
|
||||||
|
{
|
||||||
|
return (CHARSET_INFO *)mysql_find_charset_name(csname);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARSET_INFO * STDCALL mariadb_get_charset_by_nr(unsigned int csnr)
|
||||||
|
{
|
||||||
|
return (CHARSET_INFO *)mysql_find_charset_nr(csnr);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Default methods for a connection. These methods are
|
* Default methods for a connection. These methods are
|
||||||
* stored in mysql->methods and can be overwritten by
|
* stored in mysql->methods and can be overwritten by
|
||||||
@@ -3315,5 +3352,9 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS = {
|
|||||||
/* store values in bind buffer */
|
/* store values in bind buffer */
|
||||||
mthd_stmt_fetch_to_bind,
|
mthd_stmt_fetch_to_bind,
|
||||||
/* skip unbuffered stmt result */
|
/* skip unbuffered stmt result */
|
||||||
mthd_stmt_flush_unbuffered
|
mthd_stmt_flush_unbuffered,
|
||||||
|
/* set error */
|
||||||
|
my_set_error,
|
||||||
|
/* reconnect */
|
||||||
|
mysql_reconnect
|
||||||
};
|
};
|
||||||
|
@@ -416,7 +416,6 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("store_param");
|
DBUG_ENTER("store_param");
|
||||||
DBUG_PRINT("info", ("column: %d type: %d", column, stmt->params[column].buffer_type));
|
DBUG_PRINT("info", ("column: %d type: %d", column, stmt->params[column].buffer_type));
|
||||||
printf("type: %d\n", column, stmt->params[column].buffer_type);
|
|
||||||
switch (stmt->params[column].buffer_type) {
|
switch (stmt->params[column].buffer_type) {
|
||||||
case MYSQL_TYPE_TINY:
|
case MYSQL_TYPE_TINY:
|
||||||
int1store(*p, *(uchar *)stmt->params[column].buffer);
|
int1store(*p, *(uchar *)stmt->params[column].buffer);
|
||||||
|
@@ -182,7 +182,9 @@ static my_bool net_realloc(NET *net, size_t length)
|
|||||||
/* Remove unwanted characters from connection */
|
/* Remove unwanted characters from connection */
|
||||||
void net_clear(NET *net)
|
void net_clear(NET *net)
|
||||||
{
|
{
|
||||||
|
size_t len;
|
||||||
DBUG_ENTER("net_clear");
|
DBUG_ENTER("net_clear");
|
||||||
|
ma_pvio_has_data(net->pvio, &len);
|
||||||
net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */
|
net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */
|
||||||
net->write_pos=net->buff;
|
net->write_pos=net->buff;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@@ -193,6 +195,7 @@ int net_flush(NET *net)
|
|||||||
{
|
{
|
||||||
int error=0;
|
int error=0;
|
||||||
DBUG_ENTER("net_flush");
|
DBUG_ENTER("net_flush");
|
||||||
|
|
||||||
if (net->buff != net->write_pos)
|
if (net->buff != net->write_pos)
|
||||||
{
|
{
|
||||||
error=net_real_write(net,(char*) net->buff,
|
error=net_real_write(net,(char*) net->buff,
|
||||||
|
@@ -13,10 +13,24 @@ IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC")
|
|||||||
"FILE_DESCRIPTION:Connection plugin for master/slave environment")
|
"FILE_DESCRIPTION:Connection plugin for master/slave environment")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ADD_DEFINITIONS(-DHAVE_REPLICATION_DYNAMIC=1)
|
ADD_DEFINITIONS(-DHAVE_REPLICATION_DYNAMIC=1)
|
||||||
ADD_LIBRARY(replication SHARED replication.c ${EXPORT_FILE})
|
ADD_LIBRARY(replication SHARED ${replication_RC} replication.c ${EXPORT_FILE})
|
||||||
SET(INSTALL_LIBS replication)
|
SET(INSTALL_LIBS replication)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC")
|
||||||
|
IF(WIN32)
|
||||||
|
SET_VERSION_INFO("TARGET:aurora"
|
||||||
|
"FILE_TYPE:VFT_DLL"
|
||||||
|
"SOURCE_FILE:plugins/connection/aurora.c"
|
||||||
|
"ORIGINAL_FILE_NAME:aurora.dll"
|
||||||
|
"FILE_DESCRIPTION:Connection plugin for Amazon AWS Aurora")
|
||||||
|
ENDIF()
|
||||||
|
ADD_DEFINITIONS(-DHAVE_AURORA_DYNAMIC=1)
|
||||||
|
ADD_LIBRARY(aurora SHARED ${aurora_RC} aurora.c ${EXPORT_FILE})
|
||||||
|
SET(INSTALL_LIBS ${INSTALL_LIBS} aurora)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
IF(INSTALL_LIBS)
|
IF(INSTALL_LIBS)
|
||||||
INSTALL(TARGETS
|
INSTALL(TARGETS
|
||||||
${INSTALL_LIBS}
|
${INSTALL_LIBS}
|
||||||
|
820
plugins/connection/aurora.c
Normal file
820
plugins/connection/aurora.c
Normal file
@@ -0,0 +1,820 @@
|
|||||||
|
/************************************************************************************
|
||||||
|
Copyright (C) 2015 MariaDB Corporation 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 see <http://www.gnu.org/licenses>
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||||
|
|
||||||
|
Part of this code includes code from the PHP project which
|
||||||
|
is freely available from http://www.php.net
|
||||||
|
*************************************************************************************/
|
||||||
|
|
||||||
|
/* MariaDB Connection plugin for Aurora failover */
|
||||||
|
|
||||||
|
#include <my_global.h>
|
||||||
|
#include <my_sys.h>
|
||||||
|
#include <errmsg.h>
|
||||||
|
#include <ma_common.h>
|
||||||
|
#include <mysql.h>
|
||||||
|
#include <mysql/client_plugin.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <m_string.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* function prototypes */
|
||||||
|
int aurora_init(char *errormsg, size_t errormsg_size,
|
||||||
|
int unused __attribute__((unused)),
|
||||||
|
va_list unused1 __attribute__((unused)));
|
||||||
|
|
||||||
|
MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
|
||||||
|
const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag);
|
||||||
|
void aurora_close(MYSQL *mysql);
|
||||||
|
int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||||
|
size_t length, my_bool skipp_check, void *opt_arg);
|
||||||
|
int aurora_set_options(MYSQL *msql, enum mysql_option option, void *arg);
|
||||||
|
my_bool aurora_reconnect(MYSQL *mysql);
|
||||||
|
|
||||||
|
#define AURORA_MAX_INSTANCES 16
|
||||||
|
|
||||||
|
#define AURORA_UNKNOWN -1
|
||||||
|
#define AURORA_PRIMARY 0
|
||||||
|
#define AURORA_REPLICA 1
|
||||||
|
#define AURORA_UNAVAILABLE 2
|
||||||
|
|
||||||
|
#define ENABLE_AURORA(mysql)\
|
||||||
|
(mysql)->net.conn_hdlr->active= 1;
|
||||||
|
#define DISABLE_AURORA(mysql)\
|
||||||
|
(mysql)->net.conn_hdlr->active= 0;
|
||||||
|
|
||||||
|
#ifndef HAVE_REPLICATION_DYNAMIC
|
||||||
|
MARIADB_CONNECTION_PLUGIN connection_aurora_plugin =
|
||||||
|
#else
|
||||||
|
MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ =
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
MARIADB_CLIENT_CONNECTION_PLUGIN,
|
||||||
|
MARIADB_CLIENT_CONNECTION_PLUGIN_INTERFACE_VERSION,
|
||||||
|
"aurora",
|
||||||
|
"Georg Richter",
|
||||||
|
"MariaDB connection plugin for Aurora failover",
|
||||||
|
{1, 0, 0},
|
||||||
|
"LGPL",
|
||||||
|
aurora_init,
|
||||||
|
NULL,
|
||||||
|
aurora_connect,
|
||||||
|
aurora_close,
|
||||||
|
aurora_set_options,
|
||||||
|
aurora_command,
|
||||||
|
aurora_reconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct st_aurora_instance {
|
||||||
|
char *host;
|
||||||
|
int port;
|
||||||
|
time_t blacklisted;
|
||||||
|
int type;
|
||||||
|
} AURORA_INSTANCE;
|
||||||
|
|
||||||
|
typedef struct st_conn_aurora {
|
||||||
|
MARIADB_PVIO *pvio[2];
|
||||||
|
MYSQL *mysql[2];
|
||||||
|
my_bool active[2];
|
||||||
|
char *url;
|
||||||
|
unsigned int num_instances;
|
||||||
|
AURORA_INSTANCE instance[AURORA_MAX_INSTANCES];
|
||||||
|
char *username, *password, *database;
|
||||||
|
unsigned int port;
|
||||||
|
unsigned long client_flag;
|
||||||
|
unsigned int last_instance_type; /* Primary or Replica */
|
||||||
|
char primary_id[100];
|
||||||
|
} AURORA;
|
||||||
|
|
||||||
|
#define AURORA_BLACKLIST_TIMEOUT 150
|
||||||
|
|
||||||
|
#define AURORA_IS_BLACKLISTED(a, i) \
|
||||||
|
((time(NULL) - (a)->instance[(i)].blacklisted) < AURORA_BLACKLIST_TIMEOUT)
|
||||||
|
|
||||||
|
/* {{{ my_bool aurora_swutch_connection */
|
||||||
|
my_bool aurora_switch_connection(MYSQL *mysql, AURORA *aurora, int type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case AURORA_REPLICA:
|
||||||
|
if (aurora->mysql[AURORA_REPLICA])
|
||||||
|
{
|
||||||
|
mysql->net.pvio= aurora->pvio[AURORA_REPLICA];
|
||||||
|
aurora->pvio[AURORA_REPLICA]->mysql= mysql;
|
||||||
|
mysql->thread_id= aurora->mysql[AURORA_REPLICA]->thread_id;
|
||||||
|
aurora->last_instance_type= AURORA_REPLICA;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AURORA_PRIMARY:
|
||||||
|
if (aurora->mysql[AURORA_PRIMARY])
|
||||||
|
{
|
||||||
|
if (aurora->mysql[AURORA_REPLICA])
|
||||||
|
aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA];
|
||||||
|
mysql->net.pvio= aurora->pvio[AURORA_PRIMARY];
|
||||||
|
mysql->thread_id= aurora->mysql[AURORA_PRIMARY]->thread_id;
|
||||||
|
aurora->last_instance_type= AURORA_PRIMARY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ int aurora_init
|
||||||
|
*
|
||||||
|
* plugin initialization function
|
||||||
|
*/
|
||||||
|
int aurora_init(char *errormsg, size_t errormsg_size,
|
||||||
|
int unused __attribute__((unused)),
|
||||||
|
va_list unused1 __attribute__((unused)))
|
||||||
|
{
|
||||||
|
/* random generator initialization */
|
||||||
|
#ifndef WIN32
|
||||||
|
struct timeval tp;
|
||||||
|
gettimeofday(&tp,NULL);
|
||||||
|
srand(tp.tv_usec / 1000 + tp.tv_sec * 1000);
|
||||||
|
#else
|
||||||
|
srand(GetTickCount());
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ void aurora_close_memory */
|
||||||
|
void aurora_close_memory(AURORA *aurora)
|
||||||
|
{
|
||||||
|
free(aurora->url);
|
||||||
|
free(aurora->username);
|
||||||
|
free(aurora->password);
|
||||||
|
free(aurora->database);
|
||||||
|
free(aurora);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ my_bool aurora_parse_url
|
||||||
|
*
|
||||||
|
* parse url
|
||||||
|
* Url has the following format:
|
||||||
|
* instance1:port, instance2:port, .., instanceN:port
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
my_bool aurora_parse_url(const char *url, AURORA *aurora)
|
||||||
|
{
|
||||||
|
char *p, *c;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!url || url[0] == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
bzero(aurora->instance, (AURORA_MAX_INSTANCES + 1) * sizeof(char *));
|
||||||
|
bzero(&aurora->port, (AURORA_MAX_INSTANCES + 1) * sizeof(int));
|
||||||
|
|
||||||
|
if (aurora->url)
|
||||||
|
free(aurora->url);
|
||||||
|
|
||||||
|
aurora->url= strdup(url);
|
||||||
|
c= aurora->url;
|
||||||
|
|
||||||
|
/* get instances */
|
||||||
|
while((c))
|
||||||
|
{
|
||||||
|
if (p= strchr(c, ','))
|
||||||
|
{
|
||||||
|
*p= '\0';
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
if (*c)
|
||||||
|
{
|
||||||
|
aurora->instance[aurora->num_instances].host= c;
|
||||||
|
aurora->num_instances++;
|
||||||
|
}
|
||||||
|
c= p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aurora->num_instances)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* check ports */
|
||||||
|
for (i=0; i < aurora->num_instances && aurora->instance[i].host; i++)
|
||||||
|
{
|
||||||
|
aurora->instance[i].type= AURORA_UNKNOWN;
|
||||||
|
|
||||||
|
/* We need to be aware of IPv6 addresses: According to RFC3986 sect. 3.2.2
|
||||||
|
hostnames have to be enclosed in square brackets if a port is given */
|
||||||
|
if (aurora->instance[i].host[0]== '[' &&
|
||||||
|
strchr(aurora->instance[i].host, ':') &&
|
||||||
|
(p= strchr(aurora->instance[i].host,']')))
|
||||||
|
{
|
||||||
|
/* ignore first square bracket */
|
||||||
|
memmove(aurora->instance[i].host,
|
||||||
|
aurora->instance[i].host+1,
|
||||||
|
strlen(aurora->instance[i].host) - 1);
|
||||||
|
p= strchr(aurora->instance[i].host,']');
|
||||||
|
*p= 0;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p= aurora->instance[i].host;
|
||||||
|
if (p && (p= strchr(p, ':')))
|
||||||
|
{
|
||||||
|
*p= '\0';
|
||||||
|
p++;
|
||||||
|
aurora->instance[i].port= atoi(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ int aurora_get_instance_type
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
*
|
||||||
|
* AURORA_PRIMARY
|
||||||
|
* AURORA_REPLICA
|
||||||
|
* -1 on error
|
||||||
|
*/
|
||||||
|
int aurora_get_instance_type(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
char *query= "select variable_value from information_schema.global_variables where variable_name='INNODB_READ_ONLY' AND variable_value='OFF'";
|
||||||
|
|
||||||
|
if (!mysql_query(mysql, query))
|
||||||
|
{
|
||||||
|
MYSQL_RES *res= mysql_store_result(mysql);
|
||||||
|
rc= mysql_num_rows(res) ? AURORA_PRIMARY : AURORA_REPLICA;
|
||||||
|
mysql_free_result(res);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ my_bool aurora_get_primary_id
|
||||||
|
*
|
||||||
|
* try to find primary instance from slave by retrieving
|
||||||
|
* primary_id information_schema.replica_host_status information
|
||||||
|
*
|
||||||
|
* If the function succeeds, primary_id will be copied into
|
||||||
|
* aurora->primary_id
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 1 on success
|
||||||
|
* 0 if an error occured or primary_id couldn't be
|
||||||
|
* found
|
||||||
|
*/
|
||||||
|
my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora)
|
||||||
|
{
|
||||||
|
my_bool rc= 0;
|
||||||
|
|
||||||
|
if (!mysql_query(mysql, "select server_id from information_schema.replica_host_status "
|
||||||
|
"where session_id = 'MASTER_SESSION_ID'"))
|
||||||
|
{
|
||||||
|
MYSQL_RES *res;
|
||||||
|
MYSQL_ROW row;
|
||||||
|
|
||||||
|
if ((res= mysql_store_result(mysql)))
|
||||||
|
{
|
||||||
|
if ((row= mysql_fetch_row(res)))
|
||||||
|
{
|
||||||
|
if (row[0])
|
||||||
|
{
|
||||||
|
strcpy(aurora->primary_id, row[0]);
|
||||||
|
rc= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mysql_free_result(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ unsigned int aurora_get_valid_instances
|
||||||
|
*
|
||||||
|
* returns the number of instances which are
|
||||||
|
* not blacklisted or don't have a type assigned.
|
||||||
|
*/
|
||||||
|
static unsigned int aurora_get_valid_instances(AURORA *aurora, AURORA_INSTANCE **instances)
|
||||||
|
{
|
||||||
|
int i, valid_instances= 0;
|
||||||
|
|
||||||
|
memset(instances, 0, sizeof(AURORA_INSTANCE *) * AURORA_MAX_INSTANCES);
|
||||||
|
|
||||||
|
for (i=0; i < aurora->num_instances; i++)
|
||||||
|
{
|
||||||
|
if (aurora->instance[i].type != AURORA_UNAVAILABLE)
|
||||||
|
{
|
||||||
|
if (aurora->instance[i].type == AURORA_PRIMARY && aurora->active[AURORA_PRIMARY])
|
||||||
|
continue;
|
||||||
|
instances[valid_instances]= &aurora->instance[i];
|
||||||
|
valid_instances++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return valid_instances;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ void aurora_refresh_blacklist() */
|
||||||
|
void aurora_refresh_blacklist(AURORA *aurora)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; i < aurora->num_instances; i++)
|
||||||
|
{
|
||||||
|
if (aurora->instance[i].blacklisted &&
|
||||||
|
!(AURORA_IS_BLACKLISTED(aurora, i)))
|
||||||
|
{
|
||||||
|
aurora->instance[i].blacklisted= 0;
|
||||||
|
aurora->instance[i].type= AURORA_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ MYSQL *aurora_connect_instance() */
|
||||||
|
MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL *mysql)
|
||||||
|
{
|
||||||
|
if (!mysql->methods->db_connect(mysql,
|
||||||
|
instance->host,
|
||||||
|
aurora->username,
|
||||||
|
aurora->password,
|
||||||
|
aurora->database,
|
||||||
|
instance->port ? instance->port : aurora->port,
|
||||||
|
NULL,
|
||||||
|
aurora->client_flag))
|
||||||
|
{
|
||||||
|
/* connection not available */
|
||||||
|
instance->blacklisted= time(NULL);
|
||||||
|
instance->type= AURORA_UNAVAILABLE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if we are slave or master */
|
||||||
|
switch (aurora_get_instance_type(mysql))
|
||||||
|
{
|
||||||
|
case AURORA_PRIMARY:
|
||||||
|
instance->type= AURORA_PRIMARY;
|
||||||
|
return mysql;
|
||||||
|
break;
|
||||||
|
case AURORA_REPLICA:
|
||||||
|
instance->type= AURORA_REPLICA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
instance->type= AURORA_UNAVAILABLE;
|
||||||
|
instance->blacklisted= time(NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!aurora->primary_id[0])
|
||||||
|
aurora_get_primary_id(mysql, aurora);
|
||||||
|
return mysql;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ void aurora_copy_mysql() */
|
||||||
|
void aurora_copy_mysql(MYSQL *from, MYSQL *to)
|
||||||
|
{
|
||||||
|
LIST *li_stmt= to->stmts;
|
||||||
|
|
||||||
|
for (;li_stmt;li_stmt= li_stmt->next)
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data;
|
||||||
|
|
||||||
|
if (stmt->state != MYSQL_STMT_INITTED)
|
||||||
|
{
|
||||||
|
stmt->state= MYSQL_STMT_INITTED;
|
||||||
|
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from->free_me= to->free_me;
|
||||||
|
from->reconnect= to->reconnect;
|
||||||
|
from->net.conn_hdlr= to->net.conn_hdlr;
|
||||||
|
from->stmts= to->stmts;
|
||||||
|
to->stmts= NULL;
|
||||||
|
|
||||||
|
memset(&to->options, 0, sizeof(to->options));
|
||||||
|
to->free_me= 0;
|
||||||
|
to->net.conn_hdlr= 0;
|
||||||
|
mysql_close(to);
|
||||||
|
*to= *from;
|
||||||
|
to->net.pvio= from->net.pvio;
|
||||||
|
to->net.pvio->mysql= to;
|
||||||
|
from->net.pvio= NULL;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ my_bool aurora_find_replica() */
|
||||||
|
my_bool aurora_find_replica(AURORA *aurora)
|
||||||
|
{
|
||||||
|
int valid_instances;
|
||||||
|
my_bool replica_found= 0;
|
||||||
|
AURORA_INSTANCE *instance[AURORA_MAX_INSTANCES];
|
||||||
|
MYSQL mysql;
|
||||||
|
// struct st_dynamic_array *init_command= aurora->mysql[AURORA_PRIMARY]->options.init_command;
|
||||||
|
|
||||||
|
if (aurora->num_instances < 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mysql_init(&mysql);
|
||||||
|
mysql.options= aurora->mysql[AURORA_PRIMARY]->options;
|
||||||
|
|
||||||
|
/* don't execute init_command on slave */
|
||||||
|
mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr;
|
||||||
|
|
||||||
|
valid_instances= aurora_get_valid_instances(aurora, instance);
|
||||||
|
|
||||||
|
while (valid_instances && !replica_found)
|
||||||
|
{
|
||||||
|
int random_pick= rand() % valid_instances;
|
||||||
|
if ((aurora_connect_instance(aurora, instance[random_pick], &mysql)))
|
||||||
|
{
|
||||||
|
switch (instance[random_pick]->type) {
|
||||||
|
case AURORA_REPLICA:
|
||||||
|
if (!aurora->mysql[AURORA_REPLICA])
|
||||||
|
{
|
||||||
|
aurora->mysql[AURORA_REPLICA]= mysql_init(NULL);
|
||||||
|
}
|
||||||
|
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_REPLICA]);
|
||||||
|
aurora->active[AURORA_REPLICA]= 1;
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case AURORA_PRIMARY:
|
||||||
|
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]);
|
||||||
|
aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio;
|
||||||
|
aurora->active[AURORA_PRIMARY]= 1;
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mysql_close(&mysql);
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valid_instances= aurora_get_valid_instances(aurora, instance);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ AURORA_INSTANCE aurora_get_primary_id_instance() */
|
||||||
|
AURORA_INSTANCE *aurora_get_primary_id_instance(AURORA *aurora)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!aurora->primary_id[0])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i=0; i < aurora->num_instances; i++)
|
||||||
|
{
|
||||||
|
if (!strncmp(aurora->instance[i].host, aurora->primary_id, strlen(aurora->primary_id)))
|
||||||
|
return &aurora->instance[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ my_bool aurora_find_primary() */
|
||||||
|
my_bool aurora_find_primary(AURORA *aurora)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
AURORA_INSTANCE *instance= NULL;
|
||||||
|
MYSQL mysql;
|
||||||
|
my_bool check_primary= 1;
|
||||||
|
|
||||||
|
if (!aurora->num_instances)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mysql_init(&mysql);
|
||||||
|
mysql.options= aurora->mysql[AURORA_PRIMARY]->options;
|
||||||
|
mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr;
|
||||||
|
|
||||||
|
for (i=0; i < aurora->num_instances; i++)
|
||||||
|
{
|
||||||
|
if (check_primary && aurora->primary_id[0])
|
||||||
|
{
|
||||||
|
if ((instance= aurora_get_primary_id_instance(aurora)) &&
|
||||||
|
aurora_connect_instance(aurora, instance, &mysql) &&
|
||||||
|
instance->type == AURORA_PRIMARY)
|
||||||
|
{
|
||||||
|
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]);
|
||||||
|
aurora->active[AURORA_PRIMARY]= 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* primary id connect failed, don't try again */
|
||||||
|
aurora->primary_id[0]= 0;
|
||||||
|
check_primary= 0;
|
||||||
|
}
|
||||||
|
if (aurora->instance[i].type != AURORA_UNAVAILABLE)
|
||||||
|
{
|
||||||
|
if (aurora_connect_instance(aurora, &aurora->instance[i], &mysql)
|
||||||
|
&& aurora->instance[i].type == AURORA_PRIMARY)
|
||||||
|
{
|
||||||
|
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]);
|
||||||
|
aurora->active[AURORA_PRIMARY]= 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ void aurora_close_replica() */
|
||||||
|
void aurora_close_replica(MYSQL *mysql, AURORA *aurora)
|
||||||
|
{
|
||||||
|
if (aurora->mysql[AURORA_REPLICA])
|
||||||
|
{
|
||||||
|
aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA];
|
||||||
|
aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0;
|
||||||
|
mysql_close(aurora->mysql[AURORA_REPLICA]);
|
||||||
|
aurora->pvio[AURORA_REPLICA]= 0;
|
||||||
|
aurora->mysql[AURORA_REPLICA]= NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ MYSQL *aurora_connect */
|
||||||
|
MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
|
||||||
|
const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag)
|
||||||
|
{
|
||||||
|
AURORA *aurora= NULL;
|
||||||
|
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
|
||||||
|
my_bool is_reconnect= 0;
|
||||||
|
|
||||||
|
if ((aurora= (AURORA *)hdlr->data))
|
||||||
|
{
|
||||||
|
aurora_refresh_blacklist(aurora);
|
||||||
|
if (aurora->mysql[aurora->last_instance_type]->net.pvio)
|
||||||
|
{
|
||||||
|
SET_CLIENT_ERROR(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
is_reconnect= 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(aurora= (AURORA *)my_malloc(sizeof(AURORA), MYF(MY_ZEROFILL))))
|
||||||
|
{
|
||||||
|
mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql->net.conn_hdlr->data= (void *)aurora;
|
||||||
|
|
||||||
|
aurora->mysql[AURORA_PRIMARY]= mysql;
|
||||||
|
|
||||||
|
if (aurora_parse_url(host, aurora))
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user)
|
||||||
|
aurora->username= strdup(user);
|
||||||
|
if (passwd)
|
||||||
|
aurora->password= strdup(passwd);
|
||||||
|
if (db)
|
||||||
|
aurora->database= strdup(db);
|
||||||
|
aurora->port= port;
|
||||||
|
aurora->client_flag= client_flag;
|
||||||
|
aurora->pvio[AURORA_PRIMARY]= aurora->pvio[AURORA_REPLICA]= NULL;
|
||||||
|
hdlr->data= aurora;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* In case of reconnect, close broken connection first */
|
||||||
|
if (is_reconnect)
|
||||||
|
{
|
||||||
|
DISABLE_AURORA(mysql);
|
||||||
|
switch (aurora->last_instance_type) {
|
||||||
|
case AURORA_REPLICA:
|
||||||
|
aurora_close_replica(mysql, aurora);
|
||||||
|
aurora->pvio[AURORA_REPLICA]= NULL;
|
||||||
|
break;
|
||||||
|
case AURORA_PRIMARY:
|
||||||
|
/* pvio will be closed in mysql_reconnect() */
|
||||||
|
aurora->pvio[AURORA_PRIMARY]= NULL;
|
||||||
|
aurora->primary_id[0]= 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
aurora->active[aurora->last_instance_type]= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aurora->active[AURORA_REPLICA])
|
||||||
|
{
|
||||||
|
if (aurora_find_replica(aurora))
|
||||||
|
{
|
||||||
|
aurora->pvio[AURORA_REPLICA]= aurora->mysql[AURORA_REPLICA]->net.pvio;
|
||||||
|
aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= mysql->net.conn_hdlr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
aurora->pvio[AURORA_REPLICA]= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aurora->active[AURORA_PRIMARY])
|
||||||
|
{
|
||||||
|
if (aurora_find_primary(aurora))
|
||||||
|
{
|
||||||
|
aurora->active[AURORA_PRIMARY]= 1;
|
||||||
|
aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
|
||||||
|
ENABLE_AURORA(mysql);
|
||||||
|
return mysql;
|
||||||
|
error:
|
||||||
|
aurora_close_memory(aurora);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ my_bool aurora_reconnect */
|
||||||
|
my_bool aurora_reconnect(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
AURORA *aurora;
|
||||||
|
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
|
||||||
|
my_bool rc= 1;
|
||||||
|
|
||||||
|
aurora= (AURORA *)hdlr->data;
|
||||||
|
|
||||||
|
DISABLE_AURORA(mysql);
|
||||||
|
switch (aurora->last_instance_type)
|
||||||
|
{
|
||||||
|
case AURORA_REPLICA:
|
||||||
|
if (!(rc= mysql->methods->reconnect(aurora->mysql[aurora->last_instance_type])))
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
|
||||||
|
break;
|
||||||
|
case AURORA_PRIMARY:
|
||||||
|
if (!(rc= mysql->methods->reconnect(aurora->mysql[aurora->last_instance_type])))
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* todo: error message */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ENABLE_AURORA(mysql);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ void aurora_close */
|
||||||
|
void aurora_close(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
|
||||||
|
AURORA *aurora= (AURORA *)hdlr->data;
|
||||||
|
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
|
||||||
|
|
||||||
|
/* if the connection is not active yet, just return */
|
||||||
|
if (!aurora->active[1])
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (aurora->mysql[AURORA_REPLICA])
|
||||||
|
{
|
||||||
|
/* we got options from primary, so don't free it twice */
|
||||||
|
memset(&aurora->mysql[AURORA_REPLICA]->options, 0, sizeof(mysql->options));
|
||||||
|
/* connection handler wull be freed in mysql_close() */
|
||||||
|
aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0;
|
||||||
|
|
||||||
|
mysql_close(aurora->mysql[AURORA_REPLICA]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aurora->mysql[AURORA_PRIMARY])
|
||||||
|
{
|
||||||
|
/* connection handler wull be freed in mysql_close() */
|
||||||
|
aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= 0;
|
||||||
|
|
||||||
|
aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY];
|
||||||
|
|
||||||
|
mysql_close(aurora->mysql[AURORA_PRIMARY]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (aurora->mysql[AURORA_PRIMARY])
|
||||||
|
{
|
||||||
|
aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY];
|
||||||
|
aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= 0;
|
||||||
|
mysql_close(aurora->mysql[AURORA_PRIMARY]);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/* free masrwe information */
|
||||||
|
aurora_close_memory(aurora);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ my_bool is_replica_command */
|
||||||
|
my_bool is_replica_command(const char *buffer, size_t buffer_len)
|
||||||
|
{
|
||||||
|
const char *buffer_end= buffer + buffer_len;
|
||||||
|
|
||||||
|
for (; buffer < buffer_end; ++buffer)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
if (isalpha(c=*buffer))
|
||||||
|
{
|
||||||
|
if (tolower(c) == 's')
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ my_bool is_replica_stmt */
|
||||||
|
my_bool is_replica_stmt(MYSQL *mysql, const char *buffer)
|
||||||
|
{
|
||||||
|
unsigned long stmt_id= uint4korr(buffer);
|
||||||
|
LIST *stmt_list= mysql->stmts;
|
||||||
|
|
||||||
|
for (; stmt_list; stmt_list= stmt_list->next)
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt= (MYSQL_STMT *)stmt_list->data;
|
||||||
|
if (stmt->stmt_id == stmt_id)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ int aurora_command */
|
||||||
|
int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||||
|
size_t length, my_bool skipp_check, void *opt_arg)
|
||||||
|
{
|
||||||
|
AURORA *aurora= (AURORA *)mysql->net.conn_hdlr->data;
|
||||||
|
|
||||||
|
/* if we don't have slave or slave became unavailable root traffic to master */
|
||||||
|
if (!aurora->mysql[AURORA_REPLICA] || !OPT_HAS_EXT_VAL(mysql, read_only))
|
||||||
|
{
|
||||||
|
if (command != COM_INIT_DB)
|
||||||
|
{
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(command) {
|
||||||
|
case COM_INIT_DB:
|
||||||
|
/* we need to change default database on primary and replica */
|
||||||
|
if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA)
|
||||||
|
{
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
|
||||||
|
DISABLE_AURORA(mysql);
|
||||||
|
mysql_select_db(aurora->mysql[AURORA_REPLICA], arg);
|
||||||
|
ENABLE_AURORA(mysql);
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COM_QUERY:
|
||||||
|
case COM_STMT_PREPARE:
|
||||||
|
if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA)
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
|
||||||
|
break;
|
||||||
|
case COM_STMT_EXECUTE:
|
||||||
|
case COM_STMT_FETCH:
|
||||||
|
if (aurora->pvio[AURORA_REPLICA]->mysql->stmts && is_replica_stmt(aurora->pvio[AURORA_REPLICA]->mysql, arg))
|
||||||
|
{
|
||||||
|
if (aurora->last_instance_type != AURORA_REPLICA)
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (aurora->last_instance_type != AURORA_PRIMARY)
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ int aurora_set_options() */
|
||||||
|
int aurora_set_options(MYSQL *mysql, enum mysql_option option, void *arg)
|
||||||
|
{
|
||||||
|
switch(option) {
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* }}} */
|
@@ -70,7 +70,8 @@ MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ =
|
|||||||
repl_connect,
|
repl_connect,
|
||||||
repl_close,
|
repl_close,
|
||||||
repl_set_options,
|
repl_set_options,
|
||||||
repl_command
|
repl_command,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct st_conn_repl {
|
typedef struct st_conn_repl {
|
||||||
@@ -81,10 +82,20 @@ typedef struct st_conn_repl {
|
|||||||
char *url;
|
char *url;
|
||||||
char *host[2];
|
char *host[2];
|
||||||
int port[2];
|
int port[2];
|
||||||
|
unsigned int current_type;
|
||||||
} REPL_DATA;
|
} REPL_DATA;
|
||||||
|
|
||||||
#define SET_SLAVE(mysql, data) mysql->net.pvio= data->pvio[MARIADB_SLAVE]
|
#define SET_SLAVE(mysql, data)\
|
||||||
#define SET_MASTER(mysql, data) mysql->net.pvio= data->pvio[MARIADB_MASTER]
|
{\
|
||||||
|
mysql->net.pvio= data->pvio[MARIADB_SLAVE]; \
|
||||||
|
data->current_type= MARIADB_SLAVE;\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_MASTER(mysql, data)\
|
||||||
|
{\
|
||||||
|
mysql->net.pvio= data->pvio[MARIADB_MASTER];\
|
||||||
|
data->current_type= MARIADB_MASTER;\
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* parse url
|
/* parse url
|
||||||
@@ -108,10 +119,8 @@ my_bool repl_parse_url(const char *url, REPL_DATA *data)
|
|||||||
memset(data->host, 0, 2 * sizeof(char *));
|
memset(data->host, 0, 2 * sizeof(char *));
|
||||||
memset(data->port, 0, 2 * sizeof(int));
|
memset(data->port, 0, 2 * sizeof(int));
|
||||||
|
|
||||||
if (data->url)
|
if (!data->url)
|
||||||
my_free(data->url);
|
data->url= my_strdup(url, MYF(0));
|
||||||
|
|
||||||
data->url= my_strdup(url, MYF(0));
|
|
||||||
data->host[MARIADB_MASTER]= p= data->url;
|
data->host[MARIADB_MASTER]= p= data->url;
|
||||||
|
|
||||||
/* get slaves */
|
/* get slaves */
|
||||||
@@ -150,10 +159,11 @@ my_bool repl_parse_url(const char *url, REPL_DATA *data)
|
|||||||
{
|
{
|
||||||
/* We need to be aware of IPv6 addresses: According to RFC3986 sect. 3.2.2
|
/* We need to be aware of IPv6 addresses: According to RFC3986 sect. 3.2.2
|
||||||
hostnames have to be enclosed in square brackets if a port is given */
|
hostnames have to be enclosed in square brackets if a port is given */
|
||||||
if (data->host[i][0]= '[' && strchr(data->host[i], ':') && (p= strchr(data->host[i],']')))
|
if (data->host[i][0]== '[' && strchr(data->host[i], ':') && (p= strchr(data->host[i],']')))
|
||||||
{
|
{
|
||||||
/* ignore first square bracket */
|
/* ignore first square bracket */
|
||||||
data->host[i]++;
|
memmove(data->host[i], data->host[i]+1, strlen(data->host[i]) - 1);
|
||||||
|
p= strchr(data->host[i],']');
|
||||||
*p= 0;
|
*p= 0;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
@@ -176,12 +186,18 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char
|
|||||||
REPL_DATA *data= NULL;
|
REPL_DATA *data= NULL;
|
||||||
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
|
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
|
||||||
|
|
||||||
|
if ((data= (REPL_DATA *)hdlr->data))
|
||||||
|
{
|
||||||
|
ma_pvio_close(data->pvio[MARIADB_MASTER]);
|
||||||
|
data->pvio[MARIADB_MASTER]= 0;
|
||||||
|
repl_close(mysql);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(data= calloc(1, sizeof(REPL_DATA))))
|
if (!(data= calloc(1, sizeof(REPL_DATA))))
|
||||||
{
|
{
|
||||||
mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(data->pvio, 0, 2 * sizeof(MARIADB_PVIO *));
|
memset(data->pvio, 0, 2 * sizeof(MARIADB_PVIO *));
|
||||||
|
|
||||||
if (repl_parse_url(host, data))
|
if (repl_parse_url(host, data))
|
||||||
@@ -194,6 +210,7 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char
|
|||||||
|
|
||||||
data->pvio[MARIADB_MASTER]= mysql->net.pvio;
|
data->pvio[MARIADB_MASTER]= mysql->net.pvio;
|
||||||
hdlr->data= data;
|
hdlr->data= data;
|
||||||
|
SET_MASTER(mysql, data);
|
||||||
|
|
||||||
/* to allow immediate access without connection delay, we will start
|
/* to allow immediate access without connection delay, we will start
|
||||||
* connecting to slave(s) in background */
|
* connecting to slave(s) in background */
|
||||||
@@ -245,7 +262,6 @@ void repl_close(MYSQL *mysql)
|
|||||||
my_free(data->url);
|
my_free(data->url);
|
||||||
my_free(data);
|
my_free(data);
|
||||||
mysql->net.conn_hdlr->data= NULL;
|
mysql->net.conn_hdlr->data= NULL;
|
||||||
mysql_close(mysql);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static my_bool is_slave_command(const char *buffer, size_t buffer_len)
|
static my_bool is_slave_command(const char *buffer, size_t buffer_len)
|
||||||
@@ -295,20 +311,20 @@ int repl_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
|||||||
case COM_QUERY:
|
case COM_QUERY:
|
||||||
case COM_STMT_PREPARE:
|
case COM_STMT_PREPARE:
|
||||||
if (is_slave_command(arg, length))
|
if (is_slave_command(arg, length))
|
||||||
SET_SLAVE(mysql, data);
|
SET_SLAVE(mysql, data)
|
||||||
else
|
else
|
||||||
SET_MASTER(mysql,data);
|
SET_MASTER(mysql,data)
|
||||||
break;
|
break;
|
||||||
case COM_STMT_EXECUTE:
|
case COM_STMT_EXECUTE:
|
||||||
case COM_STMT_FETCH:
|
case COM_STMT_FETCH:
|
||||||
if (data->pvio[MARIADB_SLAVE]->mysql->stmts && is_slave_stmt(data->pvio[MARIADB_SLAVE]->mysql, arg))
|
if (data->pvio[MARIADB_SLAVE]->mysql->stmts && is_slave_stmt(data->pvio[MARIADB_SLAVE]->mysql, arg))
|
||||||
SET_SLAVE(mysql, data);
|
SET_SLAVE(mysql, data)
|
||||||
else
|
else
|
||||||
SET_MASTER(mysql,data);
|
SET_MASTER(mysql,data)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SET_MASTER(mysql,data);
|
SET_MASTER(mysql,data)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -251,7 +251,7 @@ my_bool pvio_npipe_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
|
|||||||
0, /* no sharing */
|
0, /* no sharing */
|
||||||
NULL, /* default security attributes */
|
NULL, /* default security attributes */
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
0, /* default attributes */
|
FILE_FLAG_OVERLAPPED,
|
||||||
NULL)) != INVALID_HANDLE_VALUE)
|
NULL)) != INVALID_HANDLE_VALUE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@@ -21,7 +21,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
|
|||||||
${CMAKE_SOURCE_DIR}/unittest/mytap)
|
${CMAKE_SOURCE_DIR}/unittest/mytap)
|
||||||
ADD_DEFINITIONS(-DLIBMARIADB)
|
ADD_DEFINITIONS(-DLIBMARIADB)
|
||||||
|
|
||||||
SET(API_TESTS "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs"
|
SET(API_TESTS "aurora" "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs"
|
||||||
"sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol")
|
"sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol")
|
||||||
|
|
||||||
# Get finger print from server certificate
|
# Get finger print from server certificate
|
||||||
@@ -61,7 +61,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 )
|
TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb)
|
||||||
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)
|
||||||
|
67
unittest/libmariadb/aurora.c
Normal file
67
unittest/libmariadb/aurora.c
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "my_test.h"
|
||||||
|
|
||||||
|
static int aurora1(MYSQL *mysql)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
my_bool read_only= 1;
|
||||||
|
char *primary, *replica;
|
||||||
|
MYSQL_RES *res;
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "CREATE TABLE t1 (a int, b varchar(20))");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1, 'foo'), (2, 'bar')");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
primary= mysql->host;
|
||||||
|
diag("primary: %s", primary);
|
||||||
|
|
||||||
|
mysql_options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, &read_only);
|
||||||
|
|
||||||
|
/* ensure, that this is a replica, so INSERT should fail */
|
||||||
|
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (3, 'error')");
|
||||||
|
if (rc)
|
||||||
|
diag("Expected error: %s", mysql_error(mysql));
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "SELECT a, b FROM t1");
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
res= mysql_store_result(mysql);
|
||||||
|
|
||||||
|
diag("Num_rows: %d", mysql_num_rows(res));
|
||||||
|
mysql_free_result(res);
|
||||||
|
|
||||||
|
replica= mysql->host;
|
||||||
|
diag("replica: %s", replica);
|
||||||
|
diag("db: %s", mysql->db);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct my_tests_st my_tests[] = {
|
||||||
|
{"aurora1", aurora1, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||||
|
{NULL, NULL, 0, 0, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
mysql_library_init(0,0,NULL);
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
get_options(argc, argv);
|
||||||
|
|
||||||
|
get_envvars();
|
||||||
|
|
||||||
|
run_tests(my_tests);
|
||||||
|
|
||||||
|
mysql_server_end();
|
||||||
|
return(exit_status());
|
||||||
|
}
|
@@ -55,13 +55,17 @@ static int test_conc75(MYSQL *my)
|
|||||||
{
|
{
|
||||||
ulong thread_id= mysql_thread_id(mysql);
|
ulong thread_id= mysql_thread_id(mysql);
|
||||||
/* force reconnect */
|
/* force reconnect */
|
||||||
|
mysql->reconnect= 1;
|
||||||
|
diag("killing connection");
|
||||||
mysql_kill(my, thread_id);
|
mysql_kill(my, thread_id);
|
||||||
sleep(1);
|
sleep(2);
|
||||||
|
mysql_ping(mysql);
|
||||||
rc= mysql_query(mysql, "load data local infile './nonexistingfile.csv' into table a (`a`)");
|
rc= mysql_query(mysql, "load data local infile './nonexistingfile.csv' into table a (`a`)");
|
||||||
FAIL_IF(!test(mysql->options.client_flag | CLIENT_LOCAL_FILES), "client_flags not correct");
|
FAIL_IF(!test(mysql->options.client_flag | CLIENT_LOCAL_FILES), "client_flags not correct");
|
||||||
|
diag("thread1: %d %d", thread_id, mysql_thread_id(mysql));
|
||||||
FAIL_IF(thread_id == mysql_thread_id(mysql), "new thread id expected");
|
FAIL_IF(thread_id == mysql_thread_id(mysql), "new thread id expected");
|
||||||
diag("cs: %s", mysql->charset->csname);
|
//diag("cs: %s", mysql->charset->csname);
|
||||||
FAIL_IF(strcmp(mysql->charset->csname, "utf8"), "wrong character set");
|
//FAIL_IF(strcmp(mysql->charset->csname, "utf8"), "wrong character set");
|
||||||
}
|
}
|
||||||
mysql_close(mysql);
|
mysql_close(mysql);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -76,7 +80,12 @@ static int test_conc74(MYSQL *my)
|
|||||||
mysql= mysql_init(NULL);
|
mysql= mysql_init(NULL);
|
||||||
|
|
||||||
|
|
||||||
mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS);
|
if (!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS))
|
||||||
|
{
|
||||||
|
diag("Error: %s", mysql_error(mysql));
|
||||||
|
mysql_close(mysql);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
rc= mysql_query(mysql, "DROP TABLE IF EXISTS a");
|
rc= mysql_query(mysql, "DROP TABLE IF EXISTS a");
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
@@ -128,7 +137,11 @@ static int test_conc70(MYSQL *my)
|
|||||||
int rc;
|
int rc;
|
||||||
MYSQL_RES *res;
|
MYSQL_RES *res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
MYSQL *mysql= mysql_init(NULL);
|
MYSQL *mysql;
|
||||||
|
|
||||||
|
SKIP_CONNECTION_HANDLER;
|
||||||
|
|
||||||
|
mysql= mysql_init(NULL);
|
||||||
|
|
||||||
rc= mysql_query(my, "SET @a:=@@max_allowed_packet");
|
rc= mysql_query(my, "SET @a:=@@max_allowed_packet");
|
||||||
check_mysql_rc(rc, my);
|
check_mysql_rc(rc, my);
|
||||||
@@ -148,6 +161,14 @@ static int test_conc70(MYSQL *my)
|
|||||||
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))");
|
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))");
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
if (mysql_warning_count(mysql))
|
||||||
|
{
|
||||||
|
diag("server doesn't accept package size");
|
||||||
|
return SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(20);
|
||||||
|
|
||||||
rc= mysql_query(mysql, "SELECT a FROM t1");
|
rc= mysql_query(mysql, "SELECT a FROM t1");
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
@@ -175,7 +196,11 @@ static int test_conc68(MYSQL *my)
|
|||||||
int rc;
|
int rc;
|
||||||
MYSQL_RES *res;
|
MYSQL_RES *res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
MYSQL *mysql= mysql_init(NULL);
|
MYSQL *mysql;
|
||||||
|
|
||||||
|
SKIP_CONNECTION_HANDLER;
|
||||||
|
|
||||||
|
mysql= mysql_init(NULL);
|
||||||
|
|
||||||
rc= mysql_query(my, "SET @a:=@@max_allowed_packet");
|
rc= mysql_query(my, "SET @a:=@@max_allowed_packet");
|
||||||
check_mysql_rc(rc, my);
|
check_mysql_rc(rc, my);
|
||||||
@@ -193,6 +218,11 @@ static int test_conc68(MYSQL *my)
|
|||||||
|
|
||||||
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))");
|
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))");
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
|
if (mysql_warning_count(mysql))
|
||||||
|
{
|
||||||
|
diag("server doesn't accept package size");
|
||||||
|
return SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
rc= mysql_query(mysql, "SELECT a FROM t1");
|
rc= mysql_query(mysql, "SELECT a FROM t1");
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
@@ -504,6 +534,7 @@ static int test_mysql_insert_id(MYSQL *mysql)
|
|||||||
according to the manual, this might be 20 or 300, but it looks like
|
according to the manual, this might be 20 or 300, but it looks like
|
||||||
auto_increment column takes priority over last_insert_id().
|
auto_increment column takes priority over last_insert_id().
|
||||||
*/
|
*/
|
||||||
|
diag("res: %d", res);
|
||||||
FAIL_UNLESS(res == 20, "");
|
FAIL_UNLESS(res == 20, "");
|
||||||
/* If first autogenerated number fails and 2nd works: */
|
/* If first autogenerated number fails and 2nd works: */
|
||||||
rc= mysql_query(mysql, "drop table t2");
|
rc= mysql_query(mysql, "drop table t2");
|
||||||
@@ -618,12 +649,9 @@ static int bug_conc1(MYSQL *mysql)
|
|||||||
{
|
{
|
||||||
mysql_real_connect(mysql, hostname, username, password, schema,
|
mysql_real_connect(mysql, hostname, username, password, schema,
|
||||||
port, socketname, 0);
|
port, socketname, 0);
|
||||||
|
diag("errno: %d", mysql_errno(mysql));
|
||||||
FAIL_IF(mysql_errno(mysql) != CR_ALREADY_CONNECTED,
|
FAIL_IF(mysql_errno(mysql) != CR_ALREADY_CONNECTED,
|
||||||
"Expected errno=CR_ALREADY_CONNECTED");
|
"Expected errno=CR_ALREADY_CONNECTED");
|
||||||
FAIL_IF(strcmp(mysql_error(mysql), ER(CR_ALREADY_CONNECTED)) != 0,
|
|
||||||
"Wrong error message");
|
|
||||||
FAIL_IF(strcmp(ER(CR_ALREADY_CONNECTED), "Can't connect twice. Already connected") != 0,
|
|
||||||
"wrong error message");
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,11 +696,14 @@ static int test_reconnect_maxpackage(MYSQL *my)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
ulong max_packet= 0;
|
ulong max_packet= 0;
|
||||||
MYSQL *mysql= mysql_init(NULL);
|
MYSQL *mysql;
|
||||||
MYSQL_RES *res;
|
MYSQL_RES *res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
char *query;
|
char *query;
|
||||||
|
|
||||||
|
SKIP_CONNECTION_HANDLER;
|
||||||
|
mysql= mysql_init(NULL);
|
||||||
|
|
||||||
FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
|
FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
|
||||||
port, socketname,
|
port, socketname,
|
||||||
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
|
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
|
||||||
@@ -770,6 +801,8 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
get_envvars();
|
get_envvars();
|
||||||
|
|
||||||
|
diag("user: %s", username);
|
||||||
|
|
||||||
run_tests(my_tests);
|
run_tests(my_tests);
|
||||||
|
|
||||||
return(exit_status());
|
return(exit_status());
|
||||||
|
@@ -679,7 +679,7 @@ static int test_utf16_utf32_noboms(MYSQL *mysql)
|
|||||||
|
|
||||||
for (i= 0; i < sizeof(csname)/sizeof(char*); ++i)
|
for (i= 0; i < sizeof(csname)/sizeof(char*); ++i)
|
||||||
{
|
{
|
||||||
csinfo[i]= mysql_find_charset_name(csname[i]);
|
csinfo[i]= mariadb_get_charset_by_name(csname[i]);
|
||||||
|
|
||||||
if (csinfo[i] == NULL)
|
if (csinfo[i] == NULL)
|
||||||
{
|
{
|
||||||
|
@@ -32,6 +32,7 @@ static int test_conc66(MYSQL *my)
|
|||||||
MYSQL *mysql= mysql_init(NULL);
|
MYSQL *mysql= mysql_init(NULL);
|
||||||
int rc;
|
int rc;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
char query[1024];
|
||||||
|
|
||||||
if (!(fp= fopen("./my.cnf", "w")))
|
if (!(fp= fopen("./my.cnf", "w")))
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -47,7 +48,8 @@ static int test_conc66(MYSQL *my)
|
|||||||
rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./my.cnf");
|
rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./my.cnf");
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
rc= mysql_query(my, "GRANT ALL ON test.* TO 'conc66'@'localhost' IDENTIFIED BY 'test\";#test'");
|
sprintf(query, "GRANT ALL ON %s.* TO 'conc66'@'%s' IDENTIFIED BY 'test\";#test'", schema, hostname);
|
||||||
|
rc= mysql_query(my, query);
|
||||||
check_mysql_rc(rc, my);
|
check_mysql_rc(rc, my);
|
||||||
rc= mysql_query(my, "FLUSH PRIVILEGES");
|
rc= mysql_query(my, "FLUSH PRIVILEGES");
|
||||||
check_mysql_rc(rc, my);
|
check_mysql_rc(rc, my);
|
||||||
@@ -57,7 +59,8 @@ static int test_conc66(MYSQL *my)
|
|||||||
diag("Error: %s", mysql_error(mysql));
|
diag("Error: %s", mysql_error(mysql));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
rc= mysql_query(my, "DROP USER conc66@localhost");
|
sprintf(query, "DROP user conc66@%s", hostname);
|
||||||
|
rc= mysql_query(my, query);
|
||||||
|
|
||||||
check_mysql_rc(rc, my);
|
check_mysql_rc(rc, my);
|
||||||
mysql_close(mysql);
|
mysql_close(mysql);
|
||||||
@@ -561,6 +564,8 @@ static int test_reconnect(MYSQL *mysql)
|
|||||||
mysql_kill(mysql, mysql_thread_id(mysql1));
|
mysql_kill(mysql, mysql_thread_id(mysql1));
|
||||||
sleep(4);
|
sleep(4);
|
||||||
|
|
||||||
|
mysql_ping(mysql1);
|
||||||
|
|
||||||
rc= mysql_query(mysql1, "SELECT 1 FROM DUAL LIMIT 0");
|
rc= mysql_query(mysql1, "SELECT 1 FROM DUAL LIMIT 0");
|
||||||
check_mysql_rc(rc, mysql1);
|
check_mysql_rc(rc, mysql1);
|
||||||
diag("Thread_id after kill: %lu", mysql_thread_id(mysql1));
|
diag("Thread_id after kill: %lu", mysql_thread_id(mysql1));
|
||||||
@@ -649,6 +654,8 @@ static int test_conc118(MYSQL *mysql)
|
|||||||
rc= mysql_kill(mysql, mysql_thread_id(mysql));
|
rc= mysql_kill(mysql, mysql_thread_id(mysql));
|
||||||
sleep(2);
|
sleep(2);
|
||||||
|
|
||||||
|
mysql_ping(mysql);
|
||||||
|
|
||||||
rc= mysql_query(mysql, "SET @a:=1");
|
rc= mysql_query(mysql, "SET @a:=1");
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
@@ -657,12 +664,9 @@ static int test_conc118(MYSQL *mysql)
|
|||||||
rc= mysql_kill(mysql, mysql_thread_id(mysql));
|
rc= mysql_kill(mysql, mysql_thread_id(mysql));
|
||||||
sleep(2);
|
sleep(2);
|
||||||
|
|
||||||
mysql->host= "foo";
|
|
||||||
|
|
||||||
rc= mysql_query(mysql, "SET @a:=1");
|
rc= mysql_query(mysql, "SET @a:=1");
|
||||||
FAIL_IF(!rc, "error expected");
|
FAIL_IF(!rc, "error expected");
|
||||||
|
|
||||||
mysql->host= hostname;
|
|
||||||
rc= mysql_query(mysql, "SET @a:=1");
|
rc= mysql_query(mysql, "SET @a:=1");
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
@@ -82,6 +82,13 @@ if (!(expr))\
|
|||||||
return FAIL;\
|
return FAIL;\
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SKIP_CONNECTION_HANDLER \
|
||||||
|
if (hostname && strstr(hostname, "://"))\
|
||||||
|
{\
|
||||||
|
diag("Test skipped (connection handler)");\
|
||||||
|
return SKIP;\
|
||||||
|
}
|
||||||
|
|
||||||
/* connection options */
|
/* connection options */
|
||||||
#define TEST_CONNECTION_DEFAULT 1 /* default connection */
|
#define TEST_CONNECTION_DEFAULT 1 /* default connection */
|
||||||
#define TEST_CONNECTION_NONE 2 /* tests creates own connection */
|
#define TEST_CONNECTION_NONE 2 /* tests creates own connection */
|
||||||
@@ -104,7 +111,7 @@ struct my_tests_st
|
|||||||
char *skipmsg;
|
char *skipmsg;
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *schema = "test_c";
|
static char *schema = 0;
|
||||||
static char *hostname = 0;
|
static char *hostname = 0;
|
||||||
static char *password = 0;
|
static char *password = 0;
|
||||||
static unsigned int port = 0;
|
static unsigned int port = 0;
|
||||||
@@ -368,18 +375,19 @@ int check_variable(MYSQL *mysql, char *variable, char *value)
|
|||||||
MYSQL *test_connect(struct my_tests_st *test) {
|
MYSQL *test_connect(struct my_tests_st *test) {
|
||||||
MYSQL *mysql;
|
MYSQL *mysql;
|
||||||
char query[255];
|
char query[255];
|
||||||
int i= 1;
|
int i= 0;
|
||||||
|
int timeout= 10;
|
||||||
|
int truncation_report= 1;
|
||||||
if (!(mysql = mysql_init(NULL))) {
|
if (!(mysql = mysql_init(NULL))) {
|
||||||
diag("%s", "mysql_init failed - exiting");
|
diag("%s", "mysql_init failed - exiting");
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &i);
|
mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &truncation_report);
|
||||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&i);
|
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
|
||||||
|
|
||||||
/* option handling */
|
/* option handling */
|
||||||
if (test && test->options) {
|
if (test && test->options) {
|
||||||
int i=0;
|
|
||||||
|
|
||||||
while (test->options[i].option)
|
while (test->options[i].option)
|
||||||
{
|
{
|
||||||
@@ -403,6 +411,8 @@ MYSQL *test_connect(struct my_tests_st *test) {
|
|||||||
|
|
||||||
/* change database or create if it doesn't exist */
|
/* change database or create if it doesn't exist */
|
||||||
if (mysql_select_db(mysql, schema)) {
|
if (mysql_select_db(mysql, schema)) {
|
||||||
|
diag("Error number: %d", mysql_errno(mysql));
|
||||||
|
|
||||||
if(mysql_errno(mysql) == 1049) {
|
if(mysql_errno(mysql) == 1049) {
|
||||||
sprintf(query, "CREATE DATABASE %s", schema);
|
sprintf(query, "CREATE DATABASE %s", schema);
|
||||||
if (mysql_query(mysql, query)) {
|
if (mysql_query(mysql, query)) {
|
||||||
@@ -425,11 +435,6 @@ static int reset_connection(MYSQL *mysql) {
|
|||||||
|
|
||||||
rc= mysql_change_user(mysql, username, password, schema);
|
rc= mysql_change_user(mysql, username, password, schema);
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
if (mysql_get_server_version(mysql) < 50400)
|
|
||||||
rc= mysql_query(mysql, "SET table_type='MyISAM'");
|
|
||||||
else
|
|
||||||
rc= mysql_query(mysql, "SET storage_engine='MyISAM'");
|
|
||||||
check_mysql_rc(rc, mysql);
|
|
||||||
rc= mysql_query(mysql, "SET sql_mode=''");
|
rc= mysql_query(mysql, "SET sql_mode=''");
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
@@ -452,6 +457,8 @@ void get_envvars() {
|
|||||||
password= envvar;
|
password= envvar;
|
||||||
if (!schema && (envvar= getenv("MYSQL_TEST_DB")))
|
if (!schema && (envvar= getenv("MYSQL_TEST_DB")))
|
||||||
schema= envvar;
|
schema= envvar;
|
||||||
|
if (!schema)
|
||||||
|
schema= "testc";
|
||||||
if (!port && (envvar= getenv("MYSQL_TEST_PORT")))
|
if (!port && (envvar= getenv("MYSQL_TEST_PORT")))
|
||||||
port= atoi(envvar);
|
port= atoi(envvar);
|
||||||
if (!socketname && (envvar= getenv("MYSQL_TEST_SOCKET")))
|
if (!socketname && (envvar= getenv("MYSQL_TEST_SOCKET")))
|
||||||
@@ -470,7 +477,8 @@ void run_tests(struct my_tests_st *test) {
|
|||||||
if ((mysql_default= test_connect(NULL)))
|
if ((mysql_default= test_connect(NULL)))
|
||||||
{
|
{
|
||||||
diag("Testing against MySQL Server %s", mysql_get_server_info(mysql_default));
|
diag("Testing against MySQL Server %s", mysql_get_server_info(mysql_default));
|
||||||
diag("Host %s", mysql_get_host_info(mysql_default));
|
diag("Host: %s", mysql_get_host_info(mysql_default));
|
||||||
|
diag("Client library: %s", mysql_get_client_info());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -64,7 +64,10 @@ static int test_conc83(MYSQL *my)
|
|||||||
/* 1. Status is inited, so prepare should work */
|
/* 1. Status is inited, so prepare should work */
|
||||||
|
|
||||||
rc= mysql_kill(mysql, mysql_thread_id(mysql));
|
rc= mysql_kill(mysql, mysql_thread_id(mysql));
|
||||||
sleep(2);
|
sleep(5);
|
||||||
|
|
||||||
|
rc= mysql_ping(mysql);
|
||||||
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
rc= mysql_stmt_prepare(stmt, query, strlen(query));
|
rc= mysql_stmt_prepare(stmt, query, strlen(query));
|
||||||
check_stmt_rc(rc, stmt);
|
check_stmt_rc(rc, stmt);
|
||||||
|
@@ -528,9 +528,8 @@ static int test_bug12744(MYSQL *mysql)
|
|||||||
rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, "1");
|
rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, "1");
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
rc= mysql_kill(mysql, mysql_thread_id(mysql));
|
rc= mysql_kill(mysql, mysql_thread_id(mysql));
|
||||||
check_mysql_rc(rc, mysql);
|
|
||||||
|
|
||||||
sleep(2);
|
sleep(4);
|
||||||
rc= mysql_ping(mysql);
|
rc= mysql_ping(mysql);
|
||||||
check_mysql_rc(rc, mysql);
|
check_mysql_rc(rc, mysql);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user