From f8912935b1fbb51a3d5ecb1f1907602284c8bf5d Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Sat, 16 Jan 2016 07:04:28 +0100 Subject: [PATCH] - Fixed several aurora plugin crashes (after reconnect) - moved mysql->reconnect to mysql->options.reconnect --- include/ma_common.h | 1 + include/mysql.h | 11 +- libmariadb/libmariadb.c | 80 ++++--- libmariadb/ma_pvio.c | 4 +- libmariadb/net.c | 5 +- plugins/connection/aurora.c | 364 +++++++++++++------------------ plugins/connection/replication.c | 4 +- unittest/libmariadb/basic-t.c | 12 +- unittest/libmariadb/connection.c | 42 ++-- unittest/libmariadb/misc.c | 3 +- unittest/libmariadb/my_test.h | 22 +- unittest/libmariadb/ps.c | 12 +- unittest/libmariadb/result.c | 3 +- unittest/libmariadb/t_aurora.c | 92 +++++++- 14 files changed, 351 insertions(+), 304 deletions(-) diff --git a/include/ma_common.h b/include/ma_common.h index 83fb4291..87fca0e8 100644 --- a/include/ma_common.h +++ b/include/ma_common.h @@ -54,6 +54,7 @@ struct st_mysql_options_extension { char *ssl_pw; /* password for encrypted certificates */ char *url; /* for connection handler we need to save URL for reconnect */ my_bool read_only; + char *connection_handler; HASH userdata; }; diff --git a/include/mysql.h b/include/mysql.h index ef8f133d..b6078699 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -216,7 +216,8 @@ extern unsigned int mariadb_deinitialize_ssl; MARIADB_OPT_SSL_PASSPHRASE, /* passphrase for encrypted certificates */ MARIADB_OPT_CONNECTION_READ_ONLY, MYSQL_OPT_CONNECT_ATTRS, /* for mysql_get_optionv */ - MARIADB_OPT_USERDATA + MARIADB_OPT_USERDATA, + MARIADB_OPT_CONNECTION_HANDLER }; enum mariadb_value { @@ -284,7 +285,7 @@ struct st_mysql_options { unsigned long max_allowed_packet; my_bool use_ssl; /* if to use SSL or not */ my_bool compress,named_pipe; - my_bool unused_1, unused_2, unused_3, unused_4; + my_bool reconnect, unused_1, unused_2, unused_3; enum mysql_option methods_to_use; char *bind_address; my_bool secure_auth; @@ -321,11 +322,11 @@ struct st_mysql_options { struct st_mysql_options options; enum mysql_status status; my_bool free_me; /* If free in mysql_close */ - my_bool reconnect; /* set to 1 if automatic reconnect */ + my_bool unused_1; char scramble_buff[20+ 1]; /* madded after 3.23.58 */ - my_bool unused_1; - void *unused_2, *unused_3, *unused_4, *unused_5; + my_bool unused_2; + void *unused_3, *unused_4, *unused_5, *unused_6; LIST *stmts; const struct st_mysql_methods *methods; void *thd; diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 85657e60..9a960ab7 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -133,7 +133,7 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS; #define native_password_plugin_name "mysql_native_password" #define IS_CONNHDLR_ACTIVE(mysql)\ - ((mysql)->net.conn_hdlr && (mysql)->net.conn_hdlr->active) + (((mysql)->net.conn_hdlr)) static void end_server(MYSQL *mysql); static void mysql_close_memory(MYSQL *mysql); @@ -1160,7 +1160,7 @@ mysql_init(MYSQL *mysql) #ifdef ENABLED_LOCAL_INFILE mysql->options.client_flag|= CLIENT_LOCAL_FILES; #endif - mysql->reconnect= 0; + mysql->options.reconnect= 0; return mysql; } @@ -1295,18 +1295,26 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user, uint port, const char *unix_socket,unsigned long client_flag) { char *end; + char *connection_handler= (mysql->options.extension) ? + mysql->options.extension->connection_handler : 0; if (!mysql->methods) mysql->methods= &MARIADB_DEFAULT_METHODS; - if (host && (end= strstr(host, "://"))) + if (connection_handler || + (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 (!connection_handler || !connection_handler[0]) + { + bzero(plugin_name, 64); + strncpy(plugin_name, host, MIN(end - host, 63)); + end+= 3; + } + else + strncpy(plugin_name, connection_handler, MIN(63, strlen(connection_handler))); if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN))) return NULL; @@ -1324,7 +1332,13 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user, if (plugin && plugin->connect) { - return plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag); + MYSQL *my= plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag); + if (!my) + { + my_free(mysql->net.conn_hdlr); + mysql->net.conn_hdlr= NULL; + } + return my; } } @@ -1663,8 +1677,8 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, char **end= begin + mysql->options.init_command->elements; /* Avoid reconnect in mysql_real_connect */ - my_bool save_reconnect= mysql->reconnect; - mysql->reconnect= 0; + my_bool save_reconnect= mysql->options.reconnect; + mysql->options.reconnect= 0; for (;begin < end; begin++) { @@ -1678,7 +1692,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, mysql_free_result(res); } while (!mysql_next_result(mysql)); } - mysql->reconnect= save_reconnect; + mysql->options.reconnect= save_reconnect; } strmov(mysql->net.sqlstate, "00000"); @@ -1733,13 +1747,13 @@ my_bool STDCALL mysql_reconnect(MYSQL *mysql) DBUG_ENTER("mysql_reconnect"); /* check if connection handler is active */ - if (IS_CONNHDLR_ACTIVE(mysql)) + if (IS_CONNHDLR_ACTIVE(mysql)) { - if (mysql->net.conn_hdlr->plugin && mysql->net.conn_hdlr->plugin->connect) + if (mysql->net.conn_hdlr->plugin && mysql->net.conn_hdlr->plugin->reconnect) DBUG_RETURN(mysql->net.conn_hdlr->plugin->reconnect(mysql)); } - if (!mysql->reconnect || + if (!mysql->options.reconnect || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) { /* Allow reconnect next time */ @@ -1750,13 +1764,6 @@ my_bool STDCALL mysql_reconnect(MYSQL *mysql) mysql_init(&tmp_mysql); 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 */ tmp_mysql.options.my_cnf_group= tmp_mysql.options.my_cnf_file= NULL; @@ -1796,7 +1803,6 @@ my_bool STDCALL mysql_reconnect(MYSQL *mysql) } } - tmp_mysql.reconnect= mysql->reconnect; tmp_mysql.free_me= mysql->free_me; tmp_mysql.stmts= mysql->stmts; mysql->stmts= NULL; @@ -1957,6 +1963,7 @@ static void mysql_close_options(MYSQL *mysql) my_free(mysql->options.extension->ssl_fp_list); my_free(mysql->options.extension->ssl_pw); my_free(mysql->options.extension->url); + my_free(mysql->options.extension->connection_handler); if(hash_inited(&mysql->options.extension->connect_attrs)) hash_free(&mysql->options.extension->connect_attrs); if (hash_inited(&mysql->options.extension->userdata)) @@ -2009,8 +2016,9 @@ void mysql_close_slow_part(MYSQL *mysql) { free_old_query(mysql); mysql->status=MYSQL_STATUS_READY; /* Force command */ - mysql->reconnect=0; - simple_command(mysql, COM_QUIT,NullS,0,1,0); + mysql->options.reconnect=0; + if (mysql->net.pvio && mysql->net.buff) + simple_command(mysql, COM_QUIT,NullS,0,1,0); end_server(mysql); } } @@ -2021,13 +2029,11 @@ mysql_close(MYSQL *mysql) DBUG_ENTER("mysql_close"); if (mysql) /* Some simple safety */ { - - if (IS_CONNHDLR_ACTIVE(mysql)) + if (mysql->net.conn_hdlr) { - void *p= (void *)mysql->net.conn_hdlr; - mysql->net.conn_hdlr->plugin->close(mysql); + MA_CONNECTION_HANDLER *p= mysql->net.conn_hdlr; + p->plugin->close(mysql); my_free(p); - DBUG_VOID_RETURN; } if (mysql->methods) @@ -2544,7 +2550,7 @@ mysql_ping(MYSQL *mysql) rc= simple_command(mysql, COM_PING,0,0,0,0); /* if connection was terminated and reconnect is true, try again */ - if (rc!=0 && mysql->reconnect) + if (rc!=0 && mysql->options.reconnect) rc= simple_command(mysql, COM_PING,0,0,0,0); return rc; } @@ -2682,7 +2688,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) mysql->options.charset_name=my_strdup((char *)arg1,MYF(MY_WME)); break; case MYSQL_OPT_RECONNECT: - mysql->reconnect= *(uint *)arg1; + mysql->options.reconnect= *(uint *)arg1; break; case MYSQL_OPT_PROTOCOL: #ifdef _WIN32 @@ -2700,7 +2706,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) mysql->options.write_timeout= *(uint *)arg1; break; case MYSQL_REPORT_DATA_TRUNCATION: - mysql->options.report_data_truncation= *(uint *)arg1; + mysql->options.report_data_truncation= *(my_bool *)arg1; break; case MYSQL_PROGRESS_CALLBACK: if (!mysql->options.extension) @@ -2785,7 +2791,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) break; case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: - if (*(uint *)arg1) + if (*(my_bool *)arg1) mysql->options.client_flag |= CLIENT_SSL_VERIFY_SERVER_CERT; else mysql->options.client_flag &= ~CLIENT_SSL_VERIFY_SERVER_CERT; @@ -2843,6 +2849,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) mysql->options.extension->connect_attrs_len= 0; } break; + case MARIADB_OPT_CONNECTION_HANDLER: + OPT_SET_EXTENDED_VALUE_STR(&mysql->options, connection_handler, (char *)arg1); + break; case MARIADB_OPT_USERDATA: { void *data= va_arg(ap, void *); @@ -3029,7 +3038,7 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) *((char **)arg)= mysql->options.charset_name; break; case MYSQL_OPT_RECONNECT: - *((uint *)arg)= mysql->reconnect; + *((my_bool *)arg)= mysql->options.reconnect; break; case MYSQL_OPT_PROTOCOL: *((uint *)arg)= mysql->options.protocol; @@ -3041,7 +3050,7 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) *((uint *)arg)= mysql->options.write_timeout; break; case MYSQL_REPORT_DATA_TRUNCATION: - *((uint *)arg)= mysql->options.report_data_truncation; + *((my_bool *)arg)= mysql->options.report_data_truncation; break; case MYSQL_PROGRESS_CALLBACK: *((void (**)(const MYSQL *, uint, uint, double, const char *, uint))arg)= @@ -3159,6 +3168,9 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) *((void **)data)= NULL; } break; + case MARIADB_OPT_CONNECTION_HANDLER: + *((char **)arg)= mysql->options.extension ? mysql->options.extension->connection_handler : NULL; + break; default: va_end(ap); DBUG_RETURN(-1); diff --git a/libmariadb/ma_pvio.c b/libmariadb/ma_pvio.c index 1d763381..7d012c66 100644 --- a/libmariadb/ma_pvio.c +++ b/libmariadb/ma_pvio.c @@ -489,8 +489,8 @@ my_bool ma_pvio_is_blocking(MARIADB_PVIO *pvio) my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *data_len) { /* check if we still have unread data in cache */ - if (pvio->cache) - if (pvio->cache_pos > pvio->cache) + if (pvio && pvio->cache) + if (pvio->cache_pos > pvio->cache) return test(pvio->cache_pos - pvio->cache); if (pvio && pvio->methods->has_data) return pvio->methods->has_data(pvio, data_len); diff --git a/libmariadb/net.c b/libmariadb/net.c index 94c32104..5a850ad7 100644 --- a/libmariadb/net.c +++ b/libmariadb/net.c @@ -182,9 +182,10 @@ static my_bool net_realloc(NET *net, size_t length) /* Remove unwanted characters from connection */ void net_clear(NET *net) { - size_t len; +// size_t len; DBUG_ENTER("net_clear"); - ma_pvio_has_data(net->pvio, &len); +/* if (net->pvio) + ma_pvio_has_data(net->pvio, &len); */ net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */ net->write_pos=net->buff; DBUG_VOID_RETURN; diff --git a/plugins/connection/aurora.c b/plugins/connection/aurora.c index 2ac5de00..32fbfe31 100644 --- a/plugins/connection/aurora.c +++ b/plugins/connection/aurora.c @@ -45,7 +45,6 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch 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 @@ -55,11 +54,6 @@ my_bool aurora_reconnect(MYSQL *mysql); #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_AURORA_DYNAMIC MARIADB_CONNECTION_PLUGIN connection_aurora_plugin = #else @@ -77,7 +71,7 @@ MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ = NULL, aurora_connect, aurora_close, - aurora_set_options, + NULL, aurora_command, aurora_reconnect }; @@ -92,16 +86,14 @@ typedef struct st_aurora_instance { } AURORA_INSTANCE; typedef struct st_conn_aurora { - MARIADB_PVIO *pvio[2]; - MYSQL *mysql[2]; - my_bool active[2]; + MYSQL *mysql[2], + save_mysql; 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; @@ -118,20 +110,13 @@ my_bool aurora_switch_connection(MYSQL *mysql, AURORA *aurora, int 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; + *mysql= *aurora->mysql[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; + *mysql= *aurora->mysql[AURORA_PRIMARY]; } break; default: @@ -257,17 +242,23 @@ my_bool aurora_parse_url(const char *url, AURORA *aurora) */ int aurora_get_instance_type(MYSQL *mysql) { - int rc; + int rc= -1; + MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr; + char *query= "select variable_value from information_schema.global_variables where variable_name='INNODB_READ_ONLY' AND variable_value='OFF'"; + if (!mysql) + return -1; + + mysql->net.conn_hdlr= 0; if (!mariadb_api->mysql_query(mysql, query)) { MYSQL_RES *res= mariadb_api->mysql_store_result(mysql); rc= mysql_num_rows(res) ? AURORA_PRIMARY : AURORA_REPLICA; mariadb_api->mysql_free_result(res); - return rc; } - return -1; + mysql->net.conn_hdlr= save_hdlr; + return rc; } /* }}} */ @@ -287,7 +278,9 @@ int aurora_get_instance_type(MYSQL *mysql) my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora) { my_bool rc= 0; + MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr; + mysql->net.conn_hdlr= 0; if (!mariadb_api->mysql_query(mysql, "select server_id from information_schema.replica_host_status " "where session_id = 'MASTER_SESSION_ID'")) { @@ -307,6 +300,7 @@ my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora) mariadb_api->mysql_free_result(res); } } + mysql->net.conn_hdlr= save_hdlr; return rc; } /* }}} */ @@ -326,7 +320,7 @@ static unsigned int aurora_get_valid_instances(AURORA *aurora, AURORA_INSTANCE * { if (aurora->instance[i].type != AURORA_UNAVAILABLE) { - if (aurora->instance[i].type == AURORA_PRIMARY && aurora->active[AURORA_PRIMARY]) + if (aurora->instance[i].type == AURORA_PRIMARY && aurora->mysql[AURORA_PRIMARY]) continue; instances[valid_instances]= &aurora->instance[i]; valid_instances++; @@ -386,31 +380,21 @@ MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL return NULL; } if (!aurora->primary_id[0]) - aurora_get_primary_id(mysql, aurora); + if (aurora_get_primary_id(mysql, aurora)) + return NULL; return mysql; } /* }}} */ -/* {{{ void aurora_copy_mysql() */ -void aurora_copy_mysql(MYSQL *from, MYSQL *to) +/* {{{ void aurora_close_internal */ +void aurora_close_internal(MYSQL *mysql) { - /* invalidate statements */ - to->methods->invalidate_stmts(to, "aurora connect/reconnect"); - - 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; - mariadb_api->mysql_close(to); - *to= *from; - to->net.pvio= from->net.pvio; - to->net.pvio->mysql= to; - from->net.pvio= NULL; + if (mysql) + { + mysql->net.conn_hdlr= 0; + memset(&mysql->options, 0, sizeof(struct st_mysql_options)); + mariadb_api->mysql_close(mysql); + } } /* }}} */ @@ -420,46 +404,45 @@ my_bool aurora_find_replica(AURORA *aurora) int valid_instances; my_bool replica_found= 0; AURORA_INSTANCE *instance[AURORA_MAX_INSTANCES]; - MYSQL mysql; + MYSQL *mysql; if (aurora->num_instances < 2) return 0; - mariadb_api->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))) + mysql= mariadb_api->mysql_init(NULL); + mysql->options= aurora->save_mysql.options; + + /* don't execute init_command on slave */ +// mysql->net.conn_hdlr= aurora->save_mysql.net.conn_hdlr; + 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]= mariadb_api->mysql_init(NULL); - } - aurora_copy_mysql(&mysql, aurora->mysql[AURORA_REPLICA]); - aurora->active[AURORA_REPLICA]= 1; + aurora->mysql[AURORA_REPLICA]= mysql; 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; + if (!aurora->mysql[AURORA_PRIMARY]) + aurora->mysql[AURORA_PRIMARY]= mysql; + else + aurora_close_internal(mysql); continue; break; default: - mariadb_api->mysql_close(&mysql); + aurora_close_internal(mysql); return 0; break; } } + else + aurora_close_internal(mysql); valid_instances= aurora_get_valid_instances(aurora, instance); } return 0; @@ -488,99 +471,79 @@ my_bool aurora_find_primary(AURORA *aurora) { unsigned int i; AURORA_INSTANCE *instance= NULL; - MYSQL mysql; + MYSQL *mysql; my_bool check_primary= 1; + /* We try to find a primary: + * by looking 1st if a replica connect provided primary_id already + * by walking through instances */ + if (!aurora->num_instances) return 0; - mariadb_api->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++) { + mysql= mariadb_api->mysql_init(NULL); + mysql->options= aurora->save_mysql.options; + if (check_primary && aurora->primary_id[0]) { if ((instance= aurora_get_primary_id_instance(aurora)) && - aurora_connect_instance(aurora, instance, &mysql) && + aurora_connect_instance(aurora, instance, mysql) && instance->type == AURORA_PRIMARY) { - aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]); - aurora->active[AURORA_PRIMARY]= 1; + aurora->primary_id[0]= 0; + aurora->mysql[AURORA_PRIMARY]= mysql; 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) + else if (aurora->instance[i].type != AURORA_UNAVAILABLE) { - if (aurora_connect_instance(aurora, &aurora->instance[i], &mysql) + 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; + aurora->mysql[AURORA_PRIMARY]= mysql; return 1; } } + aurora_close_internal(mysql); } 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; - mariadb_api->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; + MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr; if (!mariadb_api) mariadb_api= mysql->methods->api; - if ((aurora= (AURORA *)hdlr->data)) - { - aurora_refresh_blacklist(aurora); - if (aurora->mysql[aurora->last_instance_type]->net.pvio) - { - mysql->methods->set_error(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0); - return NULL; - } - is_reconnect= 1; - } - else + /* we call aurora_connect either from mysql_real_connect or from mysql_reconnect, + * so make sure in case of reconnect we don't allocate aurora twice */ + if (!(aurora= (AURORA *)save_hdlr->data)) { if (!(aurora= (AURORA *)calloc(1, sizeof(AURORA)))) { mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); return NULL; } + aurora->save_mysql= *mysql; - mysql->net.conn_hdlr->data= (void *)aurora; - - aurora->mysql[AURORA_PRIMARY]= mysql; + save_hdlr->data= (void *)aurora; if (aurora_parse_url(host, aurora)) { goto error; } + /* store login credentials for connect/reconnect */ if (user) aurora->username= strdup(user); if (passwd) @@ -589,56 +552,35 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch 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) + /* we look for replica first: + if it's a primary we don't need to call find_aurora_primary + if it's a replica we can obtain primary_id */ + if (!aurora->mysql[AURORA_REPLICA]) { - 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; - } + if (!aurora_find_replica(aurora)) + aurora->mysql[AURORA_REPLICA]= NULL; else - aurora->pvio[AURORA_REPLICA]= NULL; + aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= save_hdlr; } - if (!aurora->active[AURORA_PRIMARY]) + if (!aurora->mysql[AURORA_PRIMARY]) { - if (aurora_find_primary(aurora)) - { - aurora->active[AURORA_PRIMARY]= 1; - aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio; - } + if (!aurora_find_primary(aurora)) + aurora->mysql[AURORA_PRIMARY]= NULL; else - aurora->pvio[AURORA_PRIMARY]= NULL; + aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= save_hdlr; } - if (!aurora->pvio[AURORA_PRIMARY] && !aurora->pvio[AURORA_REPLICA]) + if (!aurora->mysql[AURORA_PRIMARY] && !aurora->mysql[AURORA_REPLICA]) goto error; - aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); - ENABLE_AURORA(mysql); + if (aurora->mysql[AURORA_PRIMARY]) + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + else + aurora_switch_connection(mysql, aurora, AURORA_REPLICA); + mysql->net.conn_hdlr= save_hdlr; return mysql; error: aurora_close_memory(aurora); @@ -650,28 +592,53 @@ error: my_bool aurora_reconnect(MYSQL *mysql) { AURORA *aurora; - MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; - my_bool rc= 1; + MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr; + int i; - aurora= (AURORA *)hdlr->data; + /* We can't determine if a new primary was promotoed, or if + * line just dropped - we will close both primary and replica + * connection and establish a new connection via + * aurora_connect */ - DISABLE_AURORA(mysql); - switch (aurora->last_instance_type) + aurora= (AURORA *)save_hdlr->data; + + /* removed blacklisted instances */ + for (i=0; i < aurora->num_instances; i++) + aurora->instance[i].type= AURORA_UNKNOWN; + + if (aurora->mysql[AURORA_PRIMARY]->thread_id == mysql->thread_id) { - case AURORA_REPLICA: - if (!(rc= mariadb_api->mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) - aurora_switch_connection(mysql, aurora, AURORA_REPLICA); - break; - case AURORA_PRIMARY: - if (!(rc= mariadb_api->mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) - aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); - break; - default: - /* todo: error message */ - break; + /* don't send COM_QUIT */ + aurora->mysql[AURORA_PRIMARY]->net.pvio= NULL; + aurora_close_internal(aurora->mysql[AURORA_PRIMARY]); + aurora->mysql[AURORA_PRIMARY]= NULL; + aurora_close_internal(aurora->mysql[AURORA_REPLICA]); + aurora->mysql[AURORA_REPLICA]= NULL; } - ENABLE_AURORA(mysql); - return rc; + else if (aurora->mysql[AURORA_REPLICA]->thread_id == mysql->thread_id) + { + /* don't send COM_QUIT */ + aurora->mysql[AURORA_REPLICA]->net.pvio= NULL; + aurora_close_internal(aurora->mysql[AURORA_REPLICA]); + aurora->mysql[AURORA_REPLICA]= NULL; + aurora_close_internal(aurora->mysql[AURORA_PRIMARY]); + aurora->mysql[AURORA_PRIMARY]= NULL; + } + + /* unset connections, so we can connect to primary and replica again */ + aurora->mysql[AURORA_PRIMARY]= aurora->mysql[AURORA_REPLICA]= NULL; + + if (aurora_connect(mysql, NULL, NULL, NULL, NULL, 0, NULL, 0)) + { + if (aurora->mysql[AURORA_PRIMARY]) + *mysql= *aurora->mysql[AURORA_PRIMARY]; + return 0; + } + if (aurora->mysql[AURORA_REPLICA]) + *mysql= *aurora->mysql[AURORA_REPLICA]; + else + *mysql= aurora->save_mysql; + return 1; } /* }}} */ @@ -679,41 +646,34 @@ my_bool aurora_reconnect(MYSQL *mysql) void aurora_close(MYSQL *mysql) { MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; - AURORA *aurora= (AURORA *)hdlr->data; + AURORA *aurora; + int i; - if (!aurora->pvio[AURORA_PRIMARY] && !aurora->pvio[AURORA_REPLICA]) - { + if (!hdlr || !hdlr->data) return; - } + + aurora= (AURORA *)hdlr->data; + *mysql= aurora->save_mysql; - aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + if (!aurora->mysql[AURORA_PRIMARY] && !aurora->mysql[AURORA_REPLICA]) + goto end; - /* if the connection is not active yet, just return */ - if (!aurora->active[1]) - return; - - if (aurora->mysql[AURORA_REPLICA]) + for (i=0; i < 2; i++) { - /* 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 mariadb_api->mysql_close() */ - aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; + if (aurora->mysql[i]) + { + /* Make sure that connection wasn't closed before, e.g. after disconnect */ + if (mysql->thread_id == aurora->mysql[i]->thread_id && !mysql->net.pvio) + aurora->mysql[i]->net.pvio= 0; - mariadb_api->mysql_close(aurora->mysql[AURORA_REPLICA]); + aurora_close_internal(aurora->mysql[i]); + aurora->mysql[i]= NULL; + } } - - 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]; - - mariadb_api->mysql_close(aurora->mysql[AURORA_PRIMARY]); - } - /* free information */ +end: aurora_close_memory(aurora); + mysql->net.conn_hdlr= hdlr; } /* }}} */ @@ -756,7 +716,8 @@ my_bool is_replica_stmt(MYSQL *mysql, const char *buffer) 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; + MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr; + AURORA *aurora= (AURORA *)save_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)) @@ -764,54 +725,43 @@ int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *ar if (command != COM_INIT_DB) { aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); - return 0; + goto end; } } 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) + if (aurora->mysql[AURORA_REPLICA] && mysql->thread_id == aurora->mysql[AURORA_PRIMARY]->thread_id) { - aurora_switch_connection(mysql, aurora, AURORA_REPLICA); - DISABLE_AURORA(mysql); + aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; mariadb_api->mysql_select_db(aurora->mysql[AURORA_REPLICA], arg); - ENABLE_AURORA(mysql); - aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= mysql->net.conn_hdlr; } break; case COM_QUERY: case COM_STMT_PREPARE: - if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA) + if (aurora->mysql[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->mysql[AURORA_REPLICA] && aurora->mysql[AURORA_REPLICA]->stmts && + is_replica_stmt(aurora->mysql[AURORA_REPLICA], arg)) { - if (aurora->last_instance_type != AURORA_REPLICA) - aurora_switch_connection(mysql, aurora, AURORA_REPLICA); + aurora_switch_connection(mysql, aurora, AURORA_REPLICA); } else { - if (aurora->last_instance_type != AURORA_PRIMARY) - aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); + aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); } default: aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); break; } +end: + mysql->net.conn_hdlr= save_hdlr; return 0; } /* }}} */ - -/* {{{ int aurora_set_options() */ -int aurora_set_options(MYSQL *mysql, enum mysql_option option, void *arg) -{ - switch(option) { - default: - return -1; - } -} -/* }}} */ diff --git a/plugins/connection/replication.c b/plugins/connection/replication.c index 9b4d1865..6bb74cef 100644 --- a/plugins/connection/replication.c +++ b/plugins/connection/replication.c @@ -202,8 +202,8 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char goto error; /* try to connect to master */ - if (!(mysql->methods->db_connect(mysql, data->host[MARIADB_MASTER], user, passwd, db, - data->port[MARIADB_MASTER] ? data->port[MARIADB_MASTER] : port, unix_socket, clientflag))) + if (!(mariadb_api->mysql_real_connect(mysql, data->host[MARIADB_MASTER], user, passwd, db, + data->port[MARIADB_MASTER] ? data->port[MARIADB_MASTER] : port, unix_socket, clientflag))) goto error; data->pvio[MARIADB_MASTER]= mysql->net.pvio; diff --git a/unittest/libmariadb/basic-t.c b/unittest/libmariadb/basic-t.c index 02dcc294..ff4fc547 100644 --- a/unittest/libmariadb/basic-t.c +++ b/unittest/libmariadb/basic-t.c @@ -35,11 +35,11 @@ static int test_conc75(MYSQL *my) int rc; MYSQL *mysql; int i; + my_bool reconnect= 1; mysql= mysql_init(NULL); - - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS); rc= mysql_query(mysql, "DROP TABLE IF EXISTS a"); @@ -55,7 +55,7 @@ static int test_conc75(MYSQL *my) { ulong thread_id= mysql_thread_id(mysql); /* force reconnect */ - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); diag("killing connection"); mysql_kill(my, thread_id); sleep(2); @@ -700,6 +700,7 @@ static int test_reconnect_maxpackage(MYSQL *my) MYSQL_RES *res; MYSQL_ROW row; char *query; + my_bool reconnect= 1; SKIP_CONNECTION_HANDLER; mysql= mysql_init(NULL); @@ -707,7 +708,7 @@ static int test_reconnect_maxpackage(MYSQL *my) FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); rc= mysql_query(mysql, "SELECT @@max_allowed_packet"); check_mysql_rc(rc, mysql); @@ -753,12 +754,13 @@ static int test_compressed(MYSQL *my) int rc; MYSQL *mysql= mysql_init(NULL); MYSQL_RES *res; + my_bool reconnect= 1; mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1); FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); rc= mysql_query(mysql, "SHOW VARIABLES"); check_mysql_rc(rc, mysql); diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 0d81b6c7..fe1f220b 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -455,16 +455,21 @@ static int test_opt_reconnect(MYSQL *mysql) { my_bool my_true= TRUE; int rc; + my_bool reconnect; + + printf("true: %d\n", TRUE); mysql= mysql_init(NULL); FAIL_IF(!mysql, "not enough memory"); - FAIL_UNLESS(mysql->reconnect == 0, "reconnect != 0"); + mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 0, "reconnect != 0"); rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, &my_true); check_mysql_rc(rc, mysql); - FAIL_UNLESS(mysql->reconnect == 1, "reconnect != 1"); + mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 1, "reconnect != 1"); if (!(mysql_real_connect(mysql, hostname, username, password, schema, port, @@ -475,14 +480,16 @@ static int test_opt_reconnect(MYSQL *mysql) return FAIL; } - FAIL_UNLESS(mysql->reconnect == 1, "reconnect != 1"); + mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 1, "reconnect != 1"); mysql_close(mysql); mysql= mysql_init(NULL); FAIL_IF(!mysql, "not enough memory"); - FAIL_UNLESS(mysql->reconnect == 0, "reconnect != 0"); + mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 0, "reconnect != 0"); if (!(mysql_real_connect(mysql, hostname, username, password, schema, port, @@ -493,7 +500,8 @@ static int test_opt_reconnect(MYSQL *mysql) return FAIL; } - FAIL_UNLESS(mysql->reconnect == 0, "reconnect != 0"); + mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 0, "reconnect != 0"); mysql_close(mysql); return OK; @@ -538,16 +546,19 @@ static int test_reconnect(MYSQL *mysql) my_bool my_true= TRUE; MYSQL *mysql1; int rc; + my_bool reconnect; mysql1= mysql_init(NULL); FAIL_IF(!mysql1, "not enough memory"); - FAIL_UNLESS(mysql1->reconnect == 0, "reconnect != 0"); + mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 0, "reconnect != 0"); rc= mysql_options(mysql1, MYSQL_OPT_RECONNECT, &my_true); check_mysql_rc(rc, mysql1); - FAIL_UNLESS(mysql1->reconnect == 1, "reconnect != 1"); + mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 1, "reconnect != 1"); if (!(mysql_real_connect(mysql1, hostname, username, password, schema, port, @@ -558,7 +569,8 @@ static int test_reconnect(MYSQL *mysql) return FAIL; } - FAIL_UNLESS(mysql1->reconnect == 1, "reconnect != 1"); + mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 1, "reconnect != 1"); diag("Thread_id before kill: %lu", mysql_thread_id(mysql1)); mysql_kill(mysql, mysql_thread_id(mysql1)); @@ -570,7 +582,8 @@ static int test_reconnect(MYSQL *mysql) check_mysql_rc(rc, mysql1); diag("Thread_id after kill: %lu", mysql_thread_id(mysql1)); - FAIL_UNLESS(mysql1->reconnect == 1, "reconnect != 1"); + mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect); + FAIL_UNLESS(reconnect == 1, "reconnect != 1"); mysql_close(mysql1); return OK; } @@ -647,8 +660,10 @@ int test_connection_timeout(MYSQL *my) static int test_conc118(MYSQL *mysql) { int rc; + my_bool reconnect= 1; + + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); - mysql->reconnect= 1; mysql->options.unused_1= 1; rc= mysql_kill(mysql, mysql_thread_id(mysql)); @@ -745,9 +760,10 @@ static int test_bind_address(MYSQL *my) static int test_get_options(MYSQL *my) { MYSQL *mysql= mysql_init(NULL); - int options_int[]= {MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_LOCAL_INFILE, - MYSQL_OPT_RECONNECT, MYSQL_OPT_PROTOCOL, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT, 0}; - my_bool options_bool[]= {MYSQL_OPT_COMPRESS, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_SECURE_AUTH, + int options_int[]= {MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_LOCAL_INFILE, + MYSQL_OPT_PROTOCOL, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT, 0}; + my_bool options_bool[]= {MYSQL_OPT_RECONNECT, MYSQL_REPORT_DATA_TRUNCATION, + MYSQL_OPT_COMPRESS, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_SECURE_AUTH, #ifdef _WIN32 MYSQL_OPT_NAMED_PIPE, #endif diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index 13dd8697..bb179128 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -957,6 +957,7 @@ static int test_conc_114(MYSQL *mysql) /* run with valgrind */ static int test_conc117(MYSQL *mysql) { + my_bool reconnect= 1; MYSQL *my= mysql_init(NULL); FAIL_IF(!mysql_real_connect(my, hostname, username, password, schema, port, socketname, 0), mysql_error(my)); @@ -964,7 +965,7 @@ static int test_conc117(MYSQL *mysql) mysql_kill(my, mysql_thread_id(my)); sleep(5); - my->reconnect= 1; + mysql_options(my, MYSQL_OPT_RECONNECT, &reconnect); mysql_query(my, "SET @a:=1"); mysql_close(my); diff --git a/unittest/libmariadb/my_test.h b/unittest/libmariadb/my_test.h index e0db2beb..c756318f 100644 --- a/unittest/libmariadb/my_test.h +++ b/unittest/libmariadb/my_test.h @@ -374,7 +374,6 @@ int check_variable(MYSQL *mysql, char *variable, char *value) */ MYSQL *test_connect(struct my_tests_st *test) { MYSQL *mysql; - char query[255]; int i= 0; int timeout= 10; int truncation_report= 1; @@ -401,7 +400,7 @@ MYSQL *test_connect(struct my_tests_st *test) { } } if (!(mysql_real_connect(mysql, hostname, username, password, - NULL, port, socketname, (test) ? test->connect_flags:0))) + schema, port, socketname, (test) ? test->connect_flags:0))) { diag("Couldn't establish connection to server %s. Error (%d): %s", hostname, mysql_errno(mysql), mysql_error(mysql)); @@ -409,24 +408,6 @@ MYSQL *test_connect(struct my_tests_st *test) { return(NULL); } - /* change database or create if it doesn't exist */ - if (mysql_select_db(mysql, schema)) { - diag("Error number: %d", mysql_errno(mysql)); - - if(mysql_errno(mysql) == 1049) { - sprintf(query, "CREATE DATABASE %s", schema); - if (mysql_query(mysql, query)) { - diag("Can't create database %s", schema); - mysql_close(mysql); - return NULL; - } - } else { - diag("Error (%d): %s", mysql_errno(mysql), mysql_error(mysql)); - mysql_close(mysql); - return NULL; - } - } - return(mysql); } @@ -526,6 +507,7 @@ void run_tests(struct my_tests_st *test) { } } if (mysql_default) { + diag("close default"); mysql_close(mysql_default); } mysql_server_end(); diff --git a/unittest/libmariadb/ps.c b/unittest/libmariadb/ps.c index add7a493..d6545a21 100644 --- a/unittest/libmariadb/ps.c +++ b/unittest/libmariadb/ps.c @@ -52,12 +52,13 @@ static int test_conc83(MYSQL *my) MYSQL_STMT *stmt; int rc; MYSQL *mysql= mysql_init(NULL); + my_bool reconnect= 1; char *query= "SELECT 1,2,3 FROM DUAL"; stmt= mysql_stmt_init(mysql); - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); FAIL_IF(!(mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0)), "mysql_real_connect failed"); @@ -4544,9 +4545,9 @@ static int test_stmt_close(MYSQL *mysql) unsigned int count; int rc; char query[MAX_TEST_QUERY_LENGTH]; + my_bool reconnect= 1; - - mysql->reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); /* set AUTOCOMMIT to ON*/ mysql_autocommit(mysql, TRUE); @@ -4644,9 +4645,8 @@ static int test_new_date(MYSQL *mysql) MYSQL_BIND bind[1]; int rc; char buffer[50]; - - - mysql->reconnect= 1; + my_bool reconnect= 1; + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); /* set AUTOCOMMIT to ON*/ mysql_autocommit(mysql, TRUE); diff --git a/unittest/libmariadb/result.c b/unittest/libmariadb/result.c index 885b70bc..69293b1b 100644 --- a/unittest/libmariadb/result.c +++ b/unittest/libmariadb/result.c @@ -932,6 +932,7 @@ select 1;\ DROP TABLE IF EXISTS test_multi_tab"; uint count, exp_value; uint rows[]= {0, 0, 2, 1, 3, 2, 2, 1, 1, 0, 0, 1, 0}; + my_bool reconnect= 1; /* First test that we get an error for multi statements @@ -950,7 +951,7 @@ DROP TABLE IF EXISTS test_multi_tab"; mysql_close(mysql); mysql= mysql_local; - mysql_local->reconnect= 1; + mysql_options(mysql_local, MYSQL_OPT_RECONNECT, &reconnect); rc= mysql_query(mysql_local, query); check_mysql_rc(rc, mysql); diff --git a/unittest/libmariadb/t_aurora.c b/unittest/libmariadb/t_aurora.c index 4336a3c5..0b9c0241 100644 --- a/unittest/libmariadb/t_aurora.c +++ b/unittest/libmariadb/t_aurora.c @@ -4,12 +4,20 @@ #include "my_test.h" #include "ma_pvio.h" -static int aurora1(MYSQL *mysql) +static int aurora1(MYSQL *my) { int rc; my_bool read_only= 1; - const char *primary, *schema; + const char *primary, *my_schema; MYSQL_RES *res; + MYSQL *mysql= mysql_init(NULL); + + if (!mysql_real_connect(mysql, hostname, username, password, schema, port, NULL, 0)) + { + diag("Error: %s", mysql_error(mysql)); + mysql_close(mysql); + return FAIL; + } rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); check_mysql_rc(rc, mysql); @@ -38,8 +46,10 @@ static int aurora1(MYSQL *mysql) diag("Num_rows: %d", mysql_num_rows(res)); mysql_free_result(res); - mariadb_get_infov(mysql, MARIADB_CONNECTION_SCHEMA, &schema); - diag("db: %s", schema); + mariadb_get_infov(mysql, MARIADB_CONNECTION_SCHEMA, &my_schema); + diag("db: %s", my_schema); + + mysql_close(mysql); return OK; } @@ -58,16 +68,86 @@ static int test_wrong_user(MYSQL *my) return OK; } +static int test_reconnect(MYSQL *my) +{ + MYSQL *mysql= mysql_init(NULL); + MYSQL_RES *res; + my_bool read_only= 1; + int rc; + my_bool reconnect= 1; + const char *aurora_host; + + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); + + if (!mysql_real_connect(mysql, hostname, username, password, schema, port, NULL, 0)) + { + diag("Error: %s", mysql_error(mysql)); + mysql_close(mysql); + return FAIL; + } + + mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &aurora_host); + diag("host: %s", aurora_host); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS tx01"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE tx01 (a int)"); + check_mysql_rc(rc, mysql); + + /* we force cluster restart and promoting new primary: + * we wait for 50 seconds - however there is no guarantee that + * cluster was restarted already - so this test might fail */ + system("/usr/local/aws/bin/aws rds failover-db-cluster --db-cluster-identifier instance-1-cluster"); + + sleep(50); + diag("Q1"); + rc= mysql_query(mysql, "INSERT INTO tx01 VALUES (1)"); + if (!rc) + diag("error expected!"); + diag("Error: %s", mysql_error(mysql)); + + diag("Q2"); + rc= mysql_query(mysql, "INSERT INTO tx01 VALUES (1)"); + if (rc) + { + diag("no error expected!"); + diag("Error: %s", mysql_error(mysql)); + diag("host: %s", mysql->host); + } + else + { + mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &aurora_host); + diag("host: %s", aurora_host); + } + + mysql_options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, &read_only); + + rc= mysql_query(mysql, "SELECT * from tx01"); + check_mysql_rc(rc, mysql); + + if ((res= mysql_store_result(mysql))) + { + diag("num_rows: %d", mysql_num_rows(res)); + mysql_free_result(res); + } + + mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &aurora_host); + diag("host: %s", aurora_host); + + mysql_close(mysql); + return OK; +} + struct my_tests_st my_tests[] = { - {"aurora1", aurora1, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {"aurora1", aurora1, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_wrong_user", test_wrong_user, TEST_CONNECTION_NONE, 0, NULL, NULL}, + {"test_reconnect", test_reconnect, TEST_CONNECTION_NONE, 0, NULL, NULL}, {NULL, NULL, 0, 0, NULL, NULL} }; int main(int argc, char **argv) { - mysql_library_init(0,0,NULL); if (argc > 1)