diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2009-09-08 00:50:10 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2009-09-08 00:50:10 +0400 |
commit | 29f0dcb56337a3e352ad7a70dcff6b25bb605325 (patch) | |
tree | 84935c21dc958724ae7dcbeeca0c0f08986fc430 /sql-common | |
parent | 915a624cbcb58a10a2cfb2e2e4fd5029191fa86a (diff) | |
parent | 8a2454f8e9fce648272577fcf8006ae6e6806cf9 (diff) | |
download | mariadb-git-29f0dcb56337a3e352ad7a70dcff6b25bb605325.tar.gz |
Merge MySQL->MariaDB
* Finished Monty and Jani's merge
* Some InnoDB tests still fail (because it's old xtradb code run against
newer testsuite). They are expected to go after mergning with the latest
xtradb.
Diffstat (limited to 'sql-common')
-rw-r--r-- | sql-common/client.c | 123 |
1 files changed, 88 insertions, 35 deletions
diff --git a/sql-common/client.c b/sql-common/client.c index eae3728020f..af44b6d2615 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -120,6 +120,7 @@ const char *def_shared_memory_base_name= default_shared_memory_base_name; static void mysql_close_free_options(MYSQL *mysql); static void mysql_close_free(MYSQL *mysql); +static void mysql_prune_stmt_list(MYSQL *mysql); #if !(defined(__WIN__) || defined(__NETWARE__)) static int wait_for_data(my_socket fd, uint timeout); @@ -476,6 +477,9 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) DWORD error_code = 0; DWORD event_access_rights= SYNCHRONIZE | EVENT_MODIFY_STATE; char *shared_memory_base_name = mysql->options.shared_memory_base_name; + static const char *name_prefixes[] = {"","Global\\"}; + const char *prefix; + int i; /* get enough space base-name + '_' + longest suffix we might ever send @@ -490,9 +494,18 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) shared_memory_base_name is unique value for each server unique_part is uniquel value for each object (events and file-mapping) */ - suffix_pos = strxmov(tmp, "Global\\", shared_memory_base_name, "_", NullS); - strmov(suffix_pos, "CONNECT_REQUEST"); - if (!(event_connect_request= OpenEvent(event_access_rights, FALSE, tmp))) + for (i = 0; i< array_elements(name_prefixes); i++) + { + prefix= name_prefixes[i]; + suffix_pos = strxmov(tmp, prefix , shared_memory_base_name, "_", NullS); + strmov(suffix_pos, "CONNECT_REQUEST"); + event_connect_request= OpenEvent(event_access_rights, FALSE, tmp); + if (event_connect_request) + { + break; + } + } + if (!event_connect_request) { error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR; goto err; @@ -544,7 +557,7 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) unique_part is uniquel value for each object (events and file-mapping) number_of_connection is number of connection between server and client */ - suffix_pos = strxmov(tmp, "Global\\", shared_memory_base_name, "_", connect_number_char, + suffix_pos = strxmov(tmp, prefix , shared_memory_base_name, "_", connect_number_char, "_", NullS); strmov(suffix_pos, "DATA"); if ((handle_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL) @@ -924,6 +937,7 @@ void end_server(MYSQL *mysql) vio_delete(mysql->net.vio); reset_sigpipe(mysql); mysql->net.vio= 0; /* Marker */ + mysql_prune_stmt_list(mysql); } net_end(&mysql->net); free_old_query(mysql); @@ -2018,6 +2032,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, (!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_TCP)) { + int status= -1; unix_socket=0; /* This is not used */ if (!port) port=mysql_port; @@ -2043,6 +2058,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ); bzero((char*) &sock_addr,sizeof(sock_addr)); sock_addr.sin_family = AF_INET; + sock_addr.sin_port = (ushort) htons((ushort) port); /* The server name may be a host name or IP address @@ -2051,28 +2067,46 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) { memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); + status= my_connect(sock, (struct sockaddr *) &sock_addr, + sizeof(sock_addr), mysql->options.connect_timeout); } else { - int tmp_errno; + int i, tmp_errno; struct hostent tmp_hostent,*hp; char buff2[GETHOSTBYNAME_BUFF_SIZE]; hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2), &tmp_errno); - if (!hp) + + /* + Don't attempt to connect to non IPv4 addresses as the client could + end up sending information to a unknown server. For example, a IPv6 + address might be returned from gethostbyname depending on options + set via the RES_OPTIONS environment variable. + */ + if (!hp || (hp->h_addrtype != AF_INET)) { my_gethostbyname_r_free(); set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate, ER(CR_UNKNOWN_HOST), host, tmp_errno); goto error; } - memcpy(&sock_addr.sin_addr, hp->h_addr, - min(sizeof(sock_addr.sin_addr), (size_t) hp->h_length)); + + for (i= 0; status && hp->h_addr_list[i]; i++) + { + IF_DBUG(char ipaddr[18];) + memcpy(&sock_addr.sin_addr, hp->h_addr_list[i], + min(sizeof(sock_addr.sin_addr), (size_t) hp->h_length)); + DBUG_PRINT("info",("Trying %s...", + (my_inet_ntoa(sock_addr.sin_addr, ipaddr), ipaddr))); + status= my_connect(sock, (struct sockaddr *) &sock_addr, + sizeof(sock_addr), mysql->options.connect_timeout); + } + my_gethostbyname_r_free(); } - sock_addr.sin_port = (ushort) htons((ushort) port); - if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), - mysql->options.connect_timeout)) + + if (status) { DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno, host)); @@ -2531,30 +2565,9 @@ my_bool mysql_reconnect(MYSQL *mysql) tmp_mysql.reconnect= 1; tmp_mysql.free_me= mysql->free_me; - /* - For each stmt in mysql->stmts, move it to tmp_mysql if it is - in state MYSQL_STMT_INIT_DONE, otherwise close it. - */ - { - LIST *element= mysql->stmts; - for (; element; element= element->next) - { - MYSQL_STMT *stmt= (MYSQL_STMT *) element->data; - if (stmt->state != MYSQL_STMT_INIT_DONE) - { - stmt->mysql= 0; - stmt->last_errno= CR_SERVER_LOST; - strmov(stmt->last_error, ER(CR_SERVER_LOST)); - strmov(stmt->sqlstate, unknown_sqlstate); - } - else - { - tmp_mysql.stmts= list_add(tmp_mysql.stmts, &stmt->list); - } - /* No need to call list_delete for statement here */ - } - mysql->stmts= NULL; - } + /* Move prepared statements (if any) over to the new mysql object */ + tmp_mysql.stmts= mysql->stmts; + mysql->stmts= 0; /* Don't free options as these are now used in tmp_mysql */ bzero((char*) &mysql->options,sizeof(mysql->options)); @@ -2644,6 +2657,46 @@ static void mysql_close_free(MYSQL *mysql) } +/** + For use when the connection to the server has been lost (in which case + the server has discarded all information about prepared statements + associated with the connection). + + Mark all statements in mysql->stmts by setting stmt->mysql= 0 if the + statement has transitioned beyond the MYSQL_STMT_INIT_DONE state, and + unlink the statement from the mysql->stmts list. + + The remaining pruned list of statements (if any) is kept in mysql->stmts. + + @param mysql pointer to the MYSQL object + + @return none +*/ +static void mysql_prune_stmt_list(MYSQL *mysql) +{ + LIST *element= mysql->stmts; + LIST *pruned_list= 0; + + for (; element; element= element->next) + { + MYSQL_STMT *stmt= (MYSQL_STMT *) element->data; + if (stmt->state != MYSQL_STMT_INIT_DONE) + { + stmt->mysql= 0; + stmt->last_errno= CR_SERVER_LOST; + strmov(stmt->last_error, ER(CR_SERVER_LOST)); + strmov(stmt->sqlstate, unknown_sqlstate); + } + else + { + pruned_list= list_add(pruned_list, element); + } + } + + mysql->stmts= pruned_list; +} + + /* Clear connection pointer of every statement: this is necessary to give error on attempt to use a prepared statement of closed |