Below is the list of changes that have just been committed into a local
5.1 repository of acurtis. When acurtis does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2008-02-20 18:23:08-08:00, acurtis@stripped +6 -0
Bug#34409
"LOCK_plugin contention via... plugin_foreach()"
First commit draft for comments/review.
sql/log_event.cc@stripped, 2008-02-20 18:22:52-08:00, acurtis@stripped +4 -4
make use of new method THD::free_mem_root()
sql/sql_class.cc@stripped, 2008-02-20 18:22:52-08:00, acurtis@stripped +3 -1
initialize and cleanup new property THD::cached_plugin_list
sql/sql_class.h@stripped, 2008-02-20 18:22:52-08:00, acurtis@stripped +16 -0
new property THD::cached_plugin_list
new methods THD::free_mem_root() and THD::alloc_plugin_cache()
sql/sql_parse.cc@stripped, 2008-02-20 18:22:52-08:00, acurtis@stripped +2 -2
make use of new method THD::free_mem_root()
sql/sql_plugin.cc@stripped, 2008-02-20 18:22:52-08:00, acurtis@stripped +54 -0
new function plugin_unlock_cached() releases plugins stored on THD::cached_plugin_list
implement a 'fast-path' in function plugin_foreach_with_mask() to reduce contention
on the LOCK_plugin mutex.
for some other operations, it may be faster to iterate cached plugins list instead of
acquiring mutex and performing hash lookup.... perhaps try_lock may be used to detect
contention and fallback on iterating through cached list.
sql/sql_plugin.h@stripped, 2008-02-20 18:22:53-08:00, acurtis@stripped +1 -0
prototype for new function plugin_unlock_cached()
diff -Nrup a/sql/log_event.cc b/sql/log_event.cc
--- a/sql/log_event.cc 2008-02-05 05:51:57 -08:00
+++ b/sql/log_event.cc 2008-02-20 18:22:52 -08:00
@@ -2554,7 +2554,7 @@ end:
thd->first_successful_insert_id_in_prev_stmt_for_binlog= 0;
thd->first_successful_insert_id_in_prev_stmt= 0;
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
- free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ thd->free_mem_root(MYF(MY_KEEP_PREALLOC));
return thd->is_slave_error;
}
@@ -3963,10 +3963,10 @@ error:
rli->report(ERROR_LEVEL, sql_errno,"\
Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
err, (char*)table_name, print_slave_db_safe(remember_db));
- free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ thd->free_mem_root(MYF(MY_KEEP_PREALLOC));
return 1;
}
- free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ thd->free_mem_root(MYF(MY_KEEP_PREALLOC));
if (thd->is_fatal_error)
{
@@ -4888,7 +4888,7 @@ int User_var_log_event::do_apply_event(R
a column value, it could always have IMPLICIT derivation.
*/
e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0);
- free_root(thd->mem_root,0);
+ thd->free_mem_root(0);
return 0;
}
diff -Nrup a/sql/sql_class.cc b/sql/sql_class.cc
--- a/sql/sql_class.cc 2008-02-12 09:21:07 -08:00
+++ b/sql/sql_class.cc 2008-02-20 18:22:52 -08:00
@@ -500,7 +500,8 @@ THD::THD()
bootstrap(0),
derived_tables_processing(FALSE),
spcont(NULL),
- m_lip(NULL)
+ m_lip(NULL),
+ cached_plugin_list(NULL)
{
ulong tmp;
@@ -876,6 +877,7 @@ THD::~THD()
}
#endif
+ plugin_unlock_cached(this);
free_root(&main_mem_root, MYF(0));
DBUG_VOID_RETURN;
}
diff -Nrup a/sql/sql_class.h b/sql/sql_class.h
--- a/sql/sql_class.h 2008-01-31 07:31:51 -08:00
+++ b/sql/sql_class.h 2008-02-20 18:22:52 -08:00
@@ -1693,6 +1693,8 @@ public:
partition_info *work_part_info;
#endif
+ plugin_ref *cached_plugin_list;
+
THD();
~THD();
@@ -2107,6 +2109,20 @@ private:
tree itself is reused between executions and thus is stored elsewhere.
*/
MEM_ROOT main_mem_root;
+public:
+ void free_mem_root(myf MyFLAGS)
+ {
+ if (mem_root == &main_mem_root)
+ plugin_unlock_cached(this);
+ free_root(mem_root, MyFLAGS);
+ }
+ plugin_ref *alloc_plugin_cache(uint size)
+ {
+ DBUG_ASSERT(!cached_plugin_list);
+ return (cached_plugin_list= (plugin_ref*)
+ alloc_root(&main_mem_root,
+ (size + 1) * sizeof(plugin_ref)));
+ }
};
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc 2008-02-14 07:52:59 -08:00
+++ b/sql/sql_parse.cc 2008-02-20 18:22:52 -08:00
@@ -446,7 +446,7 @@ pthread_handler_t handle_bootstrap(void
if (bootstrap_error)
break;
- free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ thd->free_mem_root(MYF(MY_KEEP_PREALLOC));
#ifdef USING_TRANSACTIONS
free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC));
#endif
@@ -1506,7 +1506,7 @@ bool dispatch_command(enum enum_server_c
thread_running--;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory
- free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ thd->free_mem_root(MYF(MY_KEEP_PREALLOC));
DBUG_RETURN(error);
}
diff -Nrup a/sql/sql_plugin.cc b/sql/sql_plugin.cc
--- a/sql/sql_plugin.cc 2008-02-19 13:36:44 -08:00
+++ b/sql/sql_plugin.cc 2008-02-20 18:22:52 -08:00
@@ -989,6 +989,22 @@ void plugin_unlock_list(THD *thd, plugin
}
+void plugin_unlock_cached(THD *thd)
+{
+ plugin_ref *list= thd->cached_plugin_list;
+ DBUG_ENTER("plugin_unlock_cached");
+ thd->cached_plugin_list= NULL;
+ if (!list || !*list)
+ DBUG_VOID_RETURN;
+ pthread_mutex_lock(&LOCK_plugin);
+ while (*list)
+ intern_plugin_unlock(NULL, *list++);
+ reap_plugins();
+ pthread_mutex_unlock(&LOCK_plugin);
+ DBUG_VOID_RETURN;
+}
+
+
static int plugin_initialize(struct st_plugin_int *plugin)
{
DBUG_ENTER("plugin_initialize");
@@ -1758,6 +1774,44 @@ bool plugin_foreach_with_mask(THD *thd,
DBUG_RETURN(FALSE);
state_mask= ~state_mask; // do it only once
+
+ if (likely(thd && state_mask == ~(uint) PLUGIN_IS_READY))
+ {
+ plugin_ref *list;
+
+ if (unlikely(!thd->cached_plugin_list))
+ {
+ pthread_mutex_lock(&LOCK_plugin);
+ total= plugin_array.elements;
+ if ((list= thd->alloc_plugin_cache(total)))
+ {
+ for (idx= 0; idx < total; idx++)
+ {
+ if ((*list= my_intern_plugin_lock(NULL, plugin_int_to_ref(
+ *dynamic_element(&plugin_array, idx, struct st_plugin_int **)))))
+ list++;
+ }
+ *list= 0;
+ }
+ pthread_mutex_unlock(&LOCK_plugin);
+ }
+
+ if (likely(thd->cached_plugin_list != 0))
+ {
+ for (list= thd->cached_plugin_list; *list; list++)
+ {
+ if (plugin_state(*list) & state_mask)
+ continue;
+
+ if (type != MYSQL_ANY_PLUGIN && type != plugin_decl(*list)->type)
+ continue;
+
+ if (func(thd, *list, arg))
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+ }
+ }
pthread_mutex_lock(&LOCK_plugin);
total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements
diff -Nrup a/sql/sql_plugin.h b/sql/sql_plugin.h
--- a/sql/sql_plugin.h 2007-06-12 08:41:54 -07:00
+++ b/sql/sql_plugin.h 2008-02-20 18:22:53 -08:00
@@ -123,6 +123,7 @@ extern plugin_ref plugin_lock_by_name(TH
int type CALLER_INFO_PROTO);
extern void plugin_unlock(THD *thd, plugin_ref plugin);
extern void plugin_unlock_list(THD *thd, plugin_ref *list, uint count);
+extern void plugin_unlock_cached(THD *thd);
extern bool mysql_install_plugin(THD *thd, const LEX_STRING *name,
const LEX_STRING *dl);
extern bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name);