diff options
author | unknown <serg@janus.mylan> | 2006-09-05 23:59:16 +0200 |
---|---|---|
committer | unknown <serg@janus.mylan> | 2006-09-05 23:59:16 +0200 |
commit | 6e5c98ea76590dc6e7e4d93c363f8ed336346040 (patch) | |
tree | 36ebce9c6796e7b6f768399a1f8dbb8643f838f8 /sql/sql_plugin.cc | |
parent | b1e2cfce3d9817d8ac4105865df31b41a6526abe (diff) | |
download | mariadb-git-6e5c98ea76590dc6e7e4d93c363f8ed336346040.tar.gz |
plugin_foreach - don't hold the lock when calling the function
Diffstat (limited to 'sql/sql_plugin.cc')
-rw-r--r-- | sql/sql_plugin.cc | 58 |
1 files changed, 40 insertions, 18 deletions
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 9db7c743a40..8ed16d8af58 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -63,6 +63,8 @@ static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; static rw_lock_t THR_LOCK_plugin; static bool initialized= 0; +static int plugin_array_version=0; + /* prototypes */ my_bool plugin_register_builtin(struct st_mysql_plugin *plugin); void plugin_load(void); @@ -448,6 +450,7 @@ static my_bool plugin_add(const LEX_STRING *name, const LEX_STRING *dl, int repo tmp.state= PLUGIN_IS_UNINITIALIZED; if (! (tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) goto err; + plugin_array_version++; if (my_hash_insert(&plugin_hash[plugin->type], (byte*)tmp_plugin_ptr)) { tmp_plugin_ptr->state= PLUGIN_IS_FREED; @@ -504,6 +507,7 @@ static void plugin_del(const LEX_STRING *name) hash_delete(&plugin_hash[plugin->plugin->type], (byte*)plugin); plugin_dl_del(&plugin->plugin_dl->dl); plugin->state= PLUGIN_IS_FREED; + plugin_array_version++; } DBUG_VOID_RETURN; } @@ -639,7 +643,7 @@ static byte *get_hash_key(const byte *buff, uint *length, */ int plugin_init(int skip_dynamic_loading) { - int i; + uint i; struct st_mysql_plugin **builtins; struct st_mysql_plugin *plugin; DBUG_ENTER("plugin_init"); @@ -939,43 +943,61 @@ err: DBUG_RETURN(TRUE); } - my_bool plugin_foreach(THD *thd, plugin_foreach_func *func, int type, void *arg) { - uint idx; - struct st_plugin_int *plugin; + uint idx, total; + struct st_plugin_int *plugin, **plugins; + int version=plugin_array_version; DBUG_ENTER("plugin_foreach"); - rw_rdlock(&THR_LOCK_plugin); + rw_rdlock(&THR_LOCK_plugin); if (type == MYSQL_ANY_PLUGIN) { - for (idx= 0; idx < plugin_array.elements; idx++) + total=plugin_array.elements; + plugins=(struct st_plugin_int **)my_alloca(total*sizeof(*plugins)); + for (idx= 0; idx < total; idx++) { plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *); - - /* FREED records may have garbage pointers */ - if ((plugin->state != PLUGIN_IS_FREED) && - func(thd, plugin, arg)) - goto err; + if (plugin->state == PLUGIN_IS_FREED) + continue; + plugins[idx]= plugin; } } else { HASH *hash= &plugin_hash[type]; - for (idx= 0; idx < hash->records; idx++) + total=hash->records; + plugins=(struct st_plugin_int **)my_alloca(total*sizeof(*plugins)); + for (idx= 0; idx < total; idx++) { plugin= (struct st_plugin_int *) hash_element(hash, idx); - if ((plugin->state != PLUGIN_IS_FREED) && - (plugin->state != PLUGIN_IS_DELETED) && - func(thd, plugin, arg)) - goto err; + if (plugin->state == PLUGIN_IS_FREED) + continue; + plugins[idx]= plugin; } } - rw_unlock(&THR_LOCK_plugin); + + for (idx= 0; idx < total; idx++) + { + plugin= plugins[idx]; + if (unlikely(version != plugin_array_version)) + { + rw_rdlock(&THR_LOCK_plugin); + for (uint i=idx; i < total; i++) + if (plugins[i]->state == PLUGIN_IS_FREED) + plugins[i]=0; + rw_unlock(&THR_LOCK_plugin); + } + if (plugin && func(thd, plugin, arg)) + goto err; + } + + my_afree(plugins); DBUG_RETURN(FALSE); err: - rw_unlock(&THR_LOCK_plugin); + my_afree(plugins); DBUG_RETURN(TRUE); } + |