diff options
author | unknown <acurtis/antony@xiphis.org/ltamd64.xiphis.org> | 2007-03-24 01:18:19 -0700 |
---|---|---|
committer | unknown <acurtis/antony@xiphis.org/ltamd64.xiphis.org> | 2007-03-24 01:18:19 -0700 |
commit | 99c5c28c3cc9eb417f4ca12f606c5abcf6b02a19 (patch) | |
tree | f23ab8b69e00d10ca3921fb21bb3cc8904908d19 /sql | |
parent | cb5b56c8efc1752d6768547a6f0517455cdbe7e2 (diff) | |
download | mariadb-git-99c5c28c3cc9eb417f4ca12f606c5abcf6b02a19.tar.gz |
BUG#26257 New Federated Server Functionality Doesn't support differently named tables
* Modified Federated memory allocation to use MEM_ROOT
* Modified sql_servers and federated to allocate share connection
parameters to use MEM_ROOT
* Modified Federated to allow tablename in addition to server name
* Implicit flushing of tables using altered/dropped server name
* Added tests to prove new functionality works
Contributors to this patch: Patrick Galbraith, Antony Curtis
mysql-test/r/federated_server.result:
BUG #26257 New Federated Server Functionality Doesn't support differently named tables
New test results
mysql-test/t/federated_server.test:
BUG #26257 New Federated Server Functionality Doesn't support differently named tables
New test which ensures that one can use the new 'create server'
functionality and have tables point to the correct table, using CONNECTION='server',
CONNECTION="server/tablename" and CONNECTION="mysql://...url"
sql/mysql_priv.h:
BUG #26257 New Federated Server Functionality Doesn't support differently named tables
new function: close_cached_connection_tables()
sql/sql_base.cc:
BUG #26257 New Federated Server Functionality Doesn't support differently named tables
new function: close_cached_connection_tables()
closes all open tables which match connection string
provides functionality to allow flushing of altered/dropped server names.
sql/sql_servers.cc:
BUG #26257 New Federated Server Functionality Doesn't support differently named tables
* Added function clone_server() to allocate a new server for use by
get_server_by_name() when creating a federated table
* Now using MEM_ROOT allocation (mark and sweep) to account for meta
data parameters being allocated properly, particularly with regards to
to SERVER object. Also cleans up code allocating share.
* Tables using the old definition of server name are now flushed on successful
execution of ALTER/DROP SERVER.
style: fixed some line-wrapping
sql/sql_servers.h:
BUG #26257 New Federated Server Functionality Doesn't support differently named tables
* change in prototype to get_server_by_name()
caller can now provide mem_root which strings will be copied in to.
storage/federated/ha_federated.cc:
BUG #26257 New Federated Server Functionality Doesn't support differently named tables
* Simplified share and share member memory allocaton to use MEM_ROOT
* Modified parse_url to parse table names along with server names
storage/federated/ha_federated.h:
BUG #26257 New Federated Server Functionality Doesn't support differently named tables
* Added MEM_ROOT share member
Diffstat (limited to 'sql')
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/sql_base.cc | 66 | ||||
-rw-r--r-- | sql/sql_servers.cc | 110 | ||||
-rw-r--r-- | sql/sql_servers.h | 3 |
4 files changed, 168 insertions, 14 deletions
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index efcbdf968bf..2b1b310e67e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1430,6 +1430,9 @@ void close_open_tables_and_downgrade(ALTER_PARTITION_PARAM_TYPE *lpt); void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table); bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables, bool have_lock = FALSE); +bool close_cached_connection_tables(THD *thd, bool wait_for_refresh, + LEX_STRING *connect_string, + bool have_lock = FALSE); void copy_field_from_tmp_record(Field *field,int offset); bool fill_record(THD *thd, Field **field, List<Item> &values, bool ignore_errors); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e764c498059..44becc77865 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -858,6 +858,7 @@ void free_io_cache(TABLE *table) DBUG_VOID_RETURN; } + /* Close all tables which aren't in use by any thread @@ -970,6 +971,71 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, /* + Close all tables which match specified connection string or + if specified string is NULL, then any table with a connection string. +*/ + +bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh, + LEX_STRING *connection, bool have_lock) +{ + uint idx; + TABLE_LIST tmp, *tables= NULL; + bool result= FALSE; + DBUG_ENTER("close_cached_connections"); + DBUG_ASSERT(thd); + + bzero(&tmp, sizeof(TABLE_LIST)); + + if (!have_lock) + VOID(pthread_mutex_lock(&LOCK_open)); + + for (idx= 0; idx < table_def_cache.records; idx++) + { + TABLE_SHARE *share= (TABLE_SHARE *) hash_element(&table_def_cache, idx); + + /* Ignore if table is not open or does not have a connect_string */ + if (!share->connect_string.length || !share->ref_count) + continue; + + /* Compare the connection string */ + if (connection && + (connection->length > share->connect_string.length || + (connection->length < share->connect_string.length && + (share->connect_string.str[connection->length] != '/' && + share->connect_string.str[connection->length] != '\\')) || + strncasecmp(connection->str, share->connect_string.str, + connection->length))) + continue; + + /* close_cached_tables() only uses these elements */ + tmp.db= share->db.str; + tmp.table_name= share->table_name.str; + tmp.next_local= tables; + + tables= (TABLE_LIST *) memdup_root(thd->mem_root, (char*)&tmp, + sizeof(TABLE_LIST)); + } + + if (tables) + result= close_cached_tables(thd, FALSE, tables, TRUE); + + if (!have_lock) + VOID(pthread_mutex_unlock(&LOCK_open)); + + if (if_wait_for_refresh) + { + pthread_mutex_lock(&thd->mysys_var->mutex); + thd->mysys_var->current_mutex= 0; + thd->mysys_var->current_cond= 0; + thd->proc_info=0; + pthread_mutex_unlock(&thd->mysys_var->mutex); + } + + DBUG_RETURN(result); +} + + +/* Mark all tables in the list which were used by current substatement as free for reuse. diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index 9b01a1b6889..71e141b0514 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -16,6 +16,21 @@ /* The servers are saved in the system table "servers" + + Currently, when the user performs an ALTER SERVER or a DROP SERVER + operation, it will cause all open tables which refer to the named + server connection to be flushed. This may cause some undesirable + behaviour with regard to currently running transactions. It is + expected that the DBA knows what s/he is doing when s/he performs + the ALTER SERVER or DROP SERVER operation. + + TODO: + It is desirable for us to implement a callback mechanism instead where + callbacks can be registered for specific server protocols. The callback + will be fired when such a server name has been created/altered/dropped + or when statistics are to be gathered such as how many actual connections. + Storage engines etc will be able to make use of the callback so that + currently running transactions etc will not be disrupted. */ #include "mysql_priv.h" @@ -557,6 +572,8 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options) int error; TABLE_LIST tables; TABLE *table; + LEX_STRING name= { server_options->server_name, + server_options->server_name_length }; DBUG_ENTER("drop_server"); DBUG_PRINT("info", ("server name server->server_name %s", @@ -578,14 +595,16 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options) goto end; } - error= delete_server_record(table, - server_options->server_name, - server_options->server_name_length); + error= delete_server_record(table, name.str, name.length); - /* - Perform a reload so we don't have a 'hole' in our mem_root - */ - servers_load(thd, &tables); + /* close the servers table before we call closed_cached_connection_tables */ + close_thread_tables(thd); + + if (close_cached_connection_tables(thd, TRUE, &name)) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, "Server connection in use"); + } end: rw_unlock(&THR_LOCK_servers); @@ -975,6 +994,8 @@ int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options) { int error= ER_FOREIGN_SERVER_DOESNT_EXIST; FOREIGN_SERVER *altered, *existing; + LEX_STRING name= { server_options->server_name, + server_options->server_name_length }; DBUG_ENTER("alter_server"); DBUG_PRINT("info", ("server_options->server_name %s", server_options->server_name)); @@ -982,8 +1003,8 @@ int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options) rw_wrlock(&THR_LOCK_servers); if (!(existing= (FOREIGN_SERVER *) hash_search(&servers_cache, - (byte*) server_options->server_name, - server_options->server_name_length))) + (byte*) name.str, + name.length))) goto end; altered= (FOREIGN_SERVER *)alloc_root(&mem, @@ -993,6 +1014,15 @@ int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options) error= update_server(thd, existing, altered); + /* close the servers table before we call closed_cached_connection_tables */ + close_thread_tables(thd); + + if (close_cached_connection_tables(thd, FALSE, &name)) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, "Server connection in use"); + } + end: DBUG_PRINT("info", ("error returned %d", error)); rw_unlock(&THR_LOCK_servers); @@ -1143,6 +1173,12 @@ void servers_free(bool end) DBUG_ENTER("servers_free"); if (!hash_inited(&servers_cache)) DBUG_VOID_RETURN; + if (!end) + { + free_root(&mem, MYF(MY_MARK_BLOCKS_FREE)); + my_hash_reset(&servers_cache); + DBUG_VOID_RETURN; + } rwlock_destroy(&THR_LOCK_servers); free_root(&mem,MYF(0)); hash_free(&servers_cache); @@ -1151,6 +1187,51 @@ void servers_free(bool end) /* + SYNOPSIS + + clone_server(MEM_ROOT *mem_root, FOREIGN_SERVER *orig, FOREIGN_SERVER *buff) + + Create a clone of FOREIGN_SERVER. If the supplied mem_root is of + thd->mem_root then the copy is automatically disposed at end of statement. + + NOTES + + ARGS + MEM_ROOT pointer (strings are copied into this mem root) + FOREIGN_SERVER pointer (made a copy of) + FOREIGN_SERVER buffer (if not-NULL, this pointer is returned) + + RETURN VALUE + FOREIGN_SEVER pointer (copy of one supplied FOREIGN_SERVER) +*/ + +static FOREIGN_SERVER *clone_server(MEM_ROOT *mem, const FOREIGN_SERVER *server, + FOREIGN_SERVER *buffer) +{ + DBUG_ENTER("sql_server.cc:clone_server"); + + if (!buffer) + buffer= (FOREIGN_SERVER *) alloc_root(mem, sizeof(FOREIGN_SERVER)); + + buffer->server_name= strmake_root(mem, server->server_name, + server->server_name_length); + buffer->port= server->port; + buffer->server_name_length= server->server_name_length; + + /* TODO: We need to examine which of these can really be NULL */ + buffer->db= server->db ? strdup_root(mem, server->db) : NULL; + buffer->scheme= server->scheme ? strdup_root(mem, server->scheme) : NULL; + buffer->username= server->username? strdup_root(mem, server->username): NULL; + buffer->password= server->password? strdup_root(mem, server->password): NULL; + buffer->socket= server->socket ? strdup_root(mem, server->socket) : NULL; + buffer->owner= server->owner ? strdup_root(mem, server->owner) : NULL; + buffer->host= server->host ? strdup_root(mem, server->host) : NULL; + + DBUG_RETURN(buffer); +} + + +/* SYNOPSIS get_server_by_name() @@ -1163,11 +1244,11 @@ void servers_free(bool end) */ -FOREIGN_SERVER *get_server_by_name(const char *server_name) +FOREIGN_SERVER *get_server_by_name(MEM_ROOT *mem, const char *server_name, + FOREIGN_SERVER *buff) { - ulong error_num=0; uint server_name_length; - FOREIGN_SERVER *server= 0; + FOREIGN_SERVER *server; DBUG_ENTER("get_server_by_name"); DBUG_PRINT("info", ("server_name %s", server_name)); @@ -1176,7 +1257,6 @@ FOREIGN_SERVER *get_server_by_name(const char *server_name) if (! server_name || !strlen(server_name)) { DBUG_PRINT("info", ("server_name not defined!")); - error_num= 1; DBUG_RETURN((FOREIGN_SERVER *)NULL); } @@ -1190,6 +1270,10 @@ FOREIGN_SERVER *get_server_by_name(const char *server_name) server_name, server_name_length)); server= (FOREIGN_SERVER *) NULL; } + /* otherwise, make copy of server */ + else + server= clone_server(mem, server, buff); + DBUG_PRINT("info", ("unlocking servers_cache")); rw_unlock(&THR_LOCK_servers); DBUG_RETURN(server); diff --git a/sql/sql_servers.h b/sql/sql_servers.h index 9618374dcab..63c691893d1 100644 --- a/sql/sql_servers.h +++ b/sql/sql_servers.h @@ -39,4 +39,5 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options); int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options); /* lookup functions */ -FOREIGN_SERVER *get_server_by_name(const char *server_name); +FOREIGN_SERVER *get_server_by_name(MEM_ROOT *mem, const char *server_name, + FOREIGN_SERVER *server_buffer); |