From 4dff0296f402ff4fa6ee69e0411b8136eb5cd816 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Wed, 27 Oct 2010 20:29:09 +0200 Subject: [PATCH 01/62] Added more wait states for THD wait service --- include/mysql/plugin_audit.h.pp | 12 +++++++++--- include/mysql/plugin_ftparser.h.pp | 12 +++++++++--- include/mysql/service_thd_wait.h | 12 +++++++++--- sql/item_func.cc | 6 ++++++ sql/lock.cc | 12 ++++++++++++ sql/mdl.cc | 6 ++++++ sql/scheduler.cc | 2 +- storage/innobase/srv/srv0srv.c | 4 ++-- 8 files changed, 54 insertions(+), 12 deletions(-) diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index b48cbca2e87..0011dd8c41c 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -33,10 +33,16 @@ MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str, int allocate_lex_string); #include typedef enum _thd_wait_type_e { - THD_WAIT_MUTEX= 1, + THD_WAIT_SLEEP= 1, THD_WAIT_DISKIO= 2, - THD_WAIT_ROW_TABLE_LOCK= 3, - THD_WAIT_GLOBAL_LOCK= 4 + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_LAST= 10 } thd_wait_type; extern struct thd_wait_service_st { void (*thd_wait_begin_func)(void*, thd_wait_type); diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index 2c2c1adbf88..003449ecf1c 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -33,10 +33,16 @@ MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str, int allocate_lex_string); #include typedef enum _thd_wait_type_e { - THD_WAIT_MUTEX= 1, + THD_WAIT_SLEEP= 1, THD_WAIT_DISKIO= 2, - THD_WAIT_ROW_TABLE_LOCK= 3, - THD_WAIT_GLOBAL_LOCK= 4 + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_LAST= 10 } thd_wait_type; extern struct thd_wait_service_st { void (*thd_wait_begin_func)(void*, thd_wait_type); diff --git a/include/mysql/service_thd_wait.h b/include/mysql/service_thd_wait.h index 2a8f5e610a3..188aa0ab126 100644 --- a/include/mysql/service_thd_wait.h +++ b/include/mysql/service_thd_wait.h @@ -51,10 +51,16 @@ extern "C" { #endif typedef enum _thd_wait_type_e { - THD_WAIT_MUTEX= 1, + THD_WAIT_SLEEP= 1, THD_WAIT_DISKIO= 2, - THD_WAIT_ROW_TABLE_LOCK= 3, - THD_WAIT_GLOBAL_LOCK= 4 + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_LAST= 10 } thd_wait_type; extern struct thd_wait_service_st { diff --git a/sql/item_func.cc b/sql/item_func.cc index 6699b2820e6..e20cae16094 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -52,6 +52,8 @@ #include "sp.h" #include "set_var.h" #include "debug_sync.h" +#include +#include #ifdef NO_EMBEDDED_ACCESS_CHECKS #define sp_restore_security_context(A,B) while (0) {} @@ -3802,7 +3804,9 @@ longlong Item_func_get_lock::val_int() while (ull->locked && !thd->killed) { DBUG_PRINT("info", ("waiting on lock")); + thd_wait_begin(thd, THD_WAIT_USER_LOCK); error= interruptible_wait(thd, &ull->cond, &LOCK_user_locks, timeout); + thd_wait_end(thd); if (error == ETIMEDOUT || error == ETIME) { DBUG_PRINT("info", ("lock wait timeout")); @@ -4026,7 +4030,9 @@ longlong Item_func_sleep::val_int() error= 0; while (!thd->killed) { + thd_wait_begin(thd, THD_WAIT_SLEEP); error= interruptible_wait(thd, &cond, &LOCK_user_locks, timeout); + thd_wait_end(thd); if (error == ETIMEDOUT || error == ETIME) break; error= 0; diff --git a/sql/lock.cc b/sql/lock.cc index 0181a544824..5abf90b0047 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -82,6 +82,8 @@ #include "sql_acl.h" // SUPER_ACL #include #include +#include +#include /** @defgroup Locking Locking @@ -1019,7 +1021,11 @@ bool Global_read_lock::lock_global_read_lock(THD *thd) waiting_for_read_lock++; while (protect_against_global_read_lock && !thd->killed) + { + thd_wait_begin(thd, THD_WAIT_GLOBAL_LOCK); mysql_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock); + thd_wait_end(thd); + } waiting_for_read_lock--; if (thd->killed) { @@ -1187,7 +1193,9 @@ wait_if_global_read_lock(THD *thd, bool abort_on_refresh, thd->open_tables->s->version == refresh_version)) { DBUG_PRINT("signal", ("Waiting for COND_global_read_lock")); + thd_wait_begin(thd, THD_WAIT_GLOBAL_LOCK); mysql_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock); + thd_wait_end(thd); DBUG_PRINT("signal", ("Got COND_global_read_lock")); } if (thd->killed) @@ -1285,7 +1293,11 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) old_message= thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock, "Waiting for all running commits to finish"); while (protect_against_global_read_lock && !thd->killed) + { + thd_wait_begin(thd, THD_WAIT_GLOBAL_LOCK); mysql_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock); + thd_wait_end(thd); + } DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop", protect_against_global_read_lock--;); if ((error= test(thd->killed))) diff --git a/sql/mdl.cc b/sql/mdl.cc index aa7c2a4b7f2..924a005eec7 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -18,6 +18,8 @@ #include "debug_sync.h" #include #include +#include +#include #ifdef HAVE_PSI_INTERFACE static PSI_mutex_key key_MDL_map_mutex; @@ -991,8 +993,12 @@ MDL_wait::timed_wait(THD *thd, struct timespec *abs_timeout, while (!m_wait_status && !thd_killed(thd) && wait_result != ETIMEDOUT && wait_result != ETIME) + { + thd_wait_begin(thd, THD_WAIT_META_DATA_LOCK); wait_result= mysql_cond_timedwait(&m_COND_wait_status, &m_LOCK_wait_status, abs_timeout); + thd_wait_end(thd); + } if (m_wait_status == EMPTY) { diff --git a/sql/scheduler.cc b/sql/scheduler.cc index d61a452b99e..57e0f86f158 100644 --- a/sql/scheduler.cc +++ b/sql/scheduler.cc @@ -82,7 +82,7 @@ scheduler_functions *thread_scheduler= NULL; /**@{*/ static void scheduler_wait_begin(void) { MYSQL_CALLBACK(thread_scheduler, - thd_wait_begin, (current_thd, THD_WAIT_ROW_TABLE_LOCK)); + thd_wait_begin, (current_thd, THD_WAIT_TABLE_LOCK)); } static void scheduler_wait_end(void) { diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index b2da43c188b..f86f31ddfb0 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -1234,7 +1234,7 @@ retry: trx->op_info = "waiting in InnoDB queue"; - thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK); + thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK); os_event_wait(slot->event); thd_wait_end(trx->mysql_thd); @@ -1601,7 +1601,7 @@ srv_suspend_mysql_thread( /* Suspend this thread and wait for the event. */ - thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK); + thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_LOCK); os_event_wait(event); thd_wait_end(trx->mysql_thd); From dea3152c92344abac1b7a08a8765a802a5dcdce2 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Wed, 27 Oct 2010 20:35:01 +0200 Subject: [PATCH 02/62] Added more comments to THD wait service --- include/mysql/service_thd_wait.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/mysql/service_thd_wait.h b/include/mysql/service_thd_wait.h index 188aa0ab126..6f91c0acf43 100644 --- a/include/mysql/service_thd_wait.h +++ b/include/mysql/service_thd_wait.h @@ -50,6 +50,19 @@ extern "C" { #endif +/* + One should only report wait events that could potentially block for a + long time. A mutex wait is too short of an event to report. The reason + is that an event which is reported leads to a new thread starts + executing a query and this has a negative impact of usage of CPU caches + and thus the expected gain of starting a new thread must be higher than + the expected cost of lost performance due to starting a new thread. + + Good examples of events that should be reported are waiting for row locks + that could easily be for many milliseconds or even seconds and the same + holds true for global read locks, table locks and other meta data locks. + Another event of interest is going to sleep for an extended time. +*/ typedef enum _thd_wait_type_e { THD_WAIT_SLEEP= 1, THD_WAIT_DISKIO= 2, From 8fbf0e8817d7dc0f21e0ea33ed391e2260d7f463 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Thu, 28 Oct 2010 16:31:21 +0200 Subject: [PATCH 03/62] Added THD wait state for MASTER POS WAIT --- sql/rpl_rli.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index af9b452acd8..d02aadee701 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -26,6 +26,8 @@ #include "rpl_utility.h" #include "transaction.h" #include "sql_parse.h" // end_trans, ROLLBACK +#include +#include static int count_relay_log_space(Relay_log_info* rli); @@ -792,6 +794,7 @@ int Relay_log_info::wait_for_pos(THD* thd, String* log_name, We are going to mysql_cond_(timed)wait(); if the SQL thread stops it will wake us up. */ + thd_wait_begin(thd, THD_WAIT_BINLOG); if (timeout > 0) { /* @@ -809,6 +812,7 @@ int Relay_log_info::wait_for_pos(THD* thd, String* log_name, } else mysql_cond_wait(&data_cond, &data_lock); + thd_wait_end(thd); DBUG_PRINT("info",("Got signal of master update or timed out")); if (error == ETIMEDOUT || error == ETIME) { From c0854c3e1746f81abcba27505c7f8adc09ff2c45 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Thu, 28 Oct 2010 18:27:25 +0200 Subject: [PATCH 04/62] Added reporting of fsync to THD wait interface --- include/my_sys.h | 2 ++ include/mysql/plugin_audit.h.pp | 3 ++- include/mysql/plugin_ftparser.h.pp | 3 ++- include/mysql/service_thd_wait.h | 3 ++- mysys/my_sync.c | 19 +++++++++++++++++++ sql/scheduler.cc | 18 +++++++++++++++--- 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index 95689535be5..d3bde89e177 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -633,6 +633,8 @@ extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags); extern int my_fclose(FILE *fd,myf MyFlags); extern File my_fileno(FILE *fd); extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); +void thr_set_sync_wait_callback(void (*before_sync)(void), + void (*after_sync)(void)); extern int my_sync(File fd, myf my_flags); extern int my_sync_dir(const char *dir_name, myf my_flags); extern int my_sync_dir_by_file(const char *file_name, myf my_flags); diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index 0011dd8c41c..7268fd1c6fa 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -42,7 +42,8 @@ typedef enum _thd_wait_type_e { THD_WAIT_USER_LOCK= 7, THD_WAIT_BINLOG= 8, THD_WAIT_GROUP_COMMIT= 9, - THD_WAIT_LAST= 10 + THD_WAIT_SYNC= 10, + THD_WAIT_LAST= 11 } thd_wait_type; extern struct thd_wait_service_st { void (*thd_wait_begin_func)(void*, thd_wait_type); diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index 003449ecf1c..f3ca2070e60 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -42,7 +42,8 @@ typedef enum _thd_wait_type_e { THD_WAIT_USER_LOCK= 7, THD_WAIT_BINLOG= 8, THD_WAIT_GROUP_COMMIT= 9, - THD_WAIT_LAST= 10 + THD_WAIT_SYNC= 10, + THD_WAIT_LAST= 11 } thd_wait_type; extern struct thd_wait_service_st { void (*thd_wait_begin_func)(void*, thd_wait_type); diff --git a/include/mysql/service_thd_wait.h b/include/mysql/service_thd_wait.h index 6f91c0acf43..a7ce2dbf501 100644 --- a/include/mysql/service_thd_wait.h +++ b/include/mysql/service_thd_wait.h @@ -73,7 +73,8 @@ typedef enum _thd_wait_type_e { THD_WAIT_USER_LOCK= 7, THD_WAIT_BINLOG= 8, THD_WAIT_GROUP_COMMIT= 9, - THD_WAIT_LAST= 10 + THD_WAIT_SYNC= 10, + THD_WAIT_LAST= 11 } thd_wait_type; extern struct thd_wait_service_st { diff --git a/mysys/my_sync.c b/mysys/my_sync.c index bc050922ffc..6a4e26a6542 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -17,6 +17,16 @@ #include "mysys_err.h" #include +static void (*before_sync_wait)(void)= 0; +static void (*after_sync_wait)(void)= 0; + +void thr_set_sync_wait_callback(void (*before_wait)(void), + void (*after_wait)(void)) +{ + before_sync_wait= before_wait; + after_sync_wait= after_wait; +} + /* Sync data in file to disk @@ -48,6 +58,8 @@ int my_sync(File fd, myf my_flags) do { + if (before_sync_wait) + (*before_sync_wait)(); #if defined(F_FULLFSYNC) /* In Mac OS X >= 10.3 this call is safer than fsync() (it forces the @@ -75,6 +87,8 @@ int my_sync(File fd, myf my_flags) int er= errno; if (!(my_errno= er)) my_errno= -1; /* Unknown error */ + if (after_sync_wait) + (*after_sync_wait)(); if ((my_flags & MY_IGNORE_BADFD) && (er == EBADF || er == EINVAL || er == EROFS)) { @@ -84,6 +98,11 @@ int my_sync(File fd, myf my_flags) else if (my_flags & MY_WME) my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno); } + else + { + if (after_sync_wait) + (*after_sync_wait)(); + } DBUG_RETURN(res); } /* my_sync */ diff --git a/sql/scheduler.cc b/sql/scheduler.cc index 57e0f86f158..4c56e360e0e 100644 --- a/sql/scheduler.cc +++ b/sql/scheduler.cc @@ -80,12 +80,21 @@ scheduler_functions *thread_scheduler= NULL; */ /**@{*/ -static void scheduler_wait_begin(void) { +static void scheduler_wait_lock_begin(void) { MYSQL_CALLBACK(thread_scheduler, thd_wait_begin, (current_thd, THD_WAIT_TABLE_LOCK)); } -static void scheduler_wait_end(void) { +static void scheduler_wait_lock_end(void) { + MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd)); +} + +static void scheduler_wait_sync_begin(void) { + MYSQL_CALLBACK(thread_scheduler, + thd_wait_begin, (current_thd, THD_WAIT_TABLE_LOCK)); +} + +static void scheduler_wait_sync_end(void) { MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd)); } /**@}*/ @@ -98,7 +107,10 @@ static void scheduler_wait_end(void) { mysqld.cc, so this init function will always be called. */ static void scheduler_init() { - thr_set_lock_wait_callback(scheduler_wait_begin, scheduler_wait_end); + thr_set_lock_wait_callback(scheduler_wait_lock_begin, + scheduler_wait_lock_end); + thr_set_sync_wait_callback(scheduler_wait_sync_begin, + scheduler_wait_sync_end); } /* From 6a7151903f2338bb2f89fdc48f2ff21e085f4bae Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Tue, 9 Nov 2010 16:33:40 +0100 Subject: [PATCH 05/62] Added support in DEBUG_SYNC framework for actions when THD object isn't actively executed, that is when mysys_var == NULL --- sql/debug_sync.cc | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index 74e5b2c70f3..1390bac8352 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -1746,10 +1746,15 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) mutex and cond. This would prohibit the use of DEBUG_SYNC between other places of enter_cond() and exit_cond(). */ - old_mutex= thd->mysys_var->current_mutex; - old_cond= thd->mysys_var->current_cond; - thd->mysys_var->current_mutex= &debug_sync_global.ds_mutex; - thd->mysys_var->current_cond= &debug_sync_global.ds_cond; + if (thd->mysys_var) + { + old_mutex= thd->mysys_var->current_mutex; + old_cond= thd->mysys_var->current_cond; + thd->mysys_var->current_mutex= &debug_sync_global.ds_mutex; + thd->mysys_var->current_cond= &debug_sync_global.ds_cond; + } + else + old_mutex= NULL; set_timespec(abstime, action->timeout); DBUG_EXECUTE("debug_sync_exec", { @@ -1804,11 +1809,16 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) is locked. (See comment in THD::exit_cond().) */ mysql_mutex_unlock(&debug_sync_global.ds_mutex); - mysql_mutex_lock(&thd->mysys_var->mutex); - thd->mysys_var->current_mutex= old_mutex; - thd->mysys_var->current_cond= old_cond; - thd_proc_info(thd, old_proc_info); - mysql_mutex_unlock(&thd->mysys_var->mutex); + if (old_mutex) + { + mysql_mutex_lock(&thd->mysys_var->mutex); + thd->mysys_var->current_mutex= old_mutex; + thd->mysys_var->current_cond= old_cond; + thd_proc_info(thd, old_proc_info); + mysql_mutex_unlock(&thd->mysys_var->mutex); + } + else + thd_proc_info(thd, old_proc_info); } else { From d0182e61a189fada37c19281c69fd4824e6092a8 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 19 Nov 2010 14:43:13 +0100 Subject: [PATCH 06/62] Disabled a number of tests when using thread pool --- mysql-test/suite/perfschema/t/no_threads.test | 1 + mysql-test/suite/perfschema/t/one_thread_per_con.test | 1 + mysql-test/suite/sys_vars/t/all_vars.test | 1 + mysql-test/t/information_schema.test | 3 +++ mysql-test/t/information_schema_db.test | 3 +++ mysql-test/t/mysqlshow.test | 2 ++ mysql-test/t/no-threads.test | 1 + 7 files changed, 12 insertions(+) diff --git a/mysql-test/suite/perfschema/t/no_threads.test b/mysql-test/suite/perfschema/t/no_threads.test index 9254535bf1f..2f4f4476362 100644 --- a/mysql-test/suite/perfschema/t/no_threads.test +++ b/mysql-test/suite/perfschema/t/no_threads.test @@ -17,6 +17,7 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +--source include/not_threadpool.inc # Setup : in this main thread diff --git a/mysql-test/suite/perfschema/t/one_thread_per_con.test b/mysql-test/suite/perfschema/t/one_thread_per_con.test index 7d0daffe228..eaca92875dd 100644 --- a/mysql-test/suite/perfschema/t/one_thread_per_con.test +++ b/mysql-test/suite/perfschema/t/one_thread_per_con.test @@ -17,6 +17,7 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +--source include/not_threadpool.inc # Setup diff --git a/mysql-test/suite/sys_vars/t/all_vars.test b/mysql-test/suite/sys_vars/t/all_vars.test index e9e7e16687a..d8a57b22fe3 100644 --- a/mysql-test/suite/sys_vars/t/all_vars.test +++ b/mysql-test/suite/sys_vars/t/all_vars.test @@ -14,6 +14,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --source include/not_embedded.inc +--source include/not_threadpool.inc # 2010-01-28 OBN Added support to load 'innodb' and 'semisync' if possible. # As we need to have there variables loaded if the components exist but do diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index f5fab966bdd..e9b569cd440 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1,6 +1,9 @@ # This test uses grants, which can't get tested for embedded server -- source include/not_embedded.inc +#Don't run this test when thread_pool active +--source include/not_threadpool.inc + # check that CSV engine was compiled in, as the result of the test depends # on the presence of the log tables (which are CSV-based). --source include/have_csv.inc diff --git a/mysql-test/t/information_schema_db.test b/mysql-test/t/information_schema_db.test index 7326f33b113..f1aebfa4bed 100644 --- a/mysql-test/t/information_schema_db.test +++ b/mysql-test/t/information_schema_db.test @@ -2,6 +2,9 @@ # in the embedded server by default). So skip the test in embedded-server mode. -- source include/not_embedded.inc +#Don't run this test when thread_pool active +--source include/not_threadpool.inc + -- source include/testdb_only.inc --disable_warnings diff --git a/mysql-test/t/mysqlshow.test b/mysql-test/t/mysqlshow.test index 66ec8e22ab1..515e2bcf325 100644 --- a/mysql-test/t/mysqlshow.test +++ b/mysql-test/t/mysqlshow.test @@ -2,6 +2,8 @@ -- source include/not_embedded.inc # Test lists tables in Information_schema, and InnoDB adds some -- source include/have_innodb.inc +# Don't test when thread_pool active +--source include/not_threadpool.inc --disable_warnings DROP TABLE IF EXISTS t1,t2,test1,test2; diff --git a/mysql-test/t/no-threads.test b/mysql-test/t/no-threads.test index fd8365e5678..c2b326897f8 100644 --- a/mysql-test/t/no-threads.test +++ b/mysql-test/t/no-threads.test @@ -1,3 +1,4 @@ +--source include/not_threadpool.inc # # Test the --thread-handler=no-threads option # From 7dae4282d4d5ec2ec8d17f600e87918e0a0aea00 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Wed, 12 Jan 2011 14:31:17 +0100 Subject: [PATCH 07/62] BUG#59392, removed thread local storage use in MySQL Threads by storing ibuf_inside indicator in MTR object instead --- include/mysql/plugin_auth.h.pp | 13 ++- storage/innobase/btr/btr0cur.c | 2 +- storage/innobase/buf/buf0buf.c | 16 ++-- storage/innobase/buf/buf0rea.c | 7 +- storage/innobase/fil/fil0fil.c | 2 - storage/innobase/handler/ha_innodb.cc | 1 - storage/innobase/ibuf/ibuf0ibuf.c | 113 ++++++++------------------ storage/innobase/include/buf0rea.h | 4 +- storage/innobase/include/ibuf0ibuf.h | 13 ++- storage/innobase/include/mtr0mtr.h | 2 + storage/innobase/include/mtr0mtr.ic | 1 + storage/innobase/include/thr0loc.h | 8 -- storage/innobase/mtr/mtr0mtr.c | 1 + storage/innobase/thr/thr0loc.c | 20 ----- 14 files changed, 75 insertions(+), 128 deletions(-) diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index 88588d03b9e..aed764ddb51 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -33,10 +33,17 @@ MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str, int allocate_lex_string); #include typedef enum _thd_wait_type_e { - THD_WAIT_MUTEX= 1, + THD_WAIT_SLEEP= 1, THD_WAIT_DISKIO= 2, - THD_WAIT_ROW_TABLE_LOCK= 3, - THD_WAIT_GLOBAL_LOCK= 4 + THD_WAIT_ROW_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4, + THD_WAIT_META_DATA_LOCK= 5, + THD_WAIT_TABLE_LOCK= 6, + THD_WAIT_USER_LOCK= 7, + THD_WAIT_BINLOG= 8, + THD_WAIT_GROUP_COMMIT= 9, + THD_WAIT_SYNC= 10, + THD_WAIT_LAST= 11 } thd_wait_type; extern struct thd_wait_service_st { void (*thd_wait_begin_func)(void*, thd_wait_type); diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index 50489ae4cc6..27f05da6f28 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/innobase/btr/btr0cur.c @@ -390,7 +390,7 @@ btr_cur_search_to_nth_level( ut_ad(level == 0 || mode == PAGE_CUR_LE); ut_ad(dict_index_check_search_tuple(index, tuple)); - ut_ad(!dict_index_is_ibuf(index) || ibuf_inside()); + ut_ad(!dict_index_is_ibuf(index) || ibuf_inside(mtr)); ut_ad(dtuple_check_typed(tuple)); #ifdef UNIV_DEBUG diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index b79b5634957..0fd518ac6a4 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -2314,9 +2314,6 @@ buf_page_get_zip( unsigned access_time; buf_pool_t* buf_pool = buf_pool_get(space, offset); -#ifndef UNIV_LOG_DEBUG - ut_ad(!ibuf_inside()); -#endif buf_pool->stat.n_page_gets++; for (;;) { @@ -2745,7 +2742,7 @@ buf_page_get_gen( ut_ad(zip_size == fil_space_get_zip_size(space)); ut_ad(ut_is_2pow(zip_size)); #ifndef UNIV_LOG_DEBUG - ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL)); + ut_ad(!ibuf_inside(mtr) || ibuf_page(space, zip_size, offset, NULL)); #endif buf_pool->stat.n_page_gets++; fold = buf_page_address_fold(space, offset); @@ -3114,7 +3111,7 @@ wait_until_unfixed: /* In the case of a first access, try to apply linear read-ahead */ - buf_read_ahead_linear(space, zip_size, offset); + buf_read_ahead_linear(space, zip_size, offset, mtr); } #ifdef UNIV_IBUF_COUNT_DEBUG @@ -3171,7 +3168,7 @@ buf_page_optimistic_get( access_time = buf_page_is_accessed(&block->page); buf_page_set_accessed_make_young(&block->page, access_time); - ut_ad(!ibuf_inside() + ut_ad(!ibuf_inside(mtr) || ibuf_page(buf_block_get_space(block), buf_block_get_zip_size(block), buf_block_get_page_no(block), NULL)); @@ -3227,7 +3224,8 @@ buf_page_optimistic_get( buf_read_ahead_linear(buf_block_get_space(block), buf_block_get_zip_size(block), - buf_block_get_page_no(block)); + buf_block_get_page_no(block), + mtr); } #ifdef UNIV_IBUF_COUNT_DEBUG @@ -3303,7 +3301,7 @@ buf_page_get_known_nowait( buf_pool_mutex_exit(buf_pool); } - ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD)); + ut_ad(!ibuf_inside(mtr) || (mode == BUF_KEEP_OLD)); if (rw_latch == RW_S_LATCH) { success = rw_lock_s_lock_nowait(&(block->lock), @@ -3568,9 +3566,9 @@ buf_page_init_for_read( /* It is a read-ahead within an ibuf routine */ ut_ad(!ibuf_bitmap_page(zip_size, offset)); - ut_ad(ibuf_inside()); mtr_start(&mtr); + ibuf_enter(&mtr); if (!recv_no_ibuf_operations && !ibuf_page(space, zip_size, offset, &mtr)) { diff --git a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c index 82b45172988..519724d0b9a 100644 --- a/storage/innobase/buf/buf0rea.c +++ b/storage/innobase/buf/buf0rea.c @@ -238,8 +238,10 @@ buf_read_ahead_linear( /*==================*/ ulint space, /*!< in: space id */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ - ulint offset) /*!< in: page number of a page; NOTE: the current thread + ulint offset, /*!< in: page number of a page; NOTE: the current thread must want access to this page (see NOTE 3 above) */ + mtr_t *mtr) /*!< in: mtr with knowledge if we're inside ibuf + routine */ { buf_pool_t* buf_pool = buf_pool_get(space, offset); ib_int64_t tablespace_version; @@ -429,7 +431,7 @@ buf_read_ahead_linear( /* If we got this far, read-ahead can be sensible: do it */ - if (ibuf_inside()) { + if (ibuf_inside(mtr)) { ibuf_mode = BUF_READ_IBUF_PAGES_ONLY; } else { ibuf_mode = BUF_READ_ANY_PAGE; @@ -520,7 +522,6 @@ buf_read_ibuf_merge_pages( { ulint i; - ut_ad(!ibuf_inside()); #ifdef UNIV_IBUF_DEBUG ut_a(n_stored < UNIV_PAGE_SIZE); #endif diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index cb4ccc005b5..7f1551b6bb7 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -4314,8 +4314,6 @@ fil_io( ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE) || !ibuf_bitmap_page(zip_size, block_offset) || sync || is_log); - ut_ad(!ibuf_inside() || is_log || (type == OS_FILE_WRITE) - || ibuf_page(space_id, zip_size, block_offset, NULL)); # endif /* UNIV_LOG_DEBUG */ if (sync) { mode = OS_AIO_SYNC; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 6cbf7234043..824f12b97b7 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3006,7 +3006,6 @@ innobase_close_connection( innobase_rollback_trx(trx); - thr_local_free(trx->mysql_thread_id); trx_free_for_mysql(trx); DBUG_RETURN(0); diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index ab42f1ad4f3..aab0084c214 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -324,37 +324,27 @@ still physically like the index page even if the index would have been dropped! So, there seems to be no problem. */ /******************************************************************//** -Sets the flag in the current OS thread local storage denoting that it is +Sets the flag in the current mini-transaction record indicating we're inside an insert buffer routine. */ -UNIV_INLINE +UNIV_INTERN void -ibuf_enter(void) +ibuf_enter( + mtr_t *mtr) /*!< in: mtr stores ibuf_inside info */ /*============*/ { - ibool* ptr; - - ptr = thr_local_get_in_ibuf_field(); - - ut_ad(*ptr == FALSE); - - *ptr = TRUE; + mtr->ibuf_inside = TRUE; } /******************************************************************//** -Sets the flag in the current OS thread local storage denoting that it is +Sets the flag in the current mini-transaction record indicating we're exiting an insert buffer routine. */ UNIV_INLINE void -ibuf_exit(void) +ibuf_exit( + mtr_t *mtr) /*!< in: mtr stores ibuf_inside info */ /*===========*/ { - ibool* ptr; - - ptr = thr_local_get_in_ibuf_field(); - - ut_ad(*ptr == TRUE); - - *ptr = FALSE; + mtr->ibuf_inside = FALSE; } /******************************************************************//** @@ -366,10 +356,11 @@ that are executing an insert buffer routine. @return TRUE if inside an insert buffer routine */ UNIV_INTERN ibool -ibuf_inside(void) +ibuf_inside( + mtr_t *mtr) /*!< in: mtr stores ibuf_inside info */ /*=============*/ { - return(*thr_local_get_in_ibuf_field()); + return(mtr->ibuf_inside); } /******************************************************************//** @@ -383,7 +374,7 @@ ibuf_header_page_get( { buf_block_t* block; - ut_ad(!ibuf_inside()); + ut_ad(!ibuf_inside(mtr)); block = buf_page_get( IBUF_SPACE_ID, 0, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr); @@ -404,7 +395,7 @@ ibuf_tree_root_get( buf_block_t* block; page_t* root; - ut_ad(ibuf_inside()); + ut_ad(ibuf_inside(mtr)); ut_ad(mutex_own(&ibuf_mutex)); mtr_x_lock(dict_index_get_lock(ibuf->index), mtr); @@ -547,7 +538,7 @@ ibuf_init_at_db_start(void) fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, &n_used, &mtr); - ibuf_enter(); + ibuf_enter(&mtr); ut_ad(n_used >= 2); @@ -570,8 +561,6 @@ ibuf_init_at_db_start(void) ibuf->empty = (page_get_n_recs(root) == 0); mtr_commit(&mtr); - ibuf_exit(); - heap = mem_heap_create(450); /* Use old-style record format for the insert buffer. */ @@ -1164,7 +1153,6 @@ ibuf_rec_get_page_no( const byte* field; ulint len; - ut_ad(ibuf_inside()); ut_ad(rec_get_n_fields_old(rec) > 2); field = rec_get_nth_field_old(rec, 1, &len); @@ -1199,7 +1187,6 @@ ibuf_rec_get_space( const byte* field; ulint len; - ut_ad(ibuf_inside()); ut_ad(rec_get_n_fields_old(rec) > 2); field = rec_get_nth_field_old(rec, 1, &len); @@ -1244,7 +1231,6 @@ ibuf_rec_get_info( ulint info_len_local; ulint counter_local; - ut_ad(ibuf_inside()); fields = rec_get_n_fields_old(rec); ut_a(fields > 4); @@ -1304,7 +1290,6 @@ ibuf_rec_get_op_type( { ulint len; - ut_ad(ibuf_inside()); ut_ad(rec_get_n_fields_old(rec) > 2); (void) rec_get_nth_field_old(rec, 1, &len); @@ -1677,7 +1662,6 @@ ibuf_rec_get_volume( ibool pre_4_1; ulint comp; - ut_ad(ibuf_inside()); ut_ad(rec_get_n_fields_old(ibuf_rec) > 2); data = rec_get_nth_field_old(ibuf_rec, 1, &len); @@ -2094,7 +2078,7 @@ ibuf_add_free_page(void) page = buf_block_get_frame(block); } - ibuf_enter(); + ibuf_enter(&mtr); mutex_enter(&ibuf_mutex); @@ -2124,8 +2108,6 @@ ibuf_add_free_page(void) mtr_commit(&mtr); - ibuf_exit(); - return(TRUE); } @@ -2156,7 +2138,7 @@ ibuf_remove_free_page(void) header_page = ibuf_header_page_get(&mtr); /* Prevent pessimistic inserts to insert buffer trees for a while */ - ibuf_enter(); + ibuf_enter(&mtr); mutex_enter(&ibuf_pessimistic_insert_mutex); mutex_enter(&ibuf_mutex); @@ -2165,14 +2147,14 @@ ibuf_remove_free_page(void) mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_pessimistic_insert_mutex); - ibuf_exit(); - mtr_commit(&mtr); return; } + ibuf_exit(&mtr); mtr_start(&mtr2); + ibuf_enter(&mtr2); root = ibuf_tree_root_get(&mtr2); @@ -2187,8 +2169,6 @@ ibuf_remove_free_page(void) mtr_commit(&mtr2); - ibuf_exit(); - /* Since pessimistic inserts were prevented, we know that the page is still in the free list. NOTE that also deletes may take pages from the free list, but they take them from the start, and @@ -2202,7 +2182,7 @@ ibuf_remove_free_page(void) buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no); #endif - ibuf_enter(); + ibuf_enter(&mtr); mutex_enter(&ibuf_mutex); @@ -2248,8 +2228,6 @@ ibuf_remove_free_page(void) buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no); #endif mtr_commit(&mtr); - - ibuf_exit(); } /***********************************************************************//** @@ -2271,8 +2249,6 @@ ibuf_free_excess_pages(void) ut_ad(rw_lock_get_x_lock_count( fil_space_get_latch(IBUF_SPACE_ID, NULL)) == 1); - ut_ad(!ibuf_inside()); - /* NOTE: We require that the thread did not own the latch before, because then we know that we can obey the correct latching order for ibuf latches */ @@ -2498,7 +2474,6 @@ ibuf_contract_ext( mtr_t mtr; *n_pages = 0; - ut_ad(!ibuf_inside()); /* We perform a dirty read of ibuf->empty, without latching the insert buffer root page. We trust this dirty read except @@ -2529,7 +2504,7 @@ ibuf_is_empty: mtr_start(&mtr); - ibuf_enter(); + ibuf_enter(&mtr); /* Open a cursor to a randomly chosen leaf of the tree, at a random position within the leaf */ @@ -2548,8 +2523,6 @@ ibuf_is_empty: ut_ad(page_get_page_no(btr_pcur_get_page(&pcur)) == FSP_IBUF_TREE_ROOT_PAGE_NO); - ibuf_exit(); - mtr_commit(&mtr); btr_pcur_close(&pcur); @@ -2563,8 +2536,6 @@ ibuf_is_empty: fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n", sync, *n_pages, sum_sizes); #endif - ibuf_exit(); - mtr_commit(&mtr); btr_pcur_close(&pcur); @@ -2725,7 +2696,6 @@ ibuf_get_volume_buffered_count( const byte* types; ulint n_fields = rec_get_n_fields_old(rec); - ut_ad(ibuf_inside()); ut_ad(n_fields > 4); n_fields -= 4; @@ -3039,9 +3009,8 @@ ibuf_update_max_tablespace_id(void) ut_a(!dict_table_is_comp(ibuf->index->table)); - ibuf_enter(); - mtr_start(&mtr); + ibuf_enter(&mtr); btr_pcur_open_at_index_side( FALSE, ibuf->index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr); @@ -3065,7 +3034,6 @@ ibuf_update_max_tablespace_id(void) } mtr_commit(&mtr); - ibuf_exit(); /* printf("Maximum space id in insert buffer %lu\n", max_space_id); */ @@ -3089,7 +3057,6 @@ ibuf_get_entry_counter_low( const byte* field; ulint len; - ut_ad(ibuf_inside()); ut_ad(rec_get_n_fields_old(rec) > 2); field = rec_get_nth_field_old(rec, 1, &len); @@ -3374,7 +3341,6 @@ ibuf_insert_low( if (mode == BTR_MODIFY_TREE) { for (;;) { - ibuf_enter(); mutex_enter(&ibuf_pessimistic_insert_mutex); mutex_enter(&ibuf_mutex); @@ -3385,7 +3351,6 @@ ibuf_insert_low( mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_pessimistic_insert_mutex); - ibuf_exit(); if (UNIV_UNLIKELY(!ibuf_add_free_page())) { @@ -3393,11 +3358,12 @@ ibuf_insert_low( return(DB_STRONG_FAIL); } } + mtr_start(&mtr); } else { - ibuf_enter(); + mtr_start(&mtr); + ibuf_enter(&mtr); } - mtr_start(&mtr); btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr); ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index)); @@ -3453,6 +3419,7 @@ fail_exit: ut_a((buffered == 0) || ibuf_count_get(space, page_no)); #endif mtr_start(&bitmap_mtr); + bitmap_mtr.ibuf_inside = mtr.ibuf_inside; bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, &bitmap_mtr); @@ -3579,7 +3546,6 @@ func_exit: mtr_commit(&mtr); btr_pcur_close(&pcur); - ibuf_exit(); mem_heap_free(heap); @@ -3837,7 +3803,7 @@ ibuf_insert_to_index_page( page_t* page = buf_block_get_frame(block); rec_t* rec; - ut_ad(ibuf_inside()); + ut_ad(ibuf_inside(mtr)); ut_ad(dtuple_check_typed(entry)); ut_ad(!buf_block_align(page)->is_hashed); @@ -3984,7 +3950,7 @@ ibuf_set_del_mark( page_cur_t page_cur; ulint low_match; - ut_ad(ibuf_inside()); + ut_ad(ibuf_inside(mtr)); ut_ad(dtuple_check_typed(entry)); low_match = page_cur_search( @@ -4041,7 +4007,7 @@ ibuf_delete( page_cur_t page_cur; ulint low_match; - ut_ad(ibuf_inside()); + ut_ad(ibuf_inside(mtr)); ut_ad(dtuple_check_typed(entry)); low_match = page_cur_search( @@ -4183,7 +4149,7 @@ ibuf_delete_rec( page_t* root; ulint err; - ut_ad(ibuf_inside()); + ut_ad(ibuf_inside(mtr)); ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur))); ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no); ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space); @@ -4373,8 +4339,6 @@ ibuf_merge_or_delete_for_page( return; } - ibuf_enter(); - heap = mem_heap_create(512); if (!trx_sys_multiple_tablespace_format) { @@ -4405,6 +4369,7 @@ ibuf_merge_or_delete_for_page( ut_print_timestamp(stderr); mtr_start(&mtr); + ibuf_enter(&mtr); fputs(" InnoDB: Dump of the ibuf bitmap page:\n", stderr); @@ -4445,6 +4410,7 @@ ibuf_merge_or_delete_for_page( loop: mtr_start(&mtr); + ibuf_enter(&mtr); if (block) { ibool success; @@ -4551,6 +4517,7 @@ loop: btr_pcur_commit_specify_mtr(&pcur, &mtr); mtr_start(&mtr); + ibuf_enter(&mtr); success = buf_page_get_known_nowait( RW_X_LATCH, block, @@ -4649,8 +4616,6 @@ reset_bit: fil_decr_pending_ibuf_merges(space); } - ibuf_exit(); - #ifdef UNIV_IBUF_COUNT_DEBUG ut_a(ibuf_count_get(space, page_no) == 0); #endif @@ -4687,9 +4652,8 @@ ibuf_delete_for_discarded_space( memset(dops, 0, sizeof(dops)); loop: - ibuf_enter(); - mtr_start(&mtr); + ibuf_enter(&mtr); /* Position pcur in the insert buffer at the first entry for the space */ @@ -4725,8 +4689,6 @@ loop: /* Deletion was pessimistic and mtr was committed: we start from the beginning again */ - ibuf_exit(); - goto loop; } @@ -4734,8 +4696,6 @@ loop: mtr_commit(&mtr); btr_pcur_close(&pcur); - ibuf_exit(); - goto loop; } } @@ -4753,8 +4713,6 @@ leave_loop: mutex_exit(&ibuf_mutex); #endif /* HAVE_ATOMIC_BUILTINS */ - ibuf_exit(); - mem_heap_free(heap); } @@ -4770,8 +4728,8 @@ ibuf_is_empty(void) const page_t* root; mtr_t mtr; - ibuf_enter(); mtr_start(&mtr); + ibuf_enter(&mtr); mutex_enter(&ibuf_mutex); root = ibuf_tree_root_get(&mtr); @@ -4779,7 +4737,6 @@ ibuf_is_empty(void) is_empty = (page_get_n_recs(root) == 0); mtr_commit(&mtr); - ibuf_exit(); ut_a(is_empty == ibuf->empty); diff --git a/storage/innobase/include/buf0rea.h b/storage/innobase/include/buf0rea.h index 4a52f9dcd8d..6e1f832942a 100644 --- a/storage/innobase/include/buf0rea.h +++ b/storage/innobase/include/buf0rea.h @@ -28,6 +28,7 @@ Created 11/5/1995 Heikki Tuuri #include "univ.i" #include "buf0types.h" +#include "mtr0types.h" /********************************************************************//** High-level function which reads a page asynchronously from a file to the @@ -72,8 +73,9 @@ buf_read_ahead_linear( /*==================*/ ulint space, /*!< in: space id */ ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ - ulint offset);/*!< in: page number of a page; NOTE: the current thread + ulint offset, /*!< in: page number of a page; NOTE: the current thread must want access to this page (see NOTE 3 above) */ + mtr_t *mtr); /*!< in: mtr to get ibuf_inside indicator */ /********************************************************************//** Issues read requests for pages which the ibuf module wants to read in, in order to contract the insert buffer tree. Technically, this function is like diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index dd05bcb0608..66b06575b0d 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -218,7 +218,7 @@ ibuf_should_try( a secondary index when we decide */ /******************************************************************//** -Returns TRUE if the current OS thread is performing an insert buffer +Returns TRUE if the current MTR is performing an insert buffer routine. For instance, a read-ahead of non-ibuf pages is forbidden by threads @@ -226,7 +226,16 @@ that are executing an insert buffer routine. @return TRUE if inside an insert buffer routine */ UNIV_INTERN ibool -ibuf_inside(void); +ibuf_inside( + mtr_t* mtr);/*!< in: ibuf_inside stored on mtr */ +/*=============*/ +/***********************************************************************//** +Sets ibuf_inside indicator on current MTR. +*/ +UNIV_INTERN +void +ibuf_enter( + mtr_t* mtr);/*!< in: ibuf_inside stored on mtr */ /*=============*/ /***********************************************************************//** Checks if a page address is an ibuf bitmap page (level 3 page) address. diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 8abca093548..2aaad3322c3 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -378,6 +378,8 @@ struct mtr_struct{ #endif dyn_array_t memo; /*!< memo stack for locks etc. */ dyn_array_t log; /*!< mini-transaction log */ + ibool ibuf_inside; + /* TRUE if inside ibuf changes */ ibool modifications; /* TRUE if the mtr made modifications to buffer pool pages */ diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic index 18f8e87b3cf..fd72b3b75e6 100644 --- a/storage/innobase/include/mtr0mtr.ic +++ b/storage/innobase/include/mtr0mtr.ic @@ -44,6 +44,7 @@ mtr_start( mtr->log_mode = MTR_LOG_ALL; mtr->modifications = FALSE; + mtr->ibuf_inside = FALSE; mtr->n_log_recs = 0; ut_d(mtr->state = MTR_ACTIVE); diff --git a/storage/innobase/include/thr0loc.h b/storage/innobase/include/thr0loc.h index b7eb29f2ed0..14da8bffdd7 100644 --- a/storage/innobase/include/thr0loc.h +++ b/storage/innobase/include/thr0loc.h @@ -74,14 +74,6 @@ thr_local_set_slot_no( /*==================*/ os_thread_id_t id, /*!< in: thread id of the thread */ ulint slot_no);/*!< in: slot number */ -/*******************************************************************//** -Returns pointer to the 'in_ibuf' field within the current thread local -storage. -@return pointer to the in_ibuf field */ -UNIV_INTERN -ibool* -thr_local_get_in_ibuf_field(void); -/*=============================*/ #ifndef UNIV_NONINL #include "thr0loc.ic" diff --git a/storage/innobase/mtr/mtr0mtr.c b/storage/innobase/mtr/mtr0mtr.c index 74d04a22b86..0b2100319c2 100644 --- a/storage/innobase/mtr/mtr0mtr.c +++ b/storage/innobase/mtr/mtr0mtr.c @@ -267,6 +267,7 @@ mtr_commit( ut_d(mtr->state = MTR_COMMITTED); dyn_array_free(&(mtr->memo)); dyn_array_free(&(mtr->log)); + mtr->ibuf_inside = FALSE; } #ifndef UNIV_HOTBACKUP diff --git a/storage/innobase/thr/thr0loc.c b/storage/innobase/thr/thr0loc.c index 2bd3e4b1c43..b7364afa166 100644 --- a/storage/innobase/thr/thr0loc.c +++ b/storage/innobase/thr/thr0loc.c @@ -174,26 +174,6 @@ thr_local_set_slot_no( mutex_exit(&thr_local_mutex); } -/*******************************************************************//** -Returns pointer to the 'in_ibuf' field within the current thread local -storage. -@return pointer to the in_ibuf field */ -UNIV_INTERN -ibool* -thr_local_get_in_ibuf_field(void) -/*=============================*/ -{ - thr_local_t* local; - - mutex_enter(&thr_local_mutex); - - local = thr_local_get(os_thread_get_curr_id()); - - mutex_exit(&thr_local_mutex); - - return(&(local->in_ibuf)); -} - /*******************************************************************//** Creates a local storage struct for the calling new thread. */ UNIV_INTERN From fc12800c055bf2383ab7c7fb94e39a48d5860445 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Wed, 12 Jan 2011 14:44:25 +0100 Subject: [PATCH 08/62] Removed dependency no longer correct --- storage/innobase/row/row0merge.c | 2 -- storage/innobase/row/row0mysql.c | 14 -------------- storage/innobase/row/row0sel.c | 1 - 3 files changed, 17 deletions(-) diff --git a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c index 0c68d6477a4..209df02e445 100644 --- a/storage/innobase/row/row0merge.c +++ b/storage/innobase/row/row0merge.c @@ -1929,7 +1929,6 @@ row_merge_lock_table( sel_node_t* node; ut_ad(trx); - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(mode == LOCK_X || mode == LOCK_S); heap = mem_heap_create(512); @@ -2366,7 +2365,6 @@ row_merge_rename_tables( pars_info_t* info; char old_name[MAX_TABLE_NAME_LEN + 1]; - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(old_table != new_table); ut_ad(mutex_own(&dict_sys->mutex)); diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 63f30276df6..23d248481c9 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -976,7 +976,6 @@ row_lock_table_autoinc_for_mysql( ibool was_lock_wait; ut_ad(trx); - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); /* If we already hold an AUTOINC lock on the table then do nothing. Note: We peek at the value of the current owner without acquiring @@ -1056,7 +1055,6 @@ row_lock_table_for_mysql( ibool was_lock_wait; ut_ad(trx); - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); trx->op_info = "setting table lock"; @@ -1130,7 +1128,6 @@ row_insert_for_mysql( ins_node_t* node = prebuilt->ins_node; ut_ad(trx); - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); if (prebuilt->table->ibd_file_missing) { ut_print_timestamp(stderr); @@ -1364,7 +1361,6 @@ row_update_for_mysql( trx_t* trx = prebuilt->trx; ut_ad(prebuilt && trx); - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); UT_NOT_USED(mysql_rec); if (prebuilt->table->ibd_file_missing) { @@ -1532,7 +1528,6 @@ row_unlock_for_mysql( trx_t* trx = prebuilt->trx; ut_ad(prebuilt && trx); - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); if (UNIV_UNLIKELY (!srv_locks_unsafe_for_binlog @@ -1834,7 +1829,6 @@ row_create_table_for_mysql( ulint table_name_len; ulint err; - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ @@ -2006,7 +2000,6 @@ row_create_index_for_mysql( ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ ut_ad(mutex_own(&(dict_sys->mutex))); - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); trx->op_info = "creating index"; @@ -2409,8 +2402,6 @@ row_discard_tablespace_for_mysql( table->n_foreign_key_checks_running > 0, we do not allow the discard. We also reserve the data dictionary latch. */ - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - trx->op_info = "discarding tablespace"; trx_start_if_not_started(trx); @@ -2569,8 +2560,6 @@ row_import_tablespace_for_mysql( ib_uint64_t current_lsn; ulint err = DB_SUCCESS; - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - trx_start_if_not_started(trx); trx->op_info = "importing tablespace"; @@ -2754,7 +2743,6 @@ row_truncate_table_for_mysql( redo log records on the truncated tablespace, we will assign a new tablespace identifier to the truncated tablespace. */ - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(table); if (srv_created_new_raw) { @@ -3605,7 +3593,6 @@ row_drop_database_for_mysql( int err = DB_SUCCESS; ulint namelen = strlen(name); - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_a(name != NULL); ut_a(name[namelen - 1] == '/'); @@ -3775,7 +3762,6 @@ row_rename_table_for_mysql( ibool old_is_tmp, new_is_tmp; pars_info_t* info = NULL; - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_a(old_name != NULL); ut_a(new_name != NULL); diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 14deff2d465..58043753cce 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -3370,7 +3370,6 @@ row_search_for_mysql( rec_offs_init(offsets_); ut_ad(index && pcur && search_tuple); - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) { ut_print_timestamp(stderr); From 4bc4a696bb9f0f8d453625304bc40c18187da11f Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 14 Jan 2011 09:28:23 +0100 Subject: [PATCH 09/62] Updates tests to handle thread pool correctly --- BUILD/build_mccge.sh | 3 ++- mysql-test/include/have_archive_plugin.inc | 5 +++++ mysql-test/include/have_blackhole_plugin.inc | 6 ++++++ mysql-test/include/not_threadpool.inc | 5 +++++ mysql-test/r/status.result | 6 ------ mysql-test/r/status_bug17954.result | 13 +++++++++++++ .../suite/sys_vars/t/slow_launch_time_func.test | 1 + .../suite/sys_vars/t/thread_cache_size_func.test | 1 + mysql-test/suite/sys_vars/t/wait_timeout_func.test | 1 + 9 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 mysql-test/include/not_threadpool.inc create mode 100644 mysql-test/r/status_bug17954.result diff --git a/BUILD/build_mccge.sh b/BUILD/build_mccge.sh index ca77dfb84d7..9791ac04f22 100755 --- a/BUILD/build_mccge.sh +++ b/BUILD/build_mccge.sh @@ -293,7 +293,8 @@ extended_usage() version string suffix: [none] All packages except Classic include support for user-defined - partitioning. + partitioning. All packages include support for Performance + Schema. If --with-debug is used, an additional "-debug" is appended to the version string. diff --git a/mysql-test/include/have_archive_plugin.inc b/mysql-test/include/have_archive_plugin.inc index 98e146ca20b..03b382d6344 100644 --- a/mysql-test/include/have_archive_plugin.inc +++ b/mysql-test/include/have_archive_plugin.inc @@ -1,5 +1,10 @@ +disable_query_log; if (`select plugin_library IS NULL from information_schema.plugins where plugin_name LIKE '%archive%'`) { --skip archive plugin not available } +if (`SELECT @@plugin_dir != '$ARCHIVE_PLUGIN_DIR'`) { + --skip Archive plugin requires that --plugin-dir is set to the archive plugin dir (either the .opt file does not contain \$ARCHIVE_PLUGIN_OPT or another plugin is in use) +} +enable_query_log; \ No newline at end of file diff --git a/mysql-test/include/have_blackhole_plugin.inc b/mysql-test/include/have_blackhole_plugin.inc index 749efd343d6..bd1c1ac8af7 100644 --- a/mysql-test/include/have_blackhole_plugin.inc +++ b/mysql-test/include/have_blackhole_plugin.inc @@ -1,5 +1,11 @@ +disable_query_log; if (`select plugin_library IS NULL from information_schema.plugins where plugin_name LIKE '%blackhole%'`) { --skip blackhole plugin not available; } +if (`SELECT @@plugin_dir != '$BLACKHOLE_PLUGIN_DIR'`) { + --skip Blackhole plugin requires that --plugin-dir is set to the blackhole plugin dir (either the .opt file does not contain \$BLACKHOLE_PLUGIN_OPT or another plugin is in use) +} +enable_query_log; + diff --git a/mysql-test/include/not_threadpool.inc b/mysql-test/include/not_threadpool.inc new file mode 100644 index 00000000000..a49c8cfcc32 --- /dev/null +++ b/mysql-test/include/not_threadpool.inc @@ -0,0 +1,5 @@ +if (`SELECT count(*) FROM information_schema.GLOBAL_VARIABLES WHERE + VARIABLE_NAME = 'THREAD_HANDLING' AND + VARIABLE_VALUE = 'loaded-dynamically'`){ + skip Test requires: 'not_threadpool'; +} diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index c0cd0f7bc1a..ce3acba9b8a 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -238,11 +238,5 @@ SELECT 9; 9 DROP PROCEDURE p1; DROP FUNCTION f1; -DROP VIEW IF EXISTS v1; -CREATE VIEW v1 AS SELECT VARIABLE_NAME AS NAME, CONVERT(VARIABLE_VALUE, UNSIGNED) AS VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS; -SELECT VALUE INTO @tc FROM v1 WHERE NAME = 'Threads_connected'; -SELECT NAME FROM v1 WHERE NAME = 'Threads_created' AND VALUE < @tc; -NAME -DROP VIEW v1; set @@global.concurrent_insert= @old_concurrent_insert; SET GLOBAL log_output = @old_log_output; diff --git a/mysql-test/r/status_bug17954.result b/mysql-test/r/status_bug17954.result new file mode 100644 index 00000000000..5c244cd8aca --- /dev/null +++ b/mysql-test/r/status_bug17954.result @@ -0,0 +1,13 @@ +set @old_concurrent_insert= @@global.concurrent_insert; +set @@global.concurrent_insert= 0; +SET @old_log_output = @@global.log_output; +SET GLOBAL LOG_OUTPUT = 'FILE'; +flush status; +DROP VIEW IF EXISTS v1; +CREATE VIEW v1 AS SELECT VARIABLE_NAME AS NAME, CONVERT(VARIABLE_VALUE, UNSIGNED) AS VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS; +SELECT VALUE INTO @tc FROM v1 WHERE NAME = 'Threads_connected'; +SELECT NAME FROM v1 WHERE NAME = 'Threads_created' AND VALUE < @tc; +NAME +DROP VIEW v1; +set @@global.concurrent_insert= @old_concurrent_insert; +SET GLOBAL log_output = @old_log_output; diff --git a/mysql-test/suite/sys_vars/t/slow_launch_time_func.test b/mysql-test/suite/sys_vars/t/slow_launch_time_func.test index 1f384888f81..c9fc357b10f 100644 --- a/mysql-test/suite/sys_vars/t/slow_launch_time_func.test +++ b/mysql-test/suite/sys_vars/t/slow_launch_time_func.test @@ -31,6 +31,7 @@ # --source include/not_embedded.inc +--source include/not_threadpool.inc SET @global_slow_launch_time = @@GLOBAL.slow_launch_time; diff --git a/mysql-test/suite/sys_vars/t/thread_cache_size_func.test b/mysql-test/suite/sys_vars/t/thread_cache_size_func.test index fe9f4242c0d..9bffa32ca2b 100644 --- a/mysql-test/suite/sys_vars/t/thread_cache_size_func.test +++ b/mysql-test/suite/sys_vars/t/thread_cache_size_func.test @@ -28,6 +28,7 @@ # --source include/not_embedded.inc +--source include/not_threadpool.inc SET @global_thread_cache_size = @@GLOBAL.thread_cache_size; diff --git a/mysql-test/suite/sys_vars/t/wait_timeout_func.test b/mysql-test/suite/sys_vars/t/wait_timeout_func.test index e33c39016cc..313d9e8191d 100644 --- a/mysql-test/suite/sys_vars/t/wait_timeout_func.test +++ b/mysql-test/suite/sys_vars/t/wait_timeout_func.test @@ -22,6 +22,7 @@ ############################################################################### --source include/not_embedded.inc +--source include/not_threadpool.inc SET @start_value= @@global.wait_timeout; From 35f5e0146188d416a7cfc60593f83e61f0e8e67e Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 14 Jan 2011 09:36:24 +0100 Subject: [PATCH 10/62] Fixed status test case --- mysql-test/t/status.test | 15 --------- mysql-test/t/status_bug17954.test | 54 +++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 mysql-test/t/status_bug17954.test diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index 9965875af55..26c7a89bf5c 100644 --- a/mysql-test/t/status.test +++ b/mysql-test/t/status.test @@ -354,21 +354,6 @@ DROP FUNCTION f1; # End of 5.1 tests -# -# Bug#17954 Threads_connected > Threads_created -# - ---disable_warnings -DROP VIEW IF EXISTS v1; ---enable_warnings - -CREATE VIEW v1 AS SELECT VARIABLE_NAME AS NAME, CONVERT(VARIABLE_VALUE, UNSIGNED) AS VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS; - -SELECT VALUE INTO @tc FROM v1 WHERE NAME = 'Threads_connected'; -SELECT NAME FROM v1 WHERE NAME = 'Threads_created' AND VALUE < @tc; - -DROP VIEW v1; - # Restore global concurrent_insert value. Keep in the end of the test file. --connection default set @@global.concurrent_insert= @old_concurrent_insert; diff --git a/mysql-test/t/status_bug17954.test b/mysql-test/t/status_bug17954.test new file mode 100644 index 00000000000..36430cceeff --- /dev/null +++ b/mysql-test/t/status_bug17954.test @@ -0,0 +1,54 @@ +# This test requires that --log-output includes 'table', and the general +# log is on + +# embedded server causes different stat +-- source include/not_embedded.inc + +# thread pool causes different results +-- source include/not_threadpool.inc + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +# Disable concurrent inserts to avoid sporadic test failures as it might +# affect the the value of variables used throughout the test case. +set @old_concurrent_insert= @@global.concurrent_insert; +set @@global.concurrent_insert= 0; + +# Disable logging to table, since this will also cause table locking and unlocking, which will +# show up in SHOW STATUS and may cause sporadic failures + +SET @old_log_output = @@global.log_output; +SET GLOBAL LOG_OUTPUT = 'FILE'; + +# PS causes different statistics +--disable_ps_protocol + +flush status; + +# +# Bug#17954 Threads_connected > Threads_created +# + +--disable_warnings +DROP VIEW IF EXISTS v1; +--enable_warnings + +CREATE VIEW v1 AS SELECT VARIABLE_NAME AS NAME, CONVERT(VARIABLE_VALUE, UNSIGNED) AS VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS; + +SELECT VALUE INTO @tc FROM v1 WHERE NAME = 'Threads_connected'; +SELECT NAME FROM v1 WHERE NAME = 'Threads_created' AND VALUE < @tc; +#SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS where variable_name like '%thread%'; +#SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS; +#SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES; + +DROP VIEW v1; + +# Restore global concurrent_insert value. Keep in the end of the test file. +--connection default +set @@global.concurrent_insert= @old_concurrent_insert; +SET GLOBAL log_output = @old_log_output; + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc + From 2071e6e3b2450c0ae9f3a3ba56b63b54e83fbb4f Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 14 Jan 2011 09:40:18 +0100 Subject: [PATCH 11/62] Added thread pool interface to server --- include/mysql/thread_pool_priv.h | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 include/mysql/thread_pool_priv.h diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h new file mode 100644 index 00000000000..ec5eaecafa7 --- /dev/null +++ b/include/mysql/thread_pool_priv.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef THREAD_POOL_PRIV_INCLUDED +#define THREAD_POOL_PRIV_INCLUDED + +/* + The thread pool must be able to execute commands using the connection + state in THD object. This is the main objective of the thread pool to + schedule the start of these commands. +*/ +bool do_command(THD *thd); + +/* + The thread pool requires an interface to the connection logic in the + MySQL Server since the thread pool will maintain the event logic on + the TCP connection of the MySQL Server. Thus new connections, dropped + connections will be discovered by the thread pool and it needs to + ensure that the proper MySQL Server logic attached to these events is + executed. +*/ +bool login_connection(THD *thd); +void prepare_new_connection_state(THD* thd); +void end_connection(THD *thd); +bool setup_connection_thread_globals(THD *thd); +bool init_new_connection_handler_thread(); + +/* + thread_created is maintained by thread pool when activated since + user threads are created by the thread pool (and also special + threads to maintain the thread pool). + max_connections is needed to calculate the maximum number of threads + that is allowed to be started by the thread pool. +*/ +extern ulong thread_created, max_connections; +#endif From 02e823451569f8ae90ed44a4357e7a4382c8e2c5 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 14 Jan 2011 09:46:53 +0100 Subject: [PATCH 12/62] Tests not supporting thread pool marked --- mysql-test/t/named_pipe.test | 3 +++ mysql-test/t/shm.test | 3 +++ 2 files changed, 6 insertions(+) diff --git a/mysql-test/t/named_pipe.test b/mysql-test/t/named_pipe.test index 0e6c963024f..23a11d61222 100644 --- a/mysql-test/t/named_pipe.test +++ b/mysql-test/t/named_pipe.test @@ -3,6 +3,9 @@ # other platforms --source include/windows.inc +# thread pool causes different results +-- source include/not_threadpool.inc + # Only run this test if named pipe is avaliable let $nmp= query_get_value("SHOW VARIABLES LIKE 'named_pipe'", Value, 1); if ($nmp != ON){ diff --git a/mysql-test/t/shm.test b/mysql-test/t/shm.test index 0f880e58741..4c765c43c1b 100644 --- a/mysql-test/t/shm.test +++ b/mysql-test/t/shm.test @@ -2,6 +2,9 @@ # to optimize things we skip this test on all other platforms --source include/windows.inc +# thread pool causes different results +-- source include/not_threadpool.inc + # Only run this test if shared memory is avaliable let $shm= query_get_value("SHOW VARIABLES LIKE 'shared_memory'", Value, 1); if ($shm != ON){ From c2fb1a9b2c8f80d8c4f73078283b2e295ef625f0 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 14 Jan 2011 18:01:22 +0100 Subject: [PATCH 13/62] Updated plugin.defs with thread pool --- mysql-test/include/plugin.defs | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/include/plugin.defs b/mysql-test/include/plugin.defs index 4da03dc2cc9..5192dccabf7 100644 --- a/mysql-test/include/plugin.defs +++ b/mysql-test/include/plugin.defs @@ -39,3 +39,4 @@ ha_archive storage/archive ARCHIVE_PLUGIN ha_blackhole storage/blackhole BLACKHOLE_PLUGIN ha_federated storage/federated FEDERATED_PLUGIN mypluglib plugin/fulltext SIMPLE_PARSER +thread_pool plugin/thread_pool THREADPOOL_PLUGIN thread_pool,TP_THREAD_STATE,TP_THREAD_GROUP_STATE,TP_THREAD_GROUP_STATS From 1ce30b7356086349b59d4a301888d1769567bf82 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 14 Jan 2011 19:21:27 +0100 Subject: [PATCH 14/62] Disable kill.test for thread pool --- mysql-test/t/kill.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 9e94bb44171..f36d5a2169d 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -9,6 +9,7 @@ -- source include/not_embedded.inc -- source include/have_debug_sync.inc +-- source include/not_threadpool.inc --disable_warnings SET DEBUG_SYNC = 'RESET'; From 14a46479b64e1c0ee0ced10905c65e8c7e276d8b Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Mon, 17 Jan 2011 13:25:31 +0100 Subject: [PATCH 15/62] BUG#59549, fix compiler error on Windows --- sql/log.cc | 14 +++++++------- sql/log.h | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 7ab4b6b4a61..17efbca8bb2 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5995,7 +5995,7 @@ int TC_LOG_MMAP::open(const char *opt_name) { pg->next=pg+1; pg->waiters=0; - pg->state=POOL; + pg->state=PS_POOL; mysql_mutex_init(key_PAGE_lock, &pg->lock, MY_MUTEX_INIT_FAST); mysql_cond_init(key_PAGE_cond, &pg->cond, 0); pg->start=(my_xid *)(data + i*tc_log_page_size); @@ -6169,7 +6169,7 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid) cookie= (ulong)((uchar *)p->ptr - data); // can never be zero *p->ptr++= xid; p->free--; - p->state= DIRTY; + p->state= PS_DIRTY; /* to sync or not to sync - this is the question */ mysql_mutex_unlock(&LOCK_active); @@ -6181,13 +6181,13 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid) p->waiters++; /* note - it must be while (), not do ... while () here - as p->state may be not DIRTY when we come here + as p->state may be not PS_DIRTY when we come here */ - while (p->state == DIRTY && syncing) + while (p->state == PS_DIRTY && syncing) mysql_cond_wait(&p->cond, &LOCK_sync); p->waiters--; - err= p->state == ERROR; - if (p->state != DIRTY) // page was synced + err= p->state == PS_ERROR; + if (p->state != PS_DIRTY) // page was synced { if (p->waiters == 0) mysql_cond_signal(&COND_pool); // in case somebody's waiting @@ -6225,7 +6225,7 @@ int TC_LOG_MMAP::sync() pool_last->next=syncing; pool_last=syncing; syncing->next=0; - syncing->state= err ? ERROR : POOL; + syncing->state= err ? PS_ERROR : PS_POOL; mysql_cond_broadcast(&syncing->cond); // signal "sync done" mysql_cond_signal(&COND_pool); // in case somebody's waiting mysql_mutex_unlock(&LOCK_pool); diff --git a/sql/log.h b/sql/log.h index 05f8a4ce286..d287da0dcd1 100644 --- a/sql/log.h +++ b/sql/log.h @@ -63,9 +63,9 @@ class TC_LOG_MMAP: public TC_LOG { public: // only to keep Sun Forte on sol9x86 happy typedef enum { - POOL, // page is in pool - ERROR, // last sync failed - DIRTY // new xids added since last sync + PS_POOL, // page is in pool + PS_ERROR, // last sync failed + PS_DIRTY // new xids added since last sync } PAGE_STATE; private: From e31d7282090dadf3020874549bd690363276e772 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Thu, 20 Jan 2011 18:24:48 +0100 Subject: [PATCH 16/62] BUG#59549, fix compiler error on Windows, step 2 --- sql/sp_head.cc | 14 +++++++------- sql/sp_head.h | 2 +- sql/sql_class.cc | 2 +- sql/sql_class.h | 24 ++++++++++++------------ sql/sql_cursor.h | 2 +- sql/sql_prepare.cc | 18 +++++++++--------- sql/table.cc | 2 +- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 6959d21abd6..22a8f1c4ebf 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -551,7 +551,7 @@ sp_head::operator delete(void *ptr, size_t size) throw() sp_head::sp_head() - :Query_arena(&main_mem_root, INITIALIZED_FOR_SP), + :Query_arena(&main_mem_root, ES_INITIALIZED_FOR_SP), m_flags(0), m_sp_cache_version(0), unsafe_flags(0), @@ -1209,7 +1209,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) Query_arena *old_arena; /* per-instruction arena */ MEM_ROOT execute_mem_root; - Query_arena execute_arena(&execute_mem_root, INITIALIZED_FOR_SP), + Query_arena execute_arena(&execute_mem_root, ES_INITIALIZED_FOR_SP), backup_arena; query_id_t old_query_id; TABLE *old_derived_tables; @@ -1489,7 +1489,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) thd->m_reprepare_observer= save_reprepare_observer; thd->stmt_arena= old_arena; - state= EXECUTED; + state= ES_EXECUTED; /* Restore the caller's original warning information area: @@ -1647,7 +1647,7 @@ sp_head::execute_trigger(THD *thd, sp_rcontext *nctx = NULL; bool err_status= FALSE; MEM_ROOT call_mem_root; - Query_arena call_arena(&call_mem_root, Query_arena::INITIALIZED_FOR_SP); + Query_arena call_arena(&call_mem_root, Query_arena::ES_INITIALIZED_FOR_SP); Query_arena backup_arena; DBUG_ENTER("sp_head::execute_trigger"); @@ -1788,7 +1788,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, String binlog_buf(buf, sizeof(buf), &my_charset_bin); bool err_status= FALSE; MEM_ROOT call_mem_root; - Query_arena call_arena(&call_mem_root, Query_arena::INITIALIZED_FOR_SP); + Query_arena call_arena(&call_mem_root, Query_arena::ES_INITIALIZED_FOR_SP); Query_arena backup_arena; DBUG_ENTER("sp_head::execute_function"); DBUG_PRINT("info", ("function %s", m_name.str)); @@ -2545,7 +2545,7 @@ sp_head::restore_thd_mem_root(THD *thd) DBUG_ENTER("sp_head::restore_thd_mem_root"); Item *flist= free_list; // The old list set_query_arena(thd); // Get new free_list and mem_root - state= INITIALIZED_FOR_SP; + state= ES_INITIALIZED_FOR_SP; DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx", (ulong) &mem_root, (ulong) &thd->mem_root)); @@ -3009,7 +3009,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, (thd->stmt_da->sql_errno() != ER_CANT_REOPEN_TABLE && thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE && thd->stmt_da->sql_errno() != ER_UPDATE_TABLE_USED)) - thd->stmt_arena->state= Query_arena::EXECUTED; + thd->stmt_arena->state= Query_arena::ES_EXECUTED; /* Merge here with the saved parent's values diff --git a/sql/sp_head.h b/sql/sp_head.h index 5efd48fc7c6..7ee80824b4d 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -560,7 +560,7 @@ public: /// Should give each a name or type code for debugging purposes? sp_instr(uint ip, sp_pcontext *ctx) - :Query_arena(0, INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx) + :Query_arena(0, ES_INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx) {} virtual ~sp_instr() diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c058e66df97..efa125acb2e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -493,7 +493,7 @@ bool Drop_table_error_handler::handle_condition(THD *thd, THD::THD() - :Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION, + :Statement(&main_lex, &main_mem_root, ES_CONVENTIONAL_EXECUTION, /* statement id */ 0), rli_fake(0), user_time(0), in_sub_stmt(0), diff --git a/sql/sql_class.h b/sql/sql_class.h index 8b05497388e..4104f15cfa4 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -624,14 +624,14 @@ public: /* The states relfects three diffrent life cycles for three different types of statements: - Prepared statement: INITIALIZED -> PREPARED -> EXECUTED. - Stored procedure: INITIALIZED_FOR_SP -> EXECUTED. - Other statements: CONVENTIONAL_EXECUTION never changes. + Prepared statement: ES_INITIALIZED -> ES_PREPARED -> ES_EXECUTED. + Stored procedure: ES_INITIALIZED_FOR_SP -> ES_EXECUTED. + Other statements: ES_CONVENTIONAL_EXECUTION never changes. */ enum enum_state { - INITIALIZED= 0, INITIALIZED_FOR_SP= 1, PREPARED= 2, - CONVENTIONAL_EXECUTION= 3, EXECUTED= 4, ERROR= -1 + ES_INITIALIZED= 0, ES_INITIALIZED_FOR_SP= 1, ES_PREPARED= 2, + ES_CONVENTIONAL_EXECUTION= 3, ES_EXECUTED= 4, ES_ERROR= -1 }; enum_state state; @@ -654,18 +654,18 @@ public: virtual Type type() const; virtual ~Query_arena() {}; - inline bool is_stmt_prepare() const { return state == INITIALIZED; } + inline bool is_stmt_prepare() const { return state == ES_INITIALIZED; } inline bool is_first_sp_execute() const - { return state == INITIALIZED_FOR_SP; } + { return state == ES_INITIALIZED_FOR_SP; } inline bool is_stmt_prepare_or_first_sp_execute() const - { return (int)state < (int)PREPARED; } + { return (int)state < (int)ES_PREPARED; } inline bool is_stmt_prepare_or_first_stmt_execute() const - { return (int)state <= (int)PREPARED; } - inline bool is_first_stmt_execute() const { return state == PREPARED; } + { return (int)state <= (int)ES_PREPARED; } + inline bool is_first_stmt_execute() const { return state == ES_PREPARED; } inline bool is_stmt_execute() const - { return state == PREPARED || state == EXECUTED; } + { return state == ES_PREPARED || state == ES_EXECUTED; } inline bool is_conventional() const - { return state == CONVENTIONAL_EXECUTION; } + { return state == ES_CONVENTIONAL_EXECUTION; } inline void* alloc(size_t size) { return alloc_root(mem_root,size); } inline void* calloc(size_t size) diff --git a/sql/sql_cursor.h b/sql/sql_cursor.h index ed7bfac821a..521b7771bfa 100644 --- a/sql/sql_cursor.h +++ b/sql/sql_cursor.h @@ -46,7 +46,7 @@ protected: select_result *result; public: Server_side_cursor(MEM_ROOT *mem_root_arg, select_result *result_arg) - :Query_arena(mem_root_arg, INITIALIZED), result(result_arg) + :Query_arena(mem_root_arg, ES_INITIALIZED), result(result_arg) {} virtual bool is_open() const= 0; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 64f252d11d3..847403bf053 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2712,7 +2712,7 @@ void mysqld_stmt_reset(THD *thd, char *packet) */ reset_stmt_params(stmt); - stmt->state= Query_arena::PREPARED; + stmt->state= Query_arena::ES_PREPARED; general_log_print(thd, thd->command, NullS); @@ -2830,7 +2830,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) if (param_number >= stmt->param_count) { /* Error will be sent in execute call */ - stmt->state= Query_arena::ERROR; + stmt->state= Query_arena::ES_ERROR; stmt->last_errno= ER_WRONG_ARGUMENTS; sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), "mysqld_stmt_send_long_data"); @@ -2846,7 +2846,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) if (param->set_longdata(thd->extra_data, thd->extra_length)) #endif { - stmt->state= Query_arena::ERROR; + stmt->state= Query_arena::ES_ERROR; stmt->last_errno= ER_OUTOFMEMORY; sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0); } @@ -2999,7 +2999,7 @@ end: Prepared_statement::Prepared_statement(THD *thd_arg) :Statement(NULL, &main_mem_root, - INITIALIZED, ++thd_arg->statement_id_counter), + ES_INITIALIZED, ++thd_arg->statement_id_counter), thd(thd_arg), result(thd_arg), param_array(0), @@ -3272,7 +3272,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) { setup_set_params(); lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_PREPARE; - state= Query_arena::PREPARED; + state= Query_arena::ES_PREPARED; flags&= ~ (uint) IS_IN_USE; /* @@ -3446,7 +3446,7 @@ Prepared_statement::execute_server_runnable(Server_runnable *server_runnable) Item_change_list save_change_list; thd->change_list.move_elements_to(&save_change_list); - state= CONVENTIONAL_EXECUTION; + state= ES_CONVENTIONAL_EXECUTION; if (!(lex= new (mem_root) st_lex_local)) return TRUE; @@ -3657,7 +3657,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) status_var_increment(thd->status_var.com_stmt_execute); /* Check if we got an error when sending long data */ - if (state == Query_arena::ERROR) + if (state == Query_arena::ES_ERROR) { my_message(last_errno, last_error, MYF(0)); return TRUE; @@ -3787,8 +3787,8 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) thd->set_statement(&stmt_backup); thd->stmt_arena= old_stmt_arena; - if (state == Query_arena::PREPARED) - state= Query_arena::EXECUTED; + if (state == Query_arena::ES_PREPARED) + state= Query_arena::ES_EXECUTED; if (error == 0 && this->lex->sql_command == SQLCOM_CALL) { diff --git a/sql/table.cc b/sql/table.cc index fae044f334a..238e73f7193 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1933,7 +1933,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, Query_arena *backup_stmt_arena_ptr= thd->stmt_arena; Query_arena backup_arena; - Query_arena part_func_arena(&outparam->mem_root, Query_arena::INITIALIZED); + Query_arena part_func_arena(&outparam->mem_root, Query_arena::ES_INITIALIZED); thd->set_n_backup_active_arena(&part_func_arena, &backup_arena); thd->stmt_arena= &part_func_arena; bool tmp; From 416b7144d50304a428938bb23848f2db8331824d Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Mon, 24 Jan 2011 14:57:07 +0100 Subject: [PATCH 17/62] BUG#59549, Fix compiler errors on Windows, step 5 --- include/mysql/thread_pool_priv.h | 7 ++++++- sql/mysqld.cc | 15 +++++++++------ sql/mysqld.h | 10 ++++++---- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index ec5eaecafa7..e9b729d6913 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -46,5 +46,10 @@ bool init_new_connection_handler_thread(); max_connections is needed to calculate the maximum number of threads that is allowed to be started by the thread pool. */ -extern ulong thread_created, max_connections; +extern MYSQL_PLUGIN_IMPORT ulong thread_created; +extern MYSQL_PLUGIN_IMPORT ulong max_connections; +extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_thread_count; +extern MYSQL_PLUGIN_IMPORT pthread_attr_t connection_attrib; +extern MYSQL_PLUGIN_IMPORT I_List threads; +extern MYSQL_PLUGIN_IMPORT PSI_thread_key key_thread_one_connection; #endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 188ed7c6885..15588cadaae 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -450,7 +450,7 @@ uint lower_case_table_names; ulong tc_heuristic_recover= 0; uint volatile thread_count; int32 thread_running; -ulong thread_created; +MYSQL_PLUGIN_IMPORT ulong thread_created; ulong back_log, connect_timeout, concurrency, server_id; ulong table_cache_size, table_def_size; ulong what_to_log; @@ -477,7 +477,8 @@ ulong delayed_insert_errors,flush_time; ulong specialflag=0; ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0; -ulong max_connections, max_connect_errors; +MYSQL_PLUGIN_IMPORT ulong max_connections; +ulong max_connect_errors; /** Limit of the total number of prepared statements in the server. Is necessary to protect the server against out-of-memory attacks. @@ -580,7 +581,7 @@ Le_creator le_creator; MYSQL_FILE *bootstrap_file; int bootstrap_error; -I_List threads; +MYSQL_PLUGIN_IMPORT I_List threads; Rpl_filter* rpl_filter; Rpl_filter* binlog_filter; @@ -629,9 +630,9 @@ mysql_mutex_t LOCK_des_key_file; #endif mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; mysql_rwlock_t LOCK_system_variables_hash; -mysql_cond_t COND_thread_count; +MYSQL_PLUGIN_IMPORT mysql_cond_t COND_thread_count; pthread_t signal_thread; -pthread_attr_t connection_attrib; +MYSQL_PLUGIN_IMPORT pthread_attr_t connection_attrib; mysql_mutex_t LOCK_server_started; mysql_cond_t COND_server_started; @@ -7792,7 +7793,9 @@ static PSI_cond_info all_server_conds[]= PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, key_thread_handle_manager, key_thread_main, - key_thread_one_connection, key_thread_signal_hand; + key_thread_signal_hand; + +MYSQL_PLUGIN_IMPORT PSI_thread_key key_thread_one_connection; static PSI_thread_info all_server_threads[]= { diff --git a/sql/mysqld.h b/sql/mysqld.h index 2099e57e96d..3fd60c511e8 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -204,12 +204,12 @@ extern struct my_option my_long_options[]; extern int mysqld_server_started; extern int orig_argc; extern char **orig_argv; -extern pthread_attr_t connection_attrib; +extern MYSQL_PLUGIN_IMPORT pthread_attr_t connection_attrib; extern MYSQL_FILE *bootstrap_file; extern my_bool old_mode; extern LEX_STRING opt_init_connect, opt_init_slave; extern int bootstrap_error; -extern I_List threads; +extern MYSQL_PLUGIN_IMPORT I_List threads; extern char err_shared_dir[]; extern TYPELIB thread_handling_typelib; extern my_decimal decimal_zero; @@ -263,7 +263,9 @@ extern PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond, extern PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, key_thread_handle_manager, key_thread_kill_server, key_thread_main, - key_thread_one_connection, key_thread_signal_hand; + key_thread_signal_hand; + +extern MYSQL_PLUGIN_IMPORT PSI_thread_key key_thread_one_connection; #ifdef HAVE_MMAP extern PSI_file_key key_file_map; @@ -335,7 +337,7 @@ extern mysql_mutex_t LOCK_server_started; extern mysql_cond_t COND_server_started; extern mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; extern mysql_rwlock_t LOCK_system_variables_hash; -extern mysql_cond_t COND_thread_count; +extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_thread_count; extern mysql_cond_t COND_manager; extern int32 thread_running; extern my_atomic_rwlock_t thread_running_lock; From d947cd8eabf0d3ae6994ebb6e09d435eadc6ea56 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Mon, 24 Jan 2011 15:04:35 +0100 Subject: [PATCH 18/62] Temporary fix --- include/mysql/thread_pool_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index e9b729d6913..2e8312d98ca 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -50,6 +50,6 @@ extern MYSQL_PLUGIN_IMPORT ulong thread_created; extern MYSQL_PLUGIN_IMPORT ulong max_connections; extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_thread_count; extern MYSQL_PLUGIN_IMPORT pthread_attr_t connection_attrib; -extern MYSQL_PLUGIN_IMPORT I_List threads; +/* extern MYSQL_PLUGIN_IMPORT I_List threads; */ extern MYSQL_PLUGIN_IMPORT PSI_thread_key key_thread_one_connection; #endif From fbbe9c2e8ee268222348adb1173cf5fdbcc694d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 3 Feb 2011 21:05:34 +0100 Subject: [PATCH 19/62] Fixed such that debug_sync can be used by plugins on Windows --- sql/debug_sync.h | 2 +- sql/mysqld.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/debug_sync.h b/sql/debug_sync.h index 9ac7da39d4d..ba3739e8ad5 100644 --- a/sql/debug_sync.h +++ b/sql/debug_sync.h @@ -39,7 +39,7 @@ class THD; } while (0) /* Command line option --debug-sync-timeout. See mysqld.cc. */ -extern uint opt_debug_sync_timeout; +extern MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout; /* Default WAIT_FOR timeout if command line option is given without argument. */ #define DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT 300 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 15588cadaae..02e8d8de42f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -425,7 +425,7 @@ my_bool opt_super_large_pages= 0; my_bool opt_myisam_use_mmap= 0; uint opt_large_page_size= 0; #if defined(ENABLED_DEBUG_SYNC) -uint opt_debug_sync_timeout= 0; +MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout= 0; #endif /* defined(ENABLED_DEBUG_SYNC) */ my_bool opt_old_style_user_limits= 0, trust_function_creators= 0; /* From 70136c0aa252d8da2c698f3635ddce8c60b26bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 10 Feb 2011 16:19:38 +0100 Subject: [PATCH 20/62] Updated thread_pool_priv.h with additional includes for thread pool plugins --- include/mysql/thread_pool_priv.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index 2e8312d98ca..73e48cc33e7 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -18,6 +18,28 @@ #ifndef THREAD_POOL_PRIV_INCLUDED #define THREAD_POOL_PRIV_INCLUDED +/* + A thread pool plugins requires inclusion of sql_class.h to get proper + access to THD variables and functions. + There are some DTrace probes that requires definition inside the plugin, + this requires include of probes_mysql.h. + scheduler.h contains definitions required by the plugin. + A thread pool can also use DEBUG_SYNC and must thus include + debug_sync.h + To handle definitions of Information Schema plugins it is also required + to include sql_profile.h and table.h. + + The goal is to move all dependencies from a thread pool plugin on the + MySQL Server into a version-handled plugin API. +*/ +#define MYSQL_SERVER 1 +#include +#include +#include +#include +#include +#include + /* The thread pool must be able to execute commands using the connection state in THD object. This is the main objective of the thread pool to From 6d45d27cbc9c343736a97cafa504eb1998d8bd70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 10 Feb 2011 18:41:02 +0100 Subject: [PATCH 21/62] Simplify interface to connect methods in server --- include/mysql/thread_pool_priv.h | 6 ++--- sql/sql_connect.cc | 39 +++++++++++++++++++++++--------- sql/sql_connect.h | 2 ++ 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index 73e48cc33e7..555d5fb0e7b 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -34,7 +34,6 @@ */ #define MYSQL_SERVER 1 #include -#include #include #include #include @@ -55,9 +54,10 @@ bool do_command(THD *thd); ensure that the proper MySQL Server logic attached to these events is executed. */ -bool login_connection(THD *thd); -void prepare_new_connection_state(THD* thd); +bool thd_prepare_connection(THD *thd); +bool thd_is_connection_alive(THD *thd); void end_connection(THD *thd); +void mysql_audit_release(THD *thd); bool setup_connection_thread_globals(THD *thd); bool init_new_connection_handler_thread(); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index ad6fe492056..2333c691240 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -685,6 +685,32 @@ pthread_handler_t handle_one_connection(void *arg) return 0; } +bool thd_prepare_connection(THD *thd) +{ + bool rc; + lex_start(thd); + rc= login_connection(thd); + MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd); + if (rc) + return rc; + + MYSQL_CONNECTION_START(thd->thread_id, &thd->security_ctx->priv_user[0], + (char *) thd->security_ctx->host_or_ip); + + prepare_new_connection_state(thd); + return FALSE; +} + +bool thd_is_connection_alive(THD *thd) +{ + NET *net= &thd->net; + if (!net->error && + net->vio != 0 && + !(thd->killed == THD::KILL_CONNECTION)) + return TRUE; + return FALSE; +} + void do_handle_one_connection(THD *thd_arg) { THD *thd= thd_arg; @@ -727,22 +753,13 @@ void do_handle_one_connection(THD *thd_arg) for (;;) { - NET *net= &thd->net; bool rc; - lex_start(thd); - rc= login_connection(thd); - MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd); + rc= thd_prepare_connection(thd); if (rc) goto end_thread; - MYSQL_CONNECTION_START(thd->thread_id, &thd->security_ctx->priv_user[0], - (char *) thd->security_ctx->host_or_ip); - - prepare_new_connection_state(thd); - - while (!net->error && net->vio != 0 && - !(thd->killed == THD::KILL_CONNECTION)) + while (thd_is_connection_alive(thd)) { mysql_audit_release(thd); if (do_command(thd)) diff --git a/sql/sql_connect.h b/sql/sql_connect.h index 666db4c6462..c0cb100c779 100644 --- a/sql/sql_connect.h +++ b/sql/sql_connect.h @@ -35,6 +35,8 @@ void time_out_user_resource_limits(THD *thd, USER_CONN *uc); void decrease_user_connections(USER_CONN *uc); void thd_init_client_charset(THD *thd, uint cs_number); bool setup_connection_thread_globals(THD *thd); +bool thd_prepare_connection(THD *thd); +bool thd_is_connection_alive(THD *thd); int check_user(THD *thd, enum enum_server_command command, const char *passwd, uint passwd_len, const char *db, From af948cd6fce0878375b363b980f7432ef41273b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 10 Feb 2011 19:06:37 +0100 Subject: [PATCH 22/62] Remove no longer needed things for DBUG handling in thread pool plugins --- sql/scheduler.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sql/scheduler.h b/sql/scheduler.h index b5a175434b6..72eb56967f1 100644 --- a/sql/scheduler.h +++ b/sql/scheduler.h @@ -97,11 +97,6 @@ public: void *data; /* scheduler-specific data structure */ -# ifndef DBUG_OFF - char dbug_explain[512]; - bool set_explain; -# endif - thd_scheduler(); ~thd_scheduler(); }; From 8d319b1f29537437ecf5f93003308fc16bdcd123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 10 Feb 2011 19:24:31 +0100 Subject: [PATCH 23/62] Simplifications of server interface to scheduler --- include/mysql/thread_pool_priv.h | 18 +++++++++++++++++- sql/scheduler.cc | 10 ++++++++++ sql/scheduler.h | 8 +++----- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index 555d5fb0e7b..9bda377be13 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -34,11 +34,27 @@ */ #define MYSQL_SERVER 1 #include -#include #include #include #include +struct scheduler_functions +{ + uint max_threads; + bool (*init)(void); + bool (*init_new_connection_thread)(void); + void (*add_connection)(THD *thd); + void (*thd_wait_begin)(THD *thd, int wait_type); + void (*thd_wait_end)(THD *thd); + void (*post_kill_notification)(THD *thd); + bool (*end_thread)(THD *thd, bool cache_thread); + void (*end)(void); +}; + +/* Needed to get access to scheduler variables */ +void* thd_get_scheduler(THD *thd); +PSI_thread* thd_get_psi(THD *thd); + /* The thread pool must be able to execute commands using the connection state in THD object. This is the main objective of the thread pool to diff --git a/sql/scheduler.cc b/sql/scheduler.cc index 4c56e360e0e..d9a98f37e39 100644 --- a/sql/scheduler.cc +++ b/sql/scheduler.cc @@ -160,6 +160,16 @@ thd_scheduler::~thd_scheduler() { } +void* thd_get_scheduler(THD *thd) +{ + return thd->scheduler.data; +} + +PSI_thread* thd_get_psi(THD *thd) +{ + return thd->scheduler.m_psi; +} + static scheduler_functions *saved_thread_scheduler; static uint saved_thread_handling; diff --git a/sql/scheduler.h b/sql/scheduler.h index 72eb56967f1..31ba2ab464a 100644 --- a/sql/scheduler.h +++ b/sql/scheduler.h @@ -72,11 +72,6 @@ enum scheduler_types void one_thread_per_connection_scheduler(); void one_thread_scheduler(); -enum pool_command_op -{ - NOT_IN_USE_OP= 0, NORMAL_OP= 1, CONNECT_OP, KILL_OP, DIE_OP -}; - /* To be used for pool-of-threads (implemeneted differently on various OSs) */ @@ -101,6 +96,9 @@ public: ~thd_scheduler(); }; +void *thd_get_scheduler(THD *thd); +PSI_thread* thd_get_psi(THD *thd); + extern scheduler_functions *thread_scheduler; #endif From b173e14937ecf0976e0bdc63b22276bd09e03f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 10 Feb 2011 19:29:27 +0100 Subject: [PATCH 24/62] Removed scheduler struct for now --- include/mysql/thread_pool_priv.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index 9bda377be13..871547b9905 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -38,19 +38,6 @@ #include #include -struct scheduler_functions -{ - uint max_threads; - bool (*init)(void); - bool (*init_new_connection_thread)(void); - void (*add_connection)(THD *thd); - void (*thd_wait_begin)(THD *thd, int wait_type); - void (*thd_wait_end)(THD *thd); - void (*post_kill_notification)(THD *thd); - bool (*end_thread)(THD *thd, bool cache_thread); - void (*end)(void); -}; - /* Needed to get access to scheduler variables */ void* thd_get_scheduler(THD *thd); PSI_thread* thd_get_psi(THD *thd); From 1d6945a017aaea79cbd5657e7e2f9d5359af23a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 10 Feb 2011 19:38:36 +0100 Subject: [PATCH 25/62] more fixes of scheduler interface changes --- sql/scheduler.cc | 14 -------------- sql/sql_class.cc | 10 ++++++++++ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/sql/scheduler.cc b/sql/scheduler.cc index d9a98f37e39..328ad45b4b8 100644 --- a/sql/scheduler.cc +++ b/sql/scheduler.cc @@ -149,10 +149,6 @@ void one_thread_scheduler() thd_scheduler::thd_scheduler() : m_psi(NULL), data(NULL) { -#ifndef DBUG_OFF - dbug_explain[0]= '\0'; - set_explain= FALSE; -#endif } @@ -160,16 +156,6 @@ thd_scheduler::~thd_scheduler() { } -void* thd_get_scheduler(THD *thd) -{ - return thd->scheduler.data; -} - -PSI_thread* thd_get_psi(THD *thd) -{ - return thd->scheduler.m_psi; -} - static scheduler_functions *saved_thread_scheduler; static uint saved_thread_handling; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f2a41bee707..8d00b981533 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -217,6 +217,16 @@ bool foreign_key_prefix(Key *a, Key *b) ** Thread specific functions ****************************************************************************/ +void* thd_get_scheduler(THD *thd) +{ + return thd->scheduler.data; +} + +PSI_thread* thd_get_psi(THD *thd) +{ + return thd->scheduler.m_psi; +} + /* The following functions form part of the C plugin API */ From 503294a268893121b9bbccb6c48e5f57c246864e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 10 Feb 2011 19:47:46 +0100 Subject: [PATCH 26/62] Added setters to scheduler interface --- sql/scheduler.h | 4 +++- sql/sql_class.cc | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/sql/scheduler.h b/sql/scheduler.h index 31ba2ab464a..7cf54dec004 100644 --- a/sql/scheduler.h +++ b/sql/scheduler.h @@ -96,8 +96,10 @@ public: ~thd_scheduler(); }; -void *thd_get_scheduler(THD *thd); +void *thd_get_scheduler_data(THD *thd); +void thd_set_scheduler_data(THD *thd, void *data); PSI_thread* thd_get_psi(THD *thd); +void thd_set_psi(THD *thd, PSI_thread *psi); extern scheduler_functions *thread_scheduler; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8d00b981533..3067b86d5e1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -217,16 +217,26 @@ bool foreign_key_prefix(Key *a, Key *b) ** Thread specific functions ****************************************************************************/ -void* thd_get_scheduler(THD *thd) +void *thd_get_scheduler_data(THD *thd) { return thd->scheduler.data; } -PSI_thread* thd_get_psi(THD *thd) +void thd_set_scheduler_data(THD *thd, void *data) +{ + thd->scheduler.data= data; +} + +PSI_thread *thd_get_psi(THD *thd) { return thd->scheduler.m_psi; } +void thd_set_psi(THD *thd, PSI_thread *psi) +{ + thd->scheduler.m_psi= psi; +} + /* The following functions form part of the C plugin API */ From e5b98b918d05257aca7a066e979c5cbe93851f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Wed, 16 Feb 2011 19:30:02 +0100 Subject: [PATCH 27/62] Defined private interface to THD variables, first step to plugin API --- include/mysql/thread_pool_priv.h | 20 +++- sql/sql_class.cc | 196 +++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+), 1 deletion(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index 871547b9905..7657e5912c8 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -39,8 +39,26 @@ #include /* Needed to get access to scheduler variables */ -void* thd_get_scheduler(THD *thd); +void* thd_get_scheduler_data(THD *thd); +void thd_set_scheduler_data(THD *thd, void *data); PSI_thread* thd_get_psi(THD *thd); +void thd_set_psi(THD *thd, PSI_thread *psi); + +/* Interface to THD variables and functions */ +void thd_set_killed(THD *thd); +void thd_clear_errors(THD *thd); +void thd_set_thread_stack(THD *thd, char *stack_start); +void thd_lock_connection_data(THD *thd); +void thd_unlock_connection_data(THD *thd); +void thd_close_connection(THD *thd); +THD *thd_get_current_thd(); +void thd_new_connection_setup(THD *thd, char *stack_start); +void thd_lock_data(THD *thd); +void thd_unlock_data(THD *thd); +bool thd_is_transaction_active(THD *thd); +int thd_connection_has_data(THD *thd); +void thd_set_net_read_write(THD *thd, uint val); +void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var); /* The thread pool must be able to execute commands using the connection diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3067b86d5e1..43e55f27502 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -217,26 +217,222 @@ bool foreign_key_prefix(Key *a, Key *b) ** Thread specific functions ****************************************************************************/ +/** + Get reference to scheduler data object + + @param thd THD object + + @retval Scheduler data object on THD +*/ void *thd_get_scheduler_data(THD *thd) { return thd->scheduler.data; } +/** + Set reference to Scheduler data object for THD object + + @param thd THD object + @param psi Scheduler data object to set on THD +*/ void thd_set_scheduler_data(THD *thd, void *data) { thd->scheduler.data= data; } +/** + Get reference to Performance Schema object for THD object + + @param thd THD object + + @retval Performance schema object for thread on THD +*/ PSI_thread *thd_get_psi(THD *thd) { return thd->scheduler.m_psi; } +/** + Set reference to Performance Schema object for THD object + + @param thd THD object + @param psi Performance schema object for thread +*/ void thd_set_psi(THD *thd, PSI_thread *psi) { thd->scheduler.m_psi= psi; } +/** + Set the state on connection to killed + + @param thd THD object +*/ +void thd_set_killed(THD *thd) +{ + thd->killed= THD::KILL_CONNECTION; +} + +/** + Clear errors from the previous THD + + @param thd THD object +*/ +void thd_clear_errors(THD *thd) +{ + my_errno= 0; + thd->mysys_var->abort= 0; +} + +/** + Set thread stack in THD object + + @param thd Thread object + @param stack_start Start of stack to set in THD object +*/ +void thd_set_thread_stack(THD *thd, char *stack_start) +{ + thd->thread_stack= stack_start; +} + +/** + Lock connection data for the set of connections this connection + belongs to + + @param thd THD object +*/ +void thd_lock_connection_data(THD *thd) +{ + (void)thd; + mysql_mutex_lock(&LOCK_thread_count); +} + +/** + Lock connection data for the set of connections this connection + belongs to + + @param thd THD object +*/ +void thd_unlock_connection_data(THD *thd) +{ + (void)thd; + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); +} + +/** + Close the socket used by this connection + + @param thd THD object +*/ +void thd_close_connection(THD *thd) +{ + if (thd->net.vio) + vio_close(thd->net.vio); +} + +/** + Get current THD object from thread local data + + @retval The THD object for the thread, NULL if not connection thread +*/ +THD *thd_get_current_thd() +{ + return current_thd; +} + +/** + Set up various THD data for a new connection + + thd_new_connection_setup + + @param thd THD object + @param stack_start Start of stack for connection +*/ +void thd_new_connection_setup(THD *thd, char *stack_start) +{ +#ifdef HAVE_PSI_INTERFACE + if (PSI_server) + thd_set_psi(thd, + PSI_server->new_thread(key_thread_one_connection, + thd, + thd_get_thread_id((MYSQL_THD)thd))); +#endif + thd->set_time(); + thd->prior_thr_create_utime= thd->thr_create_utime= thd->start_utime= + my_micro_time(); + threads.append(thd); + thd_unlock_connection_data(thd); + DBUG_PRINT("info", ("init new connection. thd: 0x%lx fd: %d", + (ulong)thd, thd->net.vio->sd)); + thd_set_thread_stack(thd, stack_start); +} + +/** + Lock data that needs protection in THD object + + @param thd THD object +*/ +void thd_lock_data(THD *thd) +{ + mysql_mutex_lock(&thd->LOCK_thd_data); +} + +/** + Unlock data that needs protection in THD object + + @param thd THD object +*/ +void thd_unlock_data(THD *thd) +{ + mysql_mutex_unlock(&thd->LOCK_thd_data); +} + +/** + Support method to check if connection has already started transcaction + + @param client_cntx Low level client context + + @retval TRUE if connection already started transaction +*/ +bool thd_is_transaction_active(THD *thd) +{ + return thd->transaction.is_active(); +} + +/** + Check if there is buffered data on the socket representing the connection + + @param thd THD object +*/ +int thd_connection_has_data(THD *thd) +{ + Vio *vio= thd->net.vio; + return vio->has_data(vio); +} + +/** + Set reading/writing on socket, used by SHOW PROCESSLIST + + @param thd THD object + @param val Value to set it to (0 or 1) +*/ +void thd_set_net_read_write(THD *thd, uint val) +{ + thd->net.reading_or_writing= val; +} + +/** + Set reference to mysys variable in THD object + + @param thd THD object + @param mysys_var Reference to set +*/ +void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var) +{ + thd->set_mysys_var(mysys_var); +} + /* The following functions form part of the C plugin API */ From 715d404eea606741cf09946492989b7362108583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Wed, 16 Feb 2011 20:38:35 +0100 Subject: [PATCH 28/62] More work on interfaces --- include/mysql/thread_pool_priv.h | 19 +++++++++++-------- sql/mysqld.cc | 8 ++++++++ sql/sql_class.cc | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index 7657e5912c8..34b1d7b270f 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -59,6 +59,7 @@ bool thd_is_transaction_active(THD *thd); int thd_connection_has_data(THD *thd); void thd_set_net_read_write(THD *thd, uint val); void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var); +my_socket thd_get_fd(THD *thd); /* The thread pool must be able to execute commands using the connection @@ -85,14 +86,16 @@ bool init_new_connection_handler_thread(); /* thread_created is maintained by thread pool when activated since user threads are created by the thread pool (and also special - threads to maintain the thread pool). + threads to maintain the thread pool). This is done through + inc_thread_created. max_connections is needed to calculate the maximum number of threads - that is allowed to be started by the thread pool. + that is allowed to be started by the thread pool. The method + get_max_connections() gets reference to this variable. + connection_attrib is the thread attributes for connection threads, + the method get_connection_attrib provides a reference to these + attributes. */ -extern MYSQL_PLUGIN_IMPORT ulong thread_created; -extern MYSQL_PLUGIN_IMPORT ulong max_connections; -extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_thread_count; -extern MYSQL_PLUGIN_IMPORT pthread_attr_t connection_attrib; -/* extern MYSQL_PLUGIN_IMPORT I_List threads; */ -extern MYSQL_PLUGIN_IMPORT PSI_thread_key key_thread_one_connection; +pthread_attr_t *get_connection_attrib(void); +void inc_thread_created(void); +ulong get_max_connections(void); #endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 38dc3d6557e..8f5fed07948 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4895,6 +4895,14 @@ static bool read_init_file(char *file_name) } +/** + Increment number of created threads +*/ +void inc_thread_created(void) +{ + thread_created++; +} + #ifndef EMBEDDED_LIBRARY /* diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 43e55f27502..39f80f2307d 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -433,6 +433,38 @@ void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var) thd->set_mysys_var(mysys_var); } +/** + Get socket file descriptor for this connection + + @param thd THD object + + @retval Socket of the connection +*/ +my_socket thd_get_fd(THD *thd) +{ + return thd->net.vio->sd; +} + +/** + Get thread attributes for connection threads + + @retval Reference to thread attribute for connection threads +*/ +pthread_attr_t *get_connection_attrib(void) +{ + return &connection_attrib; +} + +/** + Get max number of connections + + @retval Max number of connections for MySQL Server +*/ +ulong get_max_connections(void) +{ + return max_connections; +} + /* The following functions form part of the C plugin API */ From 9ddd01def6bc2be23ef90314fcf5bde268d9f406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 17 Feb 2011 10:48:44 +0100 Subject: [PATCH 29/62] Further work on thread pool interface --- include/mysql/thread_pool_priv.h | 47 ++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index 34b1d7b270f..175313da78e 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (C) 2010, 2011 Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,21 +19,16 @@ #define THREAD_POOL_PRIV_INCLUDED /* - A thread pool plugins requires inclusion of sql_class.h to get proper - access to THD variables and functions. - There are some DTrace probes that requires definition inside the plugin, - this requires include of probes_mysql.h. - scheduler.h contains definitions required by the plugin. + The thread pool requires access to some MySQL server error codes, this is + accessed from mysqld_error.h. + All accesses to THD variables and functions are defined in this header file. A thread pool can also use DEBUG_SYNC and must thus include debug_sync.h To handle definitions of Information Schema plugins it is also required to include sql_profile.h and table.h. - - The goal is to move all dependencies from a thread pool plugin on the - MySQL Server into a version-handled plugin API. */ +#include /* To get ER_ERROR_ON_READ */ #define MYSQL_SERVER 1 -#include #include #include #include @@ -61,8 +56,14 @@ void thd_set_net_read_write(THD *thd, uint val); void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var); my_socket thd_get_fd(THD *thd); +/* Print to the MySQL error log */ +void sql_print_error(const char *format, ...); + +/* Store a table record */ +bool schema_table_store_record(THD *thd, TABLE *table); + /* - The thread pool must be able to execute commands using the connection + The thread pool must be able to execute statements using the connection state in THD object. This is the main objective of the thread pool to schedule the start of these commands. */ @@ -76,26 +77,38 @@ bool do_command(THD *thd); ensure that the proper MySQL Server logic attached to these events is executed. */ -bool thd_prepare_connection(THD *thd); -bool thd_is_connection_alive(THD *thd); -void end_connection(THD *thd); -void mysql_audit_release(THD *thd); -bool setup_connection_thread_globals(THD *thd); +/* Initialise a new connection handler thread */ bool init_new_connection_handler_thread(); +/* Set up connection thread before use as execution thread */ +bool setup_connection_thread_globals(THD *thd); +/* Prepare connection as part of connection set-up */ +bool thd_prepare_connection(THD *thd); +/* Release auditing before executing statement */ +void mysql_audit_release(THD *thd); +/* Check if connection is still alive */ +bool thd_is_connection_alive(THD *thd); +/* Close connection with possible error code */ +void close_connection(THD *thd, uint errcode); +/* End the connection before closing it */ +void end_connection(THD *thd); +/* Destroy THD object */ +void unlink_thd(THD *thd); /* thread_created is maintained by thread pool when activated since user threads are created by the thread pool (and also special threads to maintain the thread pool). This is done through inc_thread_created. + max_connections is needed to calculate the maximum number of threads that is allowed to be started by the thread pool. The method get_max_connections() gets reference to this variable. + connection_attrib is the thread attributes for connection threads, the method get_connection_attrib provides a reference to these attributes. */ -pthread_attr_t *get_connection_attrib(void); void inc_thread_created(void); ulong get_max_connections(void); +pthread_attr_t *get_connection_attrib(void); #endif From 78bd357d318ec4aad20cf1b212d11cbe18c07404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 17 Feb 2011 10:50:51 +0100 Subject: [PATCH 30/62] added interface to scheduler.h --- include/mysql/thread_pool_priv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index 175313da78e..61261f7505e 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -29,6 +29,7 @@ */ #include /* To get ER_ERROR_ON_READ */ #define MYSQL_SERVER 1 +#include #include #include #include From 23296fdc18e864b1b016b4c6a47723b26480f9c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Thu, 17 Feb 2011 10:57:57 +0100 Subject: [PATCH 31/62] more docs of the thread pool interface --- include/mysql/thread_pool_priv.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index 61261f7505e..e4257d0c876 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -21,6 +21,8 @@ /* The thread pool requires access to some MySQL server error codes, this is accessed from mysqld_error.h. + We need access to the struct that defines the thread pool plugin interface + which is accessed through scheduler.h. All accesses to THD variables and functions are defined in this header file. A thread pool can also use DEBUG_SYNC and must thus include debug_sync.h From cede2d8d76aa1963b0b16b0065c4fb9f75731e15 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 4 Mar 2011 12:42:20 +0100 Subject: [PATCH 32/62] Fixed wrong order of call to thd_wait service --- mysys/my_sync.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysys/my_sync.c b/mysys/my_sync.c index 3ca57055470..076b9b40642 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -56,10 +56,10 @@ int my_sync(File fd, myf my_flags) DBUG_ENTER("my_sync"); DBUG_PRINT("my",("Fd: %d my_flags: %d", fd, my_flags)); + if (before_sync_wait) + (*before_sync_wait)(); do { - if (before_sync_wait) - (*before_sync_wait)(); #if defined(F_FULLFSYNC) /* In Mac OS X >= 10.3 this call is safer than fsync() (it forces the From a193425d1e43ac87a2f5ca35860edbae25380b66 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 4 Mar 2011 12:44:49 +0100 Subject: [PATCH 33/62] Added comment on how to expand the use of the debug sync framework for scheduler --- sql/debug_sync.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index 5ec4953b546..7f69ae54037 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -1745,6 +1745,10 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) We don't use enter_cond()/exit_cond(). They do not save old mutex and cond. This would prohibit the use of DEBUG_SYNC between other places of enter_cond() and exit_cond(). + + We need to check for existence of thd->mysys_var to also make + it possible to use DEBUG_SYNC framework in scheduler when this + variable has been set to NULL. */ if (thd->mysys_var) { From fd926652dee10209f42b117aba0ca69bad411aa7 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 4 Mar 2011 12:46:48 +0100 Subject: [PATCH 34/62] Removed no longer needed header files --- sql/lock.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/sql/lock.cc b/sql/lock.cc index 79fafd48e00..2e141e1c9fb 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -82,8 +82,6 @@ #include "sql_acl.h" // SUPER_ACL #include #include -#include -#include /** @defgroup Locking Locking From 5f24be65270c844ba705de9121a95b3bb048dcc3 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 4 Mar 2011 12:53:56 +0100 Subject: [PATCH 35/62] Changed prefix from ES_ to STMT_ on Query arena state --- sql/sp_head.cc | 14 +++++++------- sql/sp_head.h | 2 +- sql/sql_class.h | 24 ++++++++++++------------ sql/sql_cursor.h | 2 +- sql/sql_prepare.cc | 18 +++++++++--------- sql/table.cc | 3 ++- 6 files changed, 32 insertions(+), 31 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index ca592574e26..000d5582be4 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -550,7 +550,7 @@ sp_head::operator delete(void *ptr, size_t size) throw() sp_head::sp_head() - :Query_arena(&main_mem_root, ES_INITIALIZED_FOR_SP), + :Query_arena(&main_mem_root, STMT_INITIALIZED_FOR_SP), m_flags(0), m_sp_cache_version(0), unsafe_flags(0), @@ -1208,7 +1208,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) Query_arena *old_arena; /* per-instruction arena */ MEM_ROOT execute_mem_root; - Query_arena execute_arena(&execute_mem_root, ES_INITIALIZED_FOR_SP), + Query_arena execute_arena(&execute_mem_root, STMT_INITIALIZED_FOR_SP), backup_arena; query_id_t old_query_id; TABLE *old_derived_tables; @@ -1488,7 +1488,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) thd->m_reprepare_observer= save_reprepare_observer; thd->stmt_arena= old_arena; - state= ES_EXECUTED; + state= STMT_EXECUTED; /* Restore the caller's original warning information area: @@ -1646,7 +1646,7 @@ sp_head::execute_trigger(THD *thd, sp_rcontext *nctx = NULL; bool err_status= FALSE; MEM_ROOT call_mem_root; - Query_arena call_arena(&call_mem_root, Query_arena::ES_INITIALIZED_FOR_SP); + Query_arena call_arena(&call_mem_root, Query_arena::STMT_INITIALIZED_FOR_SP); Query_arena backup_arena; DBUG_ENTER("sp_head::execute_trigger"); @@ -1787,7 +1787,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, String binlog_buf(buf, sizeof(buf), &my_charset_bin); bool err_status= FALSE; MEM_ROOT call_mem_root; - Query_arena call_arena(&call_mem_root, Query_arena::ES_INITIALIZED_FOR_SP); + Query_arena call_arena(&call_mem_root, Query_arena::STMT_INITIALIZED_FOR_SP); Query_arena backup_arena; DBUG_ENTER("sp_head::execute_function"); DBUG_PRINT("info", ("function %s", m_name.str)); @@ -2544,7 +2544,7 @@ sp_head::restore_thd_mem_root(THD *thd) DBUG_ENTER("sp_head::restore_thd_mem_root"); Item *flist= free_list; // The old list set_query_arena(thd); // Get new free_list and mem_root - state= ES_INITIALIZED_FOR_SP; + state= STMT_INITIALIZED_FOR_SP; DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx", (ulong) &mem_root, (ulong) &thd->mem_root)); @@ -3008,7 +3008,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, (thd->stmt_da->sql_errno() != ER_CANT_REOPEN_TABLE && thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE && thd->stmt_da->sql_errno() != ER_UPDATE_TABLE_USED)) - thd->stmt_arena->state= Query_arena::ES_EXECUTED; + thd->stmt_arena->state= Query_arena::STMT_EXECUTED; /* Merge here with the saved parent's values diff --git a/sql/sp_head.h b/sql/sp_head.h index 7ee80824b4d..4d5e2dd95ab 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -560,7 +560,7 @@ public: /// Should give each a name or type code for debugging purposes? sp_instr(uint ip, sp_pcontext *ctx) - :Query_arena(0, ES_INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx) + :Query_arena(0, STMT_INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx) {} virtual ~sp_instr() diff --git a/sql/sql_class.h b/sql/sql_class.h index 5d600eab2a3..7e63205018a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -624,14 +624,14 @@ public: /* The states relfects three diffrent life cycles for three different types of statements: - Prepared statement: ES_INITIALIZED -> ES_PREPARED -> ES_EXECUTED. - Stored procedure: ES_INITIALIZED_FOR_SP -> ES_EXECUTED. - Other statements: ES_CONVENTIONAL_EXECUTION never changes. + Prepared statement: STMT_INITIALIZED -> STMT_PREPARED -> STMT_EXECUTED. + Stored procedure: STMT_INITIALIZED_FOR_SP -> STMT_EXECUTED. + Other statements: STMT_CONVENTIONAL_EXECUTION never changes. */ enum enum_state { - ES_INITIALIZED= 0, ES_INITIALIZED_FOR_SP= 1, ES_PREPARED= 2, - ES_CONVENTIONAL_EXECUTION= 3, ES_EXECUTED= 4, ES_ERROR= -1 + STMT_INITIALIZED= 0, STMT_INITIALIZED_FOR_SP= 1, STMT_PREPARED= 2, + STMT_CONVENTIONAL_EXECUTION= 3, STMT_EXECUTED= 4, STMT_ERROR= -1 }; enum_state state; @@ -654,18 +654,18 @@ public: virtual Type type() const; virtual ~Query_arena() {}; - inline bool is_stmt_prepare() const { return state == ES_INITIALIZED; } + inline bool is_stmt_prepare() const { return state == STMT_INITIALIZED; } inline bool is_first_sp_execute() const - { return state == ES_INITIALIZED_FOR_SP; } + { return state == STMT_INITIALIZED_FOR_SP; } inline bool is_stmt_prepare_or_first_sp_execute() const - { return (int)state < (int)ES_PREPARED; } + { return (int)state < (int)STMT_PREPARED; } inline bool is_stmt_prepare_or_first_stmt_execute() const - { return (int)state <= (int)ES_PREPARED; } - inline bool is_first_stmt_execute() const { return state == ES_PREPARED; } + { return (int)state <= (int)STMT_PREPARED; } + inline bool is_first_stmt_execute() const { return state == STMT_PREPARED; } inline bool is_stmt_execute() const - { return state == ES_PREPARED || state == ES_EXECUTED; } + { return state == STMT_PREPARED || state == STMT_EXECUTED; } inline bool is_conventional() const - { return state == ES_CONVENTIONAL_EXECUTION; } + { return state == STMT_CONVENTIONAL_EXECUTION; } inline void* alloc(size_t size) { return alloc_root(mem_root,size); } inline void* calloc(size_t size) diff --git a/sql/sql_cursor.h b/sql/sql_cursor.h index 521b7771bfa..d19d14fa167 100644 --- a/sql/sql_cursor.h +++ b/sql/sql_cursor.h @@ -46,7 +46,7 @@ protected: select_result *result; public: Server_side_cursor(MEM_ROOT *mem_root_arg, select_result *result_arg) - :Query_arena(mem_root_arg, ES_INITIALIZED), result(result_arg) + :Query_arena(mem_root_arg, STMT_INITIALIZED), result(result_arg) {} virtual bool is_open() const= 0; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 847403bf053..31adbe5db36 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2712,7 +2712,7 @@ void mysqld_stmt_reset(THD *thd, char *packet) */ reset_stmt_params(stmt); - stmt->state= Query_arena::ES_PREPARED; + stmt->state= Query_arena::STMT_PREPARED; general_log_print(thd, thd->command, NullS); @@ -2830,7 +2830,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) if (param_number >= stmt->param_count) { /* Error will be sent in execute call */ - stmt->state= Query_arena::ES_ERROR; + stmt->state= Query_arena::STMT_ERROR; stmt->last_errno= ER_WRONG_ARGUMENTS; sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), "mysqld_stmt_send_long_data"); @@ -2846,7 +2846,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) if (param->set_longdata(thd->extra_data, thd->extra_length)) #endif { - stmt->state= Query_arena::ES_ERROR; + stmt->state= Query_arena::STMT_ERROR; stmt->last_errno= ER_OUTOFMEMORY; sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0); } @@ -2999,7 +2999,7 @@ end: Prepared_statement::Prepared_statement(THD *thd_arg) :Statement(NULL, &main_mem_root, - ES_INITIALIZED, ++thd_arg->statement_id_counter), + STMT_INITIALIZED, ++thd_arg->statement_id_counter), thd(thd_arg), result(thd_arg), param_array(0), @@ -3272,7 +3272,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) { setup_set_params(); lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_PREPARE; - state= Query_arena::ES_PREPARED; + state= Query_arena::STMT_PREPARED; flags&= ~ (uint) IS_IN_USE; /* @@ -3446,7 +3446,7 @@ Prepared_statement::execute_server_runnable(Server_runnable *server_runnable) Item_change_list save_change_list; thd->change_list.move_elements_to(&save_change_list); - state= ES_CONVENTIONAL_EXECUTION; + state= STMT_CONVENTIONAL_EXECUTION; if (!(lex= new (mem_root) st_lex_local)) return TRUE; @@ -3657,7 +3657,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) status_var_increment(thd->status_var.com_stmt_execute); /* Check if we got an error when sending long data */ - if (state == Query_arena::ES_ERROR) + if (state == Query_arena::STMT_ERROR) { my_message(last_errno, last_error, MYF(0)); return TRUE; @@ -3787,8 +3787,8 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) thd->set_statement(&stmt_backup); thd->stmt_arena= old_stmt_arena; - if (state == Query_arena::ES_PREPARED) - state= Query_arena::ES_EXECUTED; + if (state == Query_arena::STMT_PREPARED) + state= Query_arena::STMT_EXECUTED; if (error == 0 && this->lex->sql_command == SQLCOM_CALL) { diff --git a/sql/table.cc b/sql/table.cc index 24a37d934d2..4c7f0df624c 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1933,7 +1933,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, Query_arena *backup_stmt_arena_ptr= thd->stmt_arena; Query_arena backup_arena; - Query_arena part_func_arena(&outparam->mem_root, Query_arena::ES_INITIALIZED); + Query_arena part_func_arena(&outparam->mem_root, + Query_arena::STMT_INITIALIZED); thd->set_n_backup_active_arena(&part_func_arena, &backup_arena); thd->stmt_arena= &part_func_arena; bool tmp; From b14adc3921d3f2e30f858a31ae73ecdc65901e54 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 4 Mar 2011 13:12:31 +0100 Subject: [PATCH 36/62] More review fixes --- include/my_sys.h | 4 ++-- include/mysql/plugin_audit.h.pp | 4 ++-- include/mysql/plugin_auth.h.pp | 4 ++-- include/mysql/plugin_ftparser.h.pp | 4 ++-- include/mysql/service_thd_wait.h | 4 ++-- sql/item_func.cc | 8 ++++---- sql/mdl.cc | 4 ++-- sql/scheduler.cc | 3 +++ 8 files changed, 19 insertions(+), 16 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index ed96abc7711..e13ef1af067 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -627,8 +627,8 @@ extern FILE *my_freopen(const char *path, const char *mode, FILE *stream); extern int my_fclose(FILE *fd,myf MyFlags); extern File my_fileno(FILE *fd); extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); -void thr_set_sync_wait_callback(void (*before_sync)(void), - void (*after_sync)(void)); +extern void thr_set_sync_wait_callback(void (*before_sync)(void), + void (*after_sync)(void)); extern int my_sync(File fd, myf my_flags); extern int my_sync_dir(const char *dir_name, myf my_flags); extern int my_sync_dir_by_file(const char *file_name, myf my_flags); diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index f74078c531f..732503e176a 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -46,10 +46,10 @@ typedef enum _thd_wait_type_e { THD_WAIT_LAST= 11 } thd_wait_type; extern struct thd_wait_service_st { - void (*thd_wait_begin_func)(void*, thd_wait_type); + void (*thd_wait_begin_func)(void*, int); void (*thd_wait_end_func)(void*); } *thd_wait_service; -void thd_wait_begin(void* thd, thd_wait_type wait_type); +void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); #include struct scheduler_functions; diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index aed764ddb51..e65278c518e 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -46,10 +46,10 @@ typedef enum _thd_wait_type_e { THD_WAIT_LAST= 11 } thd_wait_type; extern struct thd_wait_service_st { - void (*thd_wait_begin_func)(void*, thd_wait_type); + void (*thd_wait_begin_func)(void*, int); void (*thd_wait_end_func)(void*); } *thd_wait_service; -void thd_wait_begin(void* thd, thd_wait_type wait_type); +void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); #include struct scheduler_functions; diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index f3ca2070e60..c29eac45b19 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -46,10 +46,10 @@ typedef enum _thd_wait_type_e { THD_WAIT_LAST= 11 } thd_wait_type; extern struct thd_wait_service_st { - void (*thd_wait_begin_func)(void*, thd_wait_type); + void (*thd_wait_begin_func)(void*, int); void (*thd_wait_end_func)(void*); } *thd_wait_service; -void thd_wait_begin(void* thd, thd_wait_type wait_type); +void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); #include struct scheduler_functions; diff --git a/include/mysql/service_thd_wait.h b/include/mysql/service_thd_wait.h index a7ce2dbf501..f5d2a75f5fc 100644 --- a/include/mysql/service_thd_wait.h +++ b/include/mysql/service_thd_wait.h @@ -78,7 +78,7 @@ typedef enum _thd_wait_type_e { } thd_wait_type; extern struct thd_wait_service_st { - void (*thd_wait_begin_func)(MYSQL_THD, thd_wait_type); + void (*thd_wait_begin_func)(MYSQL_THD, int); void (*thd_wait_end_func)(MYSQL_THD); } *thd_wait_service; @@ -90,7 +90,7 @@ extern struct thd_wait_service_st { #else -void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type); +void thd_wait_begin(MYSQL_THD thd, int wait_type); void thd_wait_end(MYSQL_THD thd); #endif diff --git a/sql/item_func.cc b/sql/item_func.cc index 9195cf4f8c7..a149bb7f955 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3877,12 +3877,11 @@ longlong Item_func_get_lock::val_int() timed_cond.set_timeout(timeout * ULL(1000000000)); error= 0; + thd_wait_begin(thd, THD_WAIT_USER_LOCK); while (ull->locked && !thd->killed) { DBUG_PRINT("info", ("waiting on lock")); - thd_wait_begin(thd, THD_WAIT_USER_LOCK); error= timed_cond.wait(&ull->cond, &LOCK_user_locks); - thd_wait_end(thd); if (error == ETIMEDOUT || error == ETIME) { DBUG_PRINT("info", ("lock wait timeout")); @@ -3890,6 +3889,7 @@ longlong Item_func_get_lock::val_int() } error= 0; } + thd_wait_end(thd); if (ull->locked) { @@ -4107,15 +4107,15 @@ longlong Item_func_sleep::val_int() thd->mysys_var->current_cond= &cond; error= 0; + thd_wait_begin(thd, THD_WAIT_SLEEP); while (!thd->killed) { - thd_wait_begin(thd, THD_WAIT_SLEEP); error= timed_cond.wait(&cond, &LOCK_user_locks); - thd_wait_end(thd); if (error == ETIMEDOUT || error == ETIME) break; error= 0; } + thd_wait_end(thd); thd_proc_info(thd, 0); mysql_mutex_unlock(&LOCK_user_locks); mysql_mutex_lock(&thd->mysys_var->mutex); diff --git a/sql/mdl.cc b/sql/mdl.cc index 6cab1238b43..21410db2d22 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -975,14 +975,14 @@ MDL_wait::timed_wait(THD *thd, struct timespec *abs_timeout, old_msg= thd_enter_cond(thd, &m_COND_wait_status, &m_LOCK_wait_status, wait_state_name); + thd_wait_begin(thd, THD_WAIT_META_DATA_LOCK); while (!m_wait_status && !thd_killed(thd) && wait_result != ETIMEDOUT && wait_result != ETIME) { - thd_wait_begin(thd, THD_WAIT_META_DATA_LOCK); wait_result= mysql_cond_timedwait(&m_COND_wait_status, &m_LOCK_wait_status, abs_timeout); - thd_wait_end(thd); } + thd_wait_end(thd); if (m_wait_status == EMPTY) { diff --git a/sql/scheduler.cc b/sql/scheduler.cc index 328ad45b4b8..a3848e20be5 100644 --- a/sql/scheduler.cc +++ b/sql/scheduler.cc @@ -80,6 +80,8 @@ scheduler_functions *thread_scheduler= NULL; */ /**@{*/ +extern "C" +{ static void scheduler_wait_lock_begin(void) { MYSQL_CALLBACK(thread_scheduler, thd_wait_begin, (current_thd, THD_WAIT_TABLE_LOCK)); @@ -97,6 +99,7 @@ static void scheduler_wait_sync_begin(void) { static void scheduler_wait_sync_end(void) { MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd)); } +}; /**@}*/ /** From 7e1f962af46ba2fef89aa093fb177639f4ac7204 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 4 Mar 2011 13:17:58 +0100 Subject: [PATCH 37/62] Further review fixes --- sql/sql_class.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 39f80f2307d..3061cf9deda 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -742,7 +742,7 @@ bool Drop_table_error_handler::handle_condition(THD *thd, THD::THD() - :Statement(&main_lex, &main_mem_root, ES_CONVENTIONAL_EXECUTION, + :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION, /* statement id */ 0), rli_fake(0), user_time(0), in_sub_stmt(0), @@ -3550,7 +3550,7 @@ extern "C" void thd_pool_wait_end(MYSQL_THD thd); thd_wait_end MUST be called immediately after waking up again. */ -extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type) +extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type) { MYSQL_CALLBACK(thread_scheduler, thd_wait_begin, (thd, wait_type)); } @@ -3566,7 +3566,7 @@ extern "C" void thd_wait_end(MYSQL_THD thd) MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (thd)); } #else -extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type) +extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type) { /* do NOTHING for the embedded library */ return; From 7e3b316ecdcfc5711ea861470dc578ef701e8e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Fri, 15 Apr 2011 12:57:59 +0200 Subject: [PATCH 38/62] Use C++ manner for unused param instead of C manner --- sql/sql_class.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3061cf9deda..8f5d7f05033 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -301,9 +301,8 @@ void thd_set_thread_stack(THD *thd, char *stack_start) @param thd THD object */ -void thd_lock_connection_data(THD *thd) +void thd_lock_connection_data(THD *) { - (void)thd; mysql_mutex_lock(&LOCK_thread_count); } @@ -313,9 +312,8 @@ void thd_lock_connection_data(THD *thd) @param thd THD object */ -void thd_unlock_connection_data(THD *thd) +void thd_unlock_connection_data(THD *) { - (void)thd; mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); } From 60f8d6ab09158570c244faffe177ab26b2b1eb93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Fri, 15 Apr 2011 13:00:59 +0200 Subject: [PATCH 39/62] Changed name to better reflect function logic in accordance with WL#5788 --- sql/sql_class.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8f5d7f05033..21aed554ace 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -301,7 +301,7 @@ void thd_set_thread_stack(THD *thd, char *stack_start) @param thd THD object */ -void thd_lock_connection_data(THD *) +void thd_lock_thread_count(THD *) { mysql_mutex_lock(&LOCK_thread_count); } @@ -312,7 +312,7 @@ void thd_lock_connection_data(THD *) @param thd THD object */ -void thd_unlock_connection_data(THD *) +void thd_unlock_thread_count(THD *) { mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); From 55557e223f6c89b16cbed2fecd90c26b519b6b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Fri, 15 Apr 2011 13:02:29 +0200 Subject: [PATCH 40/62] Changed name to better reflect function logic in accordance with WL#5788 --- include/mysql/thread_pool_priv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index e4257d0c876..3f4cf371024 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -46,8 +46,8 @@ void thd_set_psi(THD *thd, PSI_thread *psi); void thd_set_killed(THD *thd); void thd_clear_errors(THD *thd); void thd_set_thread_stack(THD *thd, char *stack_start); -void thd_lock_connection_data(THD *thd); -void thd_unlock_connection_data(THD *thd); +void thd_lock_thread_count(THD *thd); +void thd_unlock_thread_count(THD *thd); void thd_close_connection(THD *thd); THD *thd_get_current_thd(); void thd_new_connection_setup(THD *thd, char *stack_start); From 18da718b77aae43ac0d641ec91e385e55d7b1360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Fri, 15 Apr 2011 15:47:26 +0200 Subject: [PATCH 41/62] Merge step 2 From 8b8b0b2776d9d78778097f7c37e2499677e68bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Fri, 15 Apr 2011 15:58:30 +0200 Subject: [PATCH 42/62] Merge 5.5, step 3 --- storage/innobase/ibuf/ibuf0ibuf.c | 2 +- storage/innobase/include/buf0rea.h | 1 - storage/innobase/include/ibuf0ibuf.h | 2 +- storage/innobase/mtr/mtr0mtr.c | 1 - 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index 6771ab219a4..8110bccc162 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -325,7 +325,7 @@ dropped! So, there seems to be no problem. */ /******************************************************************//** Sets the flag in the current mini-transaction record indicating we're inside an insert buffer routine. */ -UNIV_INTERN +UNIV_INLINE void ibuf_enter( /*=======*/ diff --git a/storage/innobase/include/buf0rea.h b/storage/innobase/include/buf0rea.h index 9906981209a..cdf6cdba3d1 100644 --- a/storage/innobase/include/buf0rea.h +++ b/storage/innobase/include/buf0rea.h @@ -28,7 +28,6 @@ Created 11/5/1995 Heikki Tuuri #include "univ.i" #include "buf0types.h" -#include "mtr0types.h" /********************************************************************//** High-level function which reads a page asynchronously from a file to the diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 0f1cb0fe688..28c97fd609f 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -234,7 +234,7 @@ ibuf_should_try( a secondary index when we decide */ /******************************************************************//** -Returns TRUE if the current MTR is performing an insert buffer +Returns TRUE if the current OS thread is performing an insert buffer routine. For instance, a read-ahead of non-ibuf pages is forbidden by threads diff --git a/storage/innobase/mtr/mtr0mtr.c b/storage/innobase/mtr/mtr0mtr.c index 877cb93b926..88e698ed818 100644 --- a/storage/innobase/mtr/mtr0mtr.c +++ b/storage/innobase/mtr/mtr0mtr.c @@ -268,7 +268,6 @@ mtr_commit( ut_d(mtr->state = MTR_COMMITTED); dyn_array_free(&(mtr->memo)); dyn_array_free(&(mtr->log)); - mtr->ibuf_inside = FALSE; } #ifndef UNIV_HOTBACKUP From d31a06b6c98c670d89ff4d709ccf7a4cf5c34824 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Wed, 20 Apr 2011 15:07:19 +0200 Subject: [PATCH 43/62] Fixed missing change of thd_unlock_connection_data to thd_unlock_thread_count --- sql/sql_class.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index dd245d6ccab..026166726b2 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -359,7 +359,7 @@ void thd_new_connection_setup(THD *thd, char *stack_start) thd->prior_thr_create_utime= thd->thr_create_utime= thd->start_utime= my_micro_time(); threads.append(thd); - thd_unlock_connection_data(thd); + thd_unlock_thread_count(thd); DBUG_PRINT("info", ("init new connection. thd: 0x%lx fd: %d", (ulong)thd, thd->net.vio->sd)); thd_set_thread_stack(thd, stack_start); From f24588519c6549313a87e2fe3aa72d23c1616d68 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Wed, 20 Apr 2011 15:15:47 +0200 Subject: [PATCH 44/62] Fixed error in merge --- sql/sql_prepare.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index dd16bda60ec..74505c06a77 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3401,7 +3401,7 @@ Prepared_statement::execute_loop(String *expanded_query, int reprepare_attempt= 0; /* Check if we got an error when sending long data */ - if (state == Query_arena::ERROR) + if (state == Query_arena::STMT_ERROR) { my_message(last_errno, last_error, MYF(0)); return TRUE; From 28f55273713991769f6e6e088d0c5967870eac8f Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Wed, 4 May 2011 10:42:48 +0200 Subject: [PATCH 45/62] Make MY_ALIGNED usable to define alignment of data structures --- include/my_compiler.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/my_compiler.h b/include/my_compiler.h index 5f898621159..e55346d62fd 100644 --- a/include/my_compiler.h +++ b/include/my_compiler.h @@ -140,6 +140,14 @@ struct my_aligned_storage #endif /* __cplusplus */ +# if defined(MY_ALIGNED) +/* + Make sure MY_ALIGNED can be used also on platforms where we don't + have a way of aligning data structures. +*/ +#define MY_ALIGNED(size) +#endif + #include #endif /* MY_COMPILER_INCLUDED */ From cb961461f28daf32d479f931f21c52509d4be3c0 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Wed, 4 May 2011 10:45:51 +0200 Subject: [PATCH 46/62] Make MY_ALIGNED usable to define alignment of data structures --- include/my_compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_compiler.h b/include/my_compiler.h index e55346d62fd..e3ff80fad40 100644 --- a/include/my_compiler.h +++ b/include/my_compiler.h @@ -140,7 +140,7 @@ struct my_aligned_storage #endif /* __cplusplus */ -# if defined(MY_ALIGNED) +# ifndef MY_ALIGNED /* Make sure MY_ALIGNED can be used also on platforms where we don't have a way of aligning data structures. From e9b8feef3253d3169157c9316eb7e6946909896b Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Thu, 12 May 2011 14:56:00 +0200 Subject: [PATCH 47/62] Bug#12346411 SQL/LOG.CC:6509: ASSERTION `PREPARED_XIDS > 0' FAILED This assert could be triggered during two phase commit if binary log was used as transaction coordinator log. The triggered assert checks that the same number of transaction IDs are processed in the prepare and commit phases. The reason it was triggered, was that the transaction consisted of an INSERT/UPDATE IGNORE that had an ignorable error. Since it had an error, no row log events were made and therefore prepared_xids was 0. However, since it was an IGNORE statement, the statement started a read/write statement transaction, committed it and completed successfully. This patch fixes the problem by adjusting the assert to take this possibility into account. Test case added to binlog.binlog_innodb_row.test. --- .../suite/binlog/r/binlog_innodb_row.result | 17 ++++++++++++ .../suite/binlog/t/binlog_innodb_row.test | 26 +++++++++++++++++++ sql/log.cc | 7 +++-- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_innodb_row.result b/mysql-test/suite/binlog/r/binlog_innodb_row.result index 093628c29cc..61f961f16da 100644 --- a/mysql-test/suite/binlog/r/binlog_innodb_row.result +++ b/mysql-test/suite/binlog/r/binlog_innodb_row.result @@ -59,3 +59,20 @@ show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE IF EXISTS `t1` /* generated by server */ ############################################### +# +# Bug#12346411 SQL/LOG.CC:6509: ASSERTION `PREPARED_XIDS > 0' FAILED +# +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1(a INT PRIMARY KEY) engine=innodb; +CREATE TABLE t2(a INT) engine=myisam; +INSERT INTO t1 VALUES (1); +START TRANSACTION; +INSERT INTO t2 VALUES (1); +INSERT IGNORE INTO t1 VALUES (1); +COMMIT; +INSERT INTO t1 VALUES (2); +START TRANSACTION; +INSERT INTO t2 VALUES (2); +UPDATE IGNORE t1 SET a=1 WHERE a=2; +COMMIT; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/binlog/t/binlog_innodb_row.test b/mysql-test/suite/binlog/t/binlog_innodb_row.test index b491510c9c9..f4ad1058a7e 100644 --- a/mysql-test/suite/binlog/t/binlog_innodb_row.test +++ b/mysql-test/suite/binlog/t/binlog_innodb_row.test @@ -77,3 +77,29 @@ DROP TEMPORARY TABLE t1; -- echo ############################################### -- source include/show_binlog_events.inc -- echo ############################################### + + +--echo # +--echo # Bug#12346411 SQL/LOG.CC:6509: ASSERTION `PREPARED_XIDS > 0' FAILED +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1(a INT PRIMARY KEY) engine=innodb; +CREATE TABLE t2(a INT) engine=myisam; + +INSERT INTO t1 VALUES (1); +START TRANSACTION; +INSERT INTO t2 VALUES (1); +INSERT IGNORE INTO t1 VALUES (1); +COMMIT; + +INSERT INTO t1 VALUES (2); +START TRANSACTION; +INSERT INTO t2 VALUES (2); +UPDATE IGNORE t1 SET a=1 WHERE a=2; +COMMIT; + +DROP TABLE t1, t2; diff --git a/sql/log.cc b/sql/log.cc index fe782c5d621..8f5db98a345 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6506,8 +6506,11 @@ int TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid) { DBUG_ENTER("TC_LOG_BINLOG::unlog"); mysql_mutex_lock(&LOCK_prep_xids); - DBUG_ASSERT(prepared_xids > 0); - if (--prepared_xids == 0) { + // prepared_xids can be 0 if the transaction had ignorable errors. + DBUG_ASSERT(prepared_xids >= 0); + if (prepared_xids > 0) + prepared_xids--; + if (prepared_xids == 0) { DBUG_PRINT("info", ("prepared_xids=%lu", prepared_xids)); mysql_cond_signal(&COND_prep_xids); } From d25b5b686b400a7640ff6459feb6db229354118d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 May 2011 18:22:14 -0400 Subject: [PATCH 48/62] BUG#12549572 : CMake file does not include gcov option This patch inserts an 'ENABLE_GCOV' option for enabling gcov compilation on Linux machines. It modifies the CMakeLists.txt setting this option to 'OFF' by default. Note: The option requires a debug build. For example, -DCMAKE_BUILD_TYPE:string="Debug" --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 235a65a6437..6766f76c665 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,6 +172,13 @@ IF(ENABLE_DEBUG_SYNC) SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC") ENDIF() +OPTION(ENABLE_GCOV "Enable gcov (debug, Linux builds only)" OFF) +IF (ENABLE_GCOV AND NOT WIN32 AND NOT APPLE) + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") + SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage -lgcov") +ENDIF() + OPTION(ENABLED_LOCAL_INFILE "If we should should enable LOAD DATA LOCAL by default" ${IF_WIN}) MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE) From cb0f843e8da38c36f230b5666829824c992b9f5a Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Fri, 13 May 2011 07:00:09 +0200 Subject: [PATCH 49/62] changed the VERSION tag to 14 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 796544a7013..f0a5c1203ed 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=15 +MYSQL_VERSION_PATCH=14 MYSQL_VERSION_EXTRA= From e2602f4eab51adc75bfa44f853ccc14c21130be7 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 13 May 2011 15:46:35 +0200 Subject: [PATCH 50/62] Removed variables no longer needed in plugins, moved to methods instead --- sql/mysqld.cc | 15 ++++++--------- sql/mysqld.h | 10 ++++------ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f078c703a1a..6776f04758f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -447,7 +447,7 @@ uint lower_case_table_names; ulong tc_heuristic_recover= 0; uint volatile thread_count; int32 thread_running; -MYSQL_PLUGIN_IMPORT ulong thread_created; +ulong thread_created; ulong back_log, connect_timeout, concurrency, server_id; ulong table_cache_size, table_def_size; ulong what_to_log; @@ -474,8 +474,7 @@ ulong delayed_insert_errors,flush_time; ulong specialflag=0; ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0; -MYSQL_PLUGIN_IMPORT ulong max_connections; -ulong max_connect_errors; +ulong max_connections, max_connect_errors; /* Maximum length of parameter value which can be set through mysql_send_long_data() call. @@ -583,7 +582,7 @@ Le_creator le_creator; MYSQL_FILE *bootstrap_file; int bootstrap_error; -MYSQL_PLUGIN_IMPORT I_List threads; +I_List threads; Rpl_filter* rpl_filter; Rpl_filter* binlog_filter; @@ -632,9 +631,9 @@ mysql_mutex_t LOCK_des_key_file; #endif mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; mysql_rwlock_t LOCK_system_variables_hash; -MYSQL_PLUGIN_IMPORT mysql_cond_t COND_thread_count; +mysql_cond_t COND_thread_count; pthread_t signal_thread; -MYSQL_PLUGIN_IMPORT pthread_attr_t connection_attrib; +pthread_attr_t connection_attrib; mysql_mutex_t LOCK_server_started; mysql_cond_t COND_server_started; @@ -7871,9 +7870,7 @@ static PSI_cond_info all_server_conds[]= PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, key_thread_handle_manager, key_thread_main, - key_thread_signal_hand; - -MYSQL_PLUGIN_IMPORT PSI_thread_key key_thread_one_connection; + key_thread_one_connection, key_thread_signal_hand; static PSI_thread_info all_server_threads[]= { diff --git a/sql/mysqld.h b/sql/mysqld.h index 4469e7f47be..303ee5bec0f 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -206,12 +206,12 @@ extern struct my_option my_long_options[]; extern int mysqld_server_started; extern "C" MYSQL_PLUGIN_IMPORT int orig_argc; extern "C" MYSQL_PLUGIN_IMPORT char **orig_argv; -extern MYSQL_PLUGIN_IMPORT pthread_attr_t connection_attrib; +extern pthread_attr_t connection_attrib; extern MYSQL_FILE *bootstrap_file; extern my_bool old_mode; extern LEX_STRING opt_init_connect, opt_init_slave; extern int bootstrap_error; -extern MYSQL_PLUGIN_IMPORT I_List threads; +extern I_List threads; extern char err_shared_dir[]; extern TYPELIB thread_handling_typelib; extern my_decimal decimal_zero; @@ -267,9 +267,7 @@ extern PSI_cond_key key_RELAYLOG_update_cond; extern PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, key_thread_handle_manager, key_thread_kill_server, key_thread_main, - key_thread_signal_hand; - -extern MYSQL_PLUGIN_IMPORT PSI_thread_key key_thread_one_connection; + key_thread_one_connection, key_thread_signal_hand; #ifdef HAVE_MMAP extern PSI_file_key key_file_map; @@ -342,7 +340,7 @@ extern mysql_mutex_t LOCK_server_started; extern mysql_cond_t COND_server_started; extern mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; extern mysql_rwlock_t LOCK_system_variables_hash; -extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_thread_count; +extern mysql_cond_t COND_thread_count; extern mysql_cond_t COND_manager; extern int32 thread_running; extern my_atomic_rwlock_t thread_running_lock; From d343f5e372bbd306b770966940c162172987151a Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Fri, 13 May 2011 18:04:49 +0200 Subject: [PATCH 51/62] Bug#12552516 LF_HASH REQUIRES MY_THREAD_INIT() Before this fix, a thread instrumented for the performance schema, that would perform file io operations, could crash inside the LF_HASH implementation, in cases when my_thread_init is not called. The crash itself has not been reported in 5.5 but similar crashes have been found in 5.6-based development branches, using LF_HASH for more instrumentation. The possibility of a crash in 5.5 is confirmed by code analysis. The problem is that, when my_thread_init() is not called, which can happen for threads in storage engines or thirs party code, my_thread_var is NULL. Using my_thread_var->stacks_ends_here in mysys/lf_alloc-pin.c is unsafe. Given that my_thread_var is used: - only for stacks_ends_here - only on platform with HAVE_ALLOCA - only when there is enough room on the stack and given that the LF_HASH implementation has a fallback algorythm implemented already when using alloca is not possible, using my_thread_var->stacks_ends_here is in fact not a strict requirement, and can be relaxed. The fix is to: - test explicitly if my_thread_var is NULL, to account for cases when my_thread_init() is not used by the calling thread. - not use alloca in this case, and rely on the fall back code already in place. so that the LF_HASH can be supported even without my_thread_init(). The implementation of mysys/lf_alloc-pin.c has been fixed to support this new usage. The units tests in unittest/mysys/lf-t.c have been adjusted accordingly. --- mysys/lf_alloc-pin.c | 47 ++++++++++++++++++++++++++----------------- unittest/mysys/lf-t.c | 37 +++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index 4ed01ac8083..cef51c89076 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -146,6 +146,7 @@ void lf_pinbox_destroy(LF_PINBOX *pinbox) */ LF_PINS *_lf_pinbox_get_pins(LF_PINBOX *pinbox) { + struct st_my_thread_var *var; uint32 pins, next, top_ver; LF_PINS *el; /* @@ -188,7 +189,12 @@ LF_PINS *_lf_pinbox_get_pins(LF_PINBOX *pinbox) el->link= pins; el->purgatory_count= 0; el->pinbox= pinbox; - el->stack_ends_here= & my_thread_var->stack_ends_here; + var= my_thread_var; + /* + Threads that do not call my_thread_init() should still be + able to use the LF_HASH. + */ + el->stack_ends_here= (var ? & var->stack_ends_here : NULL); return el; } @@ -327,34 +333,37 @@ static int match_pins(LF_PINS *el, void *addr) */ static void _lf_pinbox_real_free(LF_PINS *pins) { - int npins, alloca_size; - void *list, **addr; + int npins; + void *list; + void **addr= NULL; void *first= NULL, *last= NULL; LF_PINBOX *pinbox= pins->pinbox; npins= pinbox->pins_in_array+1; #ifdef HAVE_ALLOCA - alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins; - /* create a sorted list of pinned addresses, to speed up searches */ - if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size) + if (pins->stack_ends_here != NULL) { - struct st_harvester hv; - addr= (void **) alloca(alloca_size); - hv.granary= addr; - hv.npins= npins; - /* scan the dynarray and accumulate all pinned addresses */ - _lf_dynarray_iterate(&pinbox->pinarray, - (lf_dynarray_func)harvest_pins, &hv); + int alloca_size; + alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins; + /* create a sorted list of pinned addresses, to speed up searches */ + if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size) + { + struct st_harvester hv; + addr= (void **) alloca(alloca_size); + hv.granary= addr; + hv.npins= npins; + /* scan the dynarray and accumulate all pinned addresses */ + _lf_dynarray_iterate(&pinbox->pinarray, + (lf_dynarray_func)harvest_pins, &hv); - npins= hv.granary-addr; - /* and sort them */ - if (npins) - qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp); + npins= hv.granary-addr; + /* and sort them */ + if (npins) + qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp); + } } - else #endif - addr= 0; list= pins->purgatory; pins->purgatory= 0; diff --git a/unittest/mysys/lf-t.c b/unittest/mysys/lf-t.c index 61b7ae08cf5..c04ef358abe 100644 --- a/unittest/mysys/lf-t.c +++ b/unittest/mysys/lf-t.c @@ -27,6 +27,8 @@ int32 inserts= 0, N; LF_ALLOCATOR lf_allocator; LF_HASH lf_hash; +int with_my_thread_init=0; + /* pin allocator - alloc and release an element in a loop */ @@ -36,7 +38,8 @@ pthread_handler_t test_lf_pinbox(void *arg) int32 x= 0; LF_PINS *pins; - my_thread_init(); + if (with_my_thread_init) + my_thread_init(); pins= lf_pinbox_get_pins(&lf_allocator.pinbox); @@ -49,7 +52,10 @@ pthread_handler_t test_lf_pinbox(void *arg) pthread_mutex_lock(&mutex); if (!--running_threads) pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); - my_thread_end(); + + if (with_my_thread_init) + my_thread_end(); + return 0; } @@ -68,7 +74,8 @@ pthread_handler_t test_lf_alloc(void *arg) int32 x,y= 0; LF_PINS *pins; - my_thread_init(); + if (with_my_thread_init) + my_thread_init(); pins= lf_alloc_get_pins(&lf_allocator); @@ -101,7 +108,9 @@ pthread_handler_t test_lf_alloc(void *arg) } if (!--running_threads) pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); - my_thread_end(); + + if (with_my_thread_init) + my_thread_end(); return 0; } @@ -112,7 +121,8 @@ pthread_handler_t test_lf_hash(void *arg) int32 x,y,z,sum= 0, ins= 0; LF_PINS *pins; - my_thread_init(); + if (with_my_thread_init) + my_thread_init(); pins= lf_hash_get_pins(&lf_hash); @@ -152,14 +162,15 @@ pthread_handler_t test_lf_hash(void *arg) } if (!--running_threads) pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); - my_thread_end(); + if (with_my_thread_init) + my_thread_end(); return 0; } void do_tests() { - plan(4); + plan(7); lf_alloc_init(&lf_allocator, sizeof(TLA), offsetof(TLA, not_used)); lf_hash_init(&lf_hash, sizeof(int), LF_HASH_UNIQUE, 0, sizeof(int), 0, @@ -168,9 +179,15 @@ void do_tests() bad= my_atomic_initialize(); ok(!bad, "my_atomic_initialize() returned %d", bad); - test_concurrently("lf_pinbox", test_lf_pinbox, N= THREADS, CYCLES); - test_concurrently("lf_alloc", test_lf_alloc, N= THREADS, CYCLES); - test_concurrently("lf_hash", test_lf_hash, N= THREADS, CYCLES/10); + with_my_thread_init= 1; + test_concurrently("lf_pinbox (with my_thread_init)", test_lf_pinbox, N= THREADS, CYCLES); + test_concurrently("lf_alloc (with my_thread_init)", test_lf_alloc, N= THREADS, CYCLES); + test_concurrently("lf_hash (with my_thread_init)", test_lf_hash, N= THREADS, CYCLES/10); + + with_my_thread_init= 0; + test_concurrently("lf_pinbox (without my_thread_init)", test_lf_pinbox, N= THREADS, CYCLES); + test_concurrently("lf_alloc (without my_thread_init)", test_lf_alloc, N= THREADS, CYCLES); + test_concurrently("lf_hash (without my_thread_init)", test_lf_hash, N= THREADS, CYCLES/10); lf_hash_destroy(&lf_hash); lf_alloc_destroy(&lf_allocator); From 91133804d1a800bed4e43c07e8f26d9345c78420 Mon Sep 17 00:00:00 2001 From: Vinay Fisrekar Date: Sat, 14 May 2011 21:44:49 +0530 Subject: [PATCH 52/62] Adding bug scenario for data types in main suite Impementing Test Review Comment. Bug test scenario: SELECT is not returning result set for "equal" (=) and "NULL safe equal operator" (<=>) on BIT data type. Extending this scenario for all data types --- .../r/implicit_char_to_num_conversion.result | 366 ++++++++++++++++++ .../t/implicit_char_to_num_conversion.test | 174 +++++++++ 2 files changed, 540 insertions(+) create mode 100644 mysql-test/r/implicit_char_to_num_conversion.result create mode 100644 mysql-test/t/implicit_char_to_num_conversion.test diff --git a/mysql-test/r/implicit_char_to_num_conversion.result b/mysql-test/r/implicit_char_to_num_conversion.result new file mode 100644 index 00000000000..8f24a6b293c --- /dev/null +++ b/mysql-test/r/implicit_char_to_num_conversion.result @@ -0,0 +1,366 @@ +DROP TABLE IF EXISTS t5; +CREATE TABLE t5(c1 BIT(2) PRIMARY KEY) ENGINE = ; +INSERT INTO t5 VALUES (0), (1), (2); +SELECT HEX(c1) FROM t5 ORDER BY c1; +HEX(c1) +0 +1 +2 +SELECT HEX(c1) FROM t5 WHERE c1 = b'1' ORDER BY c1; +HEX(c1) +1 +SELECT HEX(c1) FROM t5 WHERE c1 <=> b'1' ORDER BY c1; +HEX(c1) +1 +SELECT HEX(c1) FROM t5 WHERE c1 != b'1' ORDER BY c1; +HEX(c1) +0 +2 +SELECT HEX(c1) FROM t5 WHERE c1 >= '1' ORDER BY c1; +HEX(c1) +1 +2 +SELECT HEX(c1) FROM t5 WHERE c1 <= '1' ORDER BY c1; +HEX(c1) +0 +1 +SELECT HEX(c1) FROM t5 WHERE c1 < '1' ORDER BY c1; +HEX(c1) +0 +SELECT HEX(c1) FROM t5 WHERE c1 > '0' ORDER BY c1; +HEX(c1) +1 +2 +DROP TABLE t5; +CREATE TABLE t5(c1 FLOAT(5,2) PRIMARY KEY) ENGINE = ; +INSERT INTO t5 VALUES (95.95), (-10.10), (1), (0); +SELECT c1 FROM t5 ORDER BY c1; +c1 +-10.10 +0.00 +1.00 +95.95 +SELECT c1 FROM t5 WHERE c1 >= '95' ORDER BY c1; +c1 +95.95 +SELECT c1 FROM t5 WHERE c1 <= '10.10' ORDER BY c1; +c1 +-10.10 +0.00 +1.00 +SELECT c1 FROM t5 WHERE c1 != '1' ORDER BY c1; +c1 +-10.10 +0.00 +95.95 +SELECT c1 FROM t5 WHERE c1 < '1' ORDER BY c1; +c1 +-10.10 +0.00 +SELECT c1 FROM t5 WHERE c1 > '0' ORDER BY c1; +c1 +1.00 +95.95 +DROP TABLE t5; +CREATE TABLE t5(c1 TINYINT PRIMARY KEY) ENGINE = ; +INSERT INTO t5 VALUES (95), (10),(11),(-8); +SELECT c1 FROM t5 ORDER BY c1; +c1 +-8 +10 +11 +95 +SELECT c1 FROM t5 WHERE c1 = '10' ORDER BY c1; +c1 +10 +SELECT c1 FROM t5 WHERE c1 <=> '10' ORDER BY c1; +c1 +10 +SELECT c1 FROM t5 WHERE c1 >= '95' ORDER BY c1; +c1 +95 +SELECT c1 FROM t5 WHERE c1 <= '11' ORDER BY c1; +c1 +-8 +10 +11 +SELECT c1 FROM t5 WHERE c1 != '-8' ORDER BY c1; +c1 +10 +11 +95 +SELECT c1 FROM t5 WHERE c1 < '11' ORDER BY c1; +c1 +-8 +10 +SELECT c1 FROM t5 WHERE c1 > '10' ORDER BY c1; +c1 +11 +95 +DROP TABLE t5; +CREATE TABLE t5(c1 SMALLINT PRIMARY KEY) ENGINE = ; +INSERT INTO t5 VALUES (395), (-200), (100), (111); +SELECT c1 FROM t5 ORDER BY c1; +c1 +-200 +100 +111 +395 +SELECT c1 FROM t5 WHERE c1 = '100' ORDER BY c1; +c1 +100 +SELECT c1 FROM t5 WHERE c1 <=> '100' ORDER BY c1; +c1 +100 +SELECT c1 FROM t5 WHERE c1 >= '395' ORDER BY c1; +c1 +395 +SELECT c1 FROM t5 WHERE c1 <= '-200' ORDER BY c1; +c1 +-200 +SELECT c1 FROM t5 WHERE c1 != '100' ORDER BY c1; +c1 +-200 +111 +395 +SELECT c1 FROM t5 WHERE c1 < '111' ORDER BY c1; +c1 +-200 +100 +SELECT c1 FROM t5 WHERE c1 > '111' ORDER BY c1; +c1 +395 +DROP TABLE t5; +CREATE TABLE t5(c1 MEDIUMINT PRIMARY KEY) ENGINE = ; +INSERT INTO t5 VALUES (-8388607), (311),(215),(88608); +SELECT c1 FROM t5 ORDER BY c1; +c1 +-8388607 +215 +311 +88608 +SELECT c1 FROM t5 WHERE c1 = '311' ORDER BY c1; +c1 +311 +SELECT c1 FROM t5 WHERE c1 <=> '311' ORDER BY c1; +c1 +311 +SELECT c1 FROM t5 WHERE c1 >= '215' ORDER BY c1; +c1 +215 +311 +88608 +SELECT c1 FROM t5 WHERE c1 <= '88608' ORDER BY c1; +c1 +-8388607 +215 +311 +88608 +SELECT c1 FROM t5 WHERE c1 != '-8388607' ORDER BY c1; +c1 +215 +311 +88608 +SELECT c1 FROM t5 WHERE c1 < '215' ORDER BY c1; +c1 +-8388607 +SELECT c1 FROM t5 WHERE c1 > '215' ORDER BY c1; +c1 +311 +88608 +DROP TABLE t5; +CREATE TABLE t5(c1 INT PRIMARY KEY) ENGINE = ; +INSERT INTO t5 VALUES (-2147483647), (1011),(15),(9388607); +SELECT c1 FROM t5 ORDER BY c1; +c1 +-2147483647 +15 +1011 +9388607 +SELECT c1 FROM t5 WHERE c1 = '9388607' ORDER BY c1; +c1 +9388607 +SELECT c1 FROM t5 WHERE c1 <=> '9388607' ORDER BY c1; +c1 +9388607 +SELECT c1 FROM t5 WHERE c1 >= '15' ORDER BY c1; +c1 +15 +1011 +9388607 +SELECT c1 FROM t5 WHERE c1 <= '1011' ORDER BY c1; +c1 +-2147483647 +15 +1011 +SELECT c1 FROM t5 WHERE c1 != '-2147483647' ORDER BY c1; +c1 +15 +1011 +9388607 +SELECT c1 FROM t5 WHERE c1 < '15' ORDER BY c1; +c1 +-2147483647 +SELECT c1 FROM t5 WHERE c1 > '15' ORDER BY c1; +c1 +1011 +9388607 +DROP TABLE t5; +CREATE TABLE t5(c1 BIGINT PRIMARY KEY) ENGINE = ; +INSERT INTO t5 VALUES (-9223372036854775807), (12011),(500),(3372036854775808); +SELECT c1 FROM t5 ORDER BY c1; +c1 +-9223372036854775807 +500 +12011 +3372036854775808 +SELECT c1 FROM t5 WHERE c1 = '-9223372036854775807' ORDER BY c1; +c1 +-9223372036854775807 +SELECT c1 FROM t5 WHERE c1 <=> '-9223372036854775807' ORDER BY c1; +c1 +-9223372036854775807 +SELECT c1 FROM t5 WHERE c1 >= '12011' ORDER BY c1; +c1 +12011 +3372036854775808 +SELECT c1 FROM t5 WHERE c1 <= '500' ORDER BY c1; +c1 +-9223372036854775807 +500 +SELECT c1 FROM t5 WHERE c1 != '3372036854775808' ORDER BY c1; +c1 +-9223372036854775807 +500 +12011 +SELECT c1 FROM t5 WHERE c1 < '12011' ORDER BY c1; +c1 +-9223372036854775807 +500 +SELECT c1 FROM t5 WHERE c1 > '12011' ORDER BY c1; +c1 +3372036854775808 +DROP TABLE t5; +CREATE TABLE t5(c1 DOUBLE(5,2) PRIMARY KEY) ENGINE = ; +INSERT INTO t5 VALUES (95.95), (11.11),(5),(-908.92); +SELECT c1 FROM t5 ORDER BY c1; +c1 +-908.92 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 = '11.11' ORDER BY c1; +c1 +11.11 +SELECT c1 FROM t5 WHERE c1 <=> '11.11' ORDER BY c1; +c1 +11.11 +SELECT c1 FROM t5 WHERE c1 >= '5' ORDER BY c1; +c1 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 <= '95.95' ORDER BY c1; +c1 +-908.92 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 != '-908.92' ORDER BY c1; +c1 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 < '95.95' ORDER BY c1; +c1 +-908.92 +5.00 +11.11 +SELECT c1 FROM t5 WHERE c1 > '-908.92' ORDER BY c1; +c1 +5.00 +11.11 +95.95 +DROP TABLE t5; +CREATE TABLE t5(c1 NUMERIC(5,2) PRIMARY KEY) ENGINE = ; +INSERT INTO t5 VALUES (95.95), (11.11),(5),(-908.92); +SELECT c1 FROM t5 ORDER BY c1; +c1 +-908.92 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 = '11.11' ORDER BY c1; +c1 +11.11 +SELECT c1 FROM t5 WHERE c1 <=> '11.11' ORDER BY c1; +c1 +11.11 +SELECT c1 FROM t5 WHERE c1 >= '5' ORDER BY c1; +c1 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 <= '95.95' ORDER BY c1; +c1 +-908.92 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 != '-908.92' ORDER BY c1; +c1 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 < '95.95' ORDER BY c1; +c1 +-908.92 +5.00 +11.11 +SELECT c1 FROM t5 WHERE c1 > '-908.92' ORDER BY c1; +c1 +5.00 +11.11 +95.95 +DROP TABLE t5; +CREATE TABLE t5(c1 DECIMAL(5,2) PRIMARY KEY) ENGINE = ; +INSERT INTO t5 VALUES (95.95), (11.11),(5),(-908.92); +SELECT c1 FROM t5 ORDER BY c1; +c1 +-908.92 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 = '11.11' ORDER BY c1; +c1 +11.11 +SELECT c1 FROM t5 WHERE c1 <=> '11.11' ORDER BY c1; +c1 +11.11 +SELECT c1 FROM t5 WHERE c1 >= '5' ORDER BY c1; +c1 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 <= '95.95' ORDER BY c1; +c1 +-908.92 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 != '-908.92' ORDER BY c1; +c1 +5.00 +11.11 +95.95 +SELECT c1 FROM t5 WHERE c1 < '95.95' ORDER BY c1; +c1 +-908.92 +5.00 +11.11 +SELECT c1 FROM t5 WHERE c1 > '-908.92' ORDER BY c1; +c1 +5.00 +11.11 +95.95 +DROP TABLE t5; diff --git a/mysql-test/t/implicit_char_to_num_conversion.test b/mysql-test/t/implicit_char_to_num_conversion.test new file mode 100644 index 00000000000..b4948fbc69f --- /dev/null +++ b/mysql-test/t/implicit_char_to_num_conversion.test @@ -0,0 +1,174 @@ +########### implicit_char_to_num_conversion.test ####################### +# # +# This test aims at using string/char literal in comparison operators # +# without explicit type-cast. This is a bug test for Bug#11766521 # +# - Incorrect result is returned if string/char literal is used with # +# comparision operator and bit data type column. Test is extended to # +# include numeric data type comparison with string/char literal # +# # +# # +# Creation: # +# 2011-05-10 vfisrekar Implement this test as part of Bug#11766521 # +# # +######################################################################## + +--disable_warnings +DROP TABLE IF EXISTS t5; +--enable_warnings + +let $default_engine = `select @@SESSION.storage_engine`; + +# Bug#11766521 - BIT Datatype comparison in where clause return incorrect +# result for '=' , '<=>' operators +--replace_result $default_engine +eval CREATE TABLE t5(c1 BIT(2) PRIMARY KEY) ENGINE = $default_engine; +INSERT INTO t5 VALUES (0), (1), (2); +SELECT HEX(c1) FROM t5 ORDER BY c1; +# Enable Following two select after Bug#11766521 fix +# SELECT HEX(c1) FROM t5 WHERE c1 = '1' ORDER BY c1; +# SELECT HEX(c1) FROM t5 WHERE c1 <=> '1' ORDER BY c1; +SELECT HEX(c1) FROM t5 WHERE c1 = b'1' ORDER BY c1; +SELECT HEX(c1) FROM t5 WHERE c1 <=> b'1' ORDER BY c1; +SELECT HEX(c1) FROM t5 WHERE c1 != b'1' ORDER BY c1; +SELECT HEX(c1) FROM t5 WHERE c1 >= '1' ORDER BY c1; +SELECT HEX(c1) FROM t5 WHERE c1 <= '1' ORDER BY c1; +SELECT HEX(c1) FROM t5 WHERE c1 < '1' ORDER BY c1; +SELECT HEX(c1) FROM t5 WHERE c1 > '0' ORDER BY c1; +DROP TABLE t5; + +# FLOAT Data-type +--replace_result $default_engine +eval CREATE TABLE t5(c1 FLOAT(5,2) PRIMARY KEY) ENGINE = $default_engine; +INSERT INTO t5 VALUES (95.95), (-10.10), (1), (0); +SELECT c1 FROM t5 ORDER BY c1; +# Compare with string literal +# Following two queries does not return result may be due to Bug#11766521. +# Enable them after Bug#11766521 fix. +# SELECT c1 FROM t5 WHERE c1 = '10.10' ORDER BY c1; +# SELECT c1 FROM t5 WHERE c2 <=> '11.11' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 >= '95' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <= '10.10' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 != '1' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 < '1' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 > '0' ORDER BY c1; +DROP TABLE t5; + +# TINYINT Datatype +--replace_result $default_engine +eval CREATE TABLE t5(c1 TINYINT PRIMARY KEY) ENGINE = $default_engine; +INSERT INTO t5 VALUES (95), (10),(11),(-8); +SELECT c1 FROM t5 ORDER BY c1; +# Compare with string literal +SELECT c1 FROM t5 WHERE c1 = '10' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <=> '10' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 >= '95' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <= '11' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 != '-8' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 < '11' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 > '10' ORDER BY c1; +DROP TABLE t5; + +# SMALLINT Datatype +--replace_result $default_engine +eval CREATE TABLE t5(c1 SMALLINT PRIMARY KEY) ENGINE = $default_engine; +INSERT INTO t5 VALUES (395), (-200), (100), (111); +SELECT c1 FROM t5 ORDER BY c1; +# Compare with string literal +SELECT c1 FROM t5 WHERE c1 = '100' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <=> '100' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 >= '395' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <= '-200' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 != '100' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 < '111' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 > '111' ORDER BY c1; +DROP TABLE t5; + +# MEDIUMINT Datatype +--replace_result $default_engine +eval CREATE TABLE t5(c1 MEDIUMINT PRIMARY KEY) ENGINE = $default_engine; +INSERT INTO t5 VALUES (-8388607), (311),(215),(88608); +SELECT c1 FROM t5 ORDER BY c1; +# Compare with string literal +SELECT c1 FROM t5 WHERE c1 = '311' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <=> '311' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 >= '215' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <= '88608' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 != '-8388607' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 < '215' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 > '215' ORDER BY c1; +DROP TABLE t5; + +# INT Datatype +--replace_result $default_engine +eval CREATE TABLE t5(c1 INT PRIMARY KEY) ENGINE = $default_engine; +INSERT INTO t5 VALUES (-2147483647), (1011),(15),(9388607); +SELECT c1 FROM t5 ORDER BY c1; +# Compare with string literal +SELECT c1 FROM t5 WHERE c1 = '9388607' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <=> '9388607' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 >= '15' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <= '1011' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 != '-2147483647' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 < '15' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 > '15' ORDER BY c1; +DROP TABLE t5; + +# BIGINT Data-type +--replace_result $default_engine +eval CREATE TABLE t5(c1 BIGINT PRIMARY KEY) ENGINE = $default_engine; +INSERT INTO t5 VALUES (-9223372036854775807), (12011),(500),(3372036854775808); +SELECT c1 FROM t5 ORDER BY c1; +# Compare with string literal +SELECT c1 FROM t5 WHERE c1 = '-9223372036854775807' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <=> '-9223372036854775807' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 >= '12011' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <= '500' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 != '3372036854775808' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 < '12011' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 > '12011' ORDER BY c1; +DROP TABLE t5; + +# DOUBLE Datatype +--replace_result $default_engine +eval CREATE TABLE t5(c1 DOUBLE(5,2) PRIMARY KEY) ENGINE = $default_engine; +INSERT INTO t5 VALUES (95.95), (11.11),(5),(-908.92); +SELECT c1 FROM t5 ORDER BY c1; +# Compare with string literal +SELECT c1 FROM t5 WHERE c1 = '11.11' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <=> '11.11' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 >= '5' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <= '95.95' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 != '-908.92' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 < '95.95' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 > '-908.92' ORDER BY c1; +DROP TABLE t5; + +# NUMERIC Datatype +--replace_result $default_engine +eval CREATE TABLE t5(c1 NUMERIC(5,2) PRIMARY KEY) ENGINE = $default_engine; +INSERT INTO t5 VALUES (95.95), (11.11),(5),(-908.92); +SELECT c1 FROM t5 ORDER BY c1; +# Compare with string literal +SELECT c1 FROM t5 WHERE c1 = '11.11' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <=> '11.11' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 >= '5' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <= '95.95' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 != '-908.92' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 < '95.95' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 > '-908.92' ORDER BY c1; +DROP TABLE t5; + +# DECIMAL Datatype +--replace_result $default_engine +eval CREATE TABLE t5(c1 DECIMAL(5,2) PRIMARY KEY) ENGINE = $default_engine; +INSERT INTO t5 VALUES (95.95), (11.11),(5),(-908.92); +SELECT c1 FROM t5 ORDER BY c1; +# Compare with string literal +SELECT c1 FROM t5 WHERE c1 = '11.11' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <=> '11.11' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 >= '5' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 <= '95.95' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 != '-908.92' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 < '95.95' ORDER BY c1; +SELECT c1 FROM t5 WHERE c1 > '-908.92' ORDER BY c1; +DROP TABLE t5; From 96daf87a10e132e2bbb58e96343ffa0513b56870 Mon Sep 17 00:00:00 2001 From: Alexander Nozdrin Date: Mon, 16 May 2011 12:50:42 +0400 Subject: [PATCH 53/62] A patch for Bug#12429877: QUERY_TABLES_LIST::SROUTINES IS NOT FREED IN FLUSH_READ_LOCK (VALGRIND WARNING). The problem was that under some circustances the memory allocated for Query_tables_list::sroutines was not freed properly. The cause of this problem was the absence of LEX::restore_backup_query_tables_list() call in one of the branches in mysql_table_grant() function. --- sql/sql_acl.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 18758130767..0eb05489015 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3644,6 +3644,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, { // Should never happen /* Restore the state of binlog format */ DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); + thd->lex->restore_backup_query_tables_list(&backup); if (save_binlog_row_based) thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(TRUE); /* purecov: deadcode */ From fce2f006566b93bbc3af6d6e64ddd943b04ad6be Mon Sep 17 00:00:00 2001 From: Alexander Nozdrin Date: Mon, 16 May 2011 12:51:14 +0400 Subject: [PATCH 54/62] Ignore auto-generated files. --- .bzrignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.bzrignore b/.bzrignore index 2369d922ddf..a851f547392 100644 --- a/.bzrignore +++ b/.bzrignore @@ -3132,3 +3132,4 @@ VERSION.dep info_macros.cmake Docs/INFO_BIN Docs/INFO_SRC +Testing From 252b86bc273a41f04f8a88a2e4114a2e7e2e4528 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Mon, 16 May 2011 12:44:34 +0300 Subject: [PATCH 55/62] Bug 12535301 - SYS_VARS.RPL_INIT_SLAVE_FUNC MISMATCHES IN DAILY-5.5 notifying PB2 the test fails through mysql-test/collections/default.experimental. --- mysql-test/collections/default.experimental | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index 5ecc8ef8c64..22505701ac1 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -28,6 +28,7 @@ sys_vars.wait_timeout_func # Bug#41255 2010-04-26 alik wait_t sys_vars.ndb_log_update_as_write_basic sys_vars.have_ndbcluster_basic sys_vars.ndb_log_updated_only_basic +sys_vars.rpl_init_slave_func # Bug#12535301 2011-05-09 andrei sys_vars.rpl_init_slave_func mismatches in daily-5.5 main.gis-rtree # svoj: due to BUG#38965 main.type_float # svoj: due to BUG#38965 From 955cb796e7672d1186f44de84528b7b8fe47f0c9 Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Mon, 16 May 2011 20:26:55 +0200 Subject: [PATCH 56/62] - Changes needed to use newer WiX version (Bug#60029) - Added an alterantive search path for WiX components - Added a custom welcome dialog to include the copyright line (Bug#59805 and Bug#59512) - Excluded some binaries to make package smaller, in effect makig the "essentials" package obsolete - Added a bit more error checking when running the WiX tools WiX XML changes done by Johannes Taxacher --- packaging/WiX/ca/CMakeLists.txt | 40 ++++++++++++--- packaging/WiX/create_msi.cmake.in | 85 ++++++++++++++++++++++++------- packaging/WiX/custom_ui.wxs | 28 +++++++--- 3 files changed, 124 insertions(+), 29 deletions(-) diff --git a/packaging/WiX/ca/CMakeLists.txt b/packaging/WiX/ca/CMakeLists.txt index a03ceb9a5d2..6872dc99d94 100644 --- a/packaging/WiX/ca/CMakeLists.txt +++ b/packaging/WiX/ca/CMakeLists.txt @@ -13,15 +13,43 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/inc) -LINK_DIRECTORIES(${WIX_DIR}/../SDK/lib) +INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/inc ${WIX_DIR}/SDK/inc) +LINK_DIRECTORIES(${WIX_DIR}/../SDK/lib ${WIX_DIR}/SDK/lib) SET(WIXCA_SOURCES CustomAction.cpp CustomAction.def) IF(CMAKE_SIZEOF_VOID_P EQUAL 8) - LINK_LIBRARIES(wcautil_x64 dutil_x64 msi version) + SET(WIX_ARCH_SUFFIX "_x64") ELSE() - LINK_LIBRARIES(wcautil dutil msi version) + SET(WIX_ARCH_SUFFIX) ENDIF() - -ADD_LIBRARY(wixca SHARED ${WIXCA_SOURCES}) + +IF(MSVC_VERSION EQUAL 1400) + SET(WIX35_MSVC_SUFFIX "_2005") +ELSEIF(MSVC_VERSION EQUAL 1500) + SET(WIX35_MSVC_SUFFIX "_2008") +ELSEIF(MSVC_VERSION EQUAL 1600) + SET(WIX35_MSVC_SUFFIX "_2010") +ELSE() + # When next VS is out, add the correct version here + MESSAGE(FATAL_ERROR "Unknown VS version") +ENDIF() + +MESSAGE(STATUS "Searching for wcautil${WIX_ARCH_SUFFIX} or wcautil${WIX35_MSVC_SUFFIX}${WIX_ARCH_SUFFIX} in ${WIX_DIR}/../SDK/lib ${WIX_DIR}/SDK/lib") +MESSAGE(STATUS "Searching for dutil${WIX_ARCH_SUFFIX} or dutil${WIX35_MSVC_SUFFIX}${WIX_ARCH_SUFFIX} in ${WIX_DIR}/../SDK/lib ${WIX_DIR}/SDK/lib") + +FIND_LIBRARY(WIX_WCAUTIL_LIBRARY + NAMES wcautil${WIX_ARCH_SUFFIX} wcautil${WIX35_MSVC_SUFFIX}${WIX_ARCH_SUFFIX} + HINTS ${WIX_DIR}/../SDK/lib ${WIX_DIR}/SDK/lib) + +FIND_LIBRARY(WIX_DUTIL_LIBRARY + NAMES dutil${WIX_ARCH_SUFFIX} dutil${WIX35_MSVC_SUFFIX}${WIX_ARCH_SUFFIX} + PATHS ${WIX_DIR}/../SDK/lib ${WIX_DIR}/SDK/lib) + +MESSAGE(STATUS "Found: ${WIX_WCAUTIL_LIBRARY}") +MESSAGE(STATUS "Found: ${WIX_DUTIL_LIBRARY}") + +ADD_VERSION_INFO(wixca SHARED WIXCA_SOURCES) +ADD_LIBRARY(wixca SHARED EXCLUDE_FROM_ALL ${WIXCA_SOURCES}) +TARGET_LINK_LIBRARIES(wixca ${WIX_WCAUTIL_LIBRARY} ${WIX_DUTIL_LIBRARY} + msi version ) diff --git a/packaging/WiX/create_msi.cmake.in b/packaging/WiX/create_msi.cmake.in index a1899b701fd..dd2e9fd9d85 100644 --- a/packaging/WiX/create_msi.cmake.in +++ b/packaging/WiX/create_msi.cmake.in @@ -15,6 +15,28 @@ SET(COPYING_RTF "@COPYING_RTF@") SET(CPACK_WIX_CONFIG "@CPACK_WIX_CONFIG@") SET(CPACK_WIX_INCLUDE "@CPACK_WIX_INCLUDE@") +LIST(APPEND EXCLUDE_DIRS + bin/debug + data/test + lib/plugin/debug + mysql-test + scripts + sql-bench +) + +LIST(APPEND EXCLUDE_FILES + bin/echo.exe + bin/mysql_client_test_embedded.exe + bin/mysqld-debug.exe + bin/mysqltest_embedded.exe + bin/replace.exe + lib/debug/mysqlserver.lib + lib/libmysqld.dll + lib/libmysqld.lib + lib/mysqlserver.lib + lib/mysqlservices.lib +) + IF(CMAKE_SIZEOF_VOID_P EQUAL 8) SET(Win64 " Win64='yes'") SET(Platform x64) @@ -197,11 +219,18 @@ ENDMACRO() FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root) + FILE(RELATIVE_PATH dir_rel ${topdir} ${dir}) + IF(dir_rel) + LIST(FIND EXCLUDE_DIRS ${dir_rel} TO_EXCLUDE) + IF(NOT TO_EXCLUDE EQUAL -1) + MESSAGE(STATUS "excluding directory: ${dir_rel}") + RETURN() + ENDIF() + ENDIF() FILE(GLOB all_files ${dir}/*) IF(NOT all_files) RETURN() ENDIF() - FILE(RELATIVE_PATH dir_rel ${topdir} ${dir}) IF(dir_rel) MAKE_DIRECTORY(${dir_root}/${dir_rel}) MAKE_WIX_IDENTIFIER("${dir_rel}" id) @@ -215,18 +244,31 @@ FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root) FOREACH(f ${all_files}) IF(NOT IS_DIRECTORY ${f}) FILE(RELATIVE_PATH rel ${topdir} ${f}) - MAKE_WIX_IDENTIFIER("${rel}" id) - FILE(TO_NATIVE_PATH ${f} f_native) - GET_FILENAME_COMPONENT(f_ext "${f}" EXT) - # According to MSDN each DLL or EXE should be in the own component - IF(f_ext MATCHES ".exe" OR f_ext MATCHES ".dll") + SET(TO_EXCLUDE) + IF(rel MATCHES "\\.pdb$") + SET(TO_EXCLUDE TRUE) + ELSE() + LIST(FIND EXCLUDE_FILES ${rel} RES) + IF(NOT RES EQUAL -1) + SET(TO_EXCLUDE TRUE) + ENDIF() + ENDIF() + IF(TO_EXCLUDE) + MESSAGE(STATUS "excluding file: ${rel}") + ELSE() + MAKE_WIX_IDENTIFIER("${rel}" id) + FILE(TO_NATIVE_PATH ${f} f_native) + GET_FILENAME_COMPONENT(f_ext "${f}" EXT) + # According to MSDN each DLL or EXE should be in the own component + IF(f_ext MATCHES ".exe" OR f_ext MATCHES ".dll") - FILE(APPEND ${file} " \n") - FILE(APPEND ${file} " \n") - FILE(APPEND ${file} " \n") - FILE(APPEND ${file_comp} " \n") - ELSE() - SET(NONEXEFILES "${NONEXEFILES}\n" ) + FILE(APPEND ${file} " \n") + FILE(APPEND ${file} " \n") + FILE(APPEND ${file} " \n") + FILE(APPEND ${file_comp} " \n") + ELSE() + SET(NONEXEFILES "${NONEXEFILES}\n" ) + ENDIF() ENDIF() ENDIF() ENDFOREACH() @@ -247,18 +289,18 @@ ENDFUNCTION() FUNCTION(TRAVERSE_DIRECTORIES dir topdir file prefix) FILE(RELATIVE_PATH rel ${topdir} ${dir}) - IF(rel AND IS_DIRECTORY "${f}") + IF(rel) MAKE_WIX_IDENTIFIER("${rel}" id) GET_FILENAME_COMPONENT(name ${dir} NAME) FILE(APPEND ${file} "${prefix}\n") ENDIF() FILE(GLOB all_files ${dir}/*) - FOREACH(f ${all_files}) + FOREACH(f ${all_files}) IF(IS_DIRECTORY ${f}) TRAVERSE_DIRECTORIES(${f} ${topdir} ${file} "${prefix} ") ENDIF() ENDFOREACH() - IF(rel AND IS_DIRECTORY "${f}") + IF(rel) FILE(APPEND ${file} "${prefix}\n") ENDIF() ENDFUNCTION() @@ -317,16 +359,25 @@ ENDIF() FILE(REMOVE mysql_server.wixobj) EXECUTE_PROCESS( COMMAND ${CANDLE_EXECUTABLE} -ext WixUtilExtension mysql_server.wxs ${EXTRA_CANDLE_ARGS} + RESULT_VARIABLE CANDLE_RESULT ) + +IF(CANDLE_RESULT) + MESSAGE(FATAL_ERROR "ERROR: can't run candle") +ENDIF() + EXECUTE_PROCESS( COMMAND ${LIGHT_EXECUTABLE} -ext WixUIExtension -ext WixUtilExtension mysql_server.wixobj -out ${CPACK_PACKAGE_FILE_NAME}.msi ${EXTRA_LIGHT_ARGS} + RESULT_VARIABLE LIGHT_RESULT ) +IF(LIGHT_RESULT) + MESSAGE(FATAL_ERROR "ERROR: can't run light") +ENDIF() + # Switch monolithic install on again EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -DCPACK_MONOLITHIC_INSTALL=1 ${CMAKE_BINARY_DIR} - OUTPUT_QUIET ) - diff --git a/packaging/WiX/custom_ui.wxs b/packaging/WiX/custom_ui.wxs index 90db5c416fe..1dc1ef28e4f 100644 --- a/packaging/WiX/custom_ui.wxs +++ b/packaging/WiX/custom_ui.wxs @@ -1,7 +1,22 @@ - + + + 1 + + + NOT OLDERVERSIONBEINGUPGRADED + OLDERVERSIONBEINGUPGRADED + + + + + + + + + 1]]> @@ -47,10 +62,7 @@ 1 - NOT OLDERVERSIONBEINGUPGRADED - OLDERVERSIONBEINGUPGRADED - - 1 + 1 LicenseAccepted = "1" 1 @@ -74,7 +86,11 @@ 1 1 - 1 + 1 + + + NOT Installed + From b1307dc0e173ba1d0b32e6c5fdb06b8aaf9e69dc Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Mon, 16 May 2011 22:47:59 +0200 Subject: [PATCH 57/62] Fixed code review comments --- mysys/lf_alloc-pin.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index cef51c89076..127d7807761 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -344,8 +344,7 @@ static void _lf_pinbox_real_free(LF_PINS *pins) #ifdef HAVE_ALLOCA if (pins->stack_ends_here != NULL) { - int alloca_size; - alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins; + int alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins; /* create a sorted list of pinned addresses, to speed up searches */ if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size) { From 3201f92cb3a8e564387d656f7a7bb566d4776bb5 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 18 May 2011 10:47:43 +0400 Subject: [PATCH 58/62] Bug#12403504 AFTER FIX FOR #11889186 : ASSERTION FAILED: DELSUM+(INT) Y/4-TEMP > 0 There are two problems: 1. There is a missing check for 'year' parameter(year can not be greater than 9999) in makedate function. fix: added check that year can not be greater than 9999. 2. There is a missing check for zero date in from_days() function. fix: added zero date check into Item_func_from_days::get_date() function. mysql-test/r/func_time.result: test case mysql-test/t/func_time.test: test case sql/item_timefunc.cc: --added check that year can not be greater than 9999 for makedate() function --added zero date check into Item_func_from_days::get_date() function --- mysql-test/r/func_time.result | 9 +++++++++ mysql-test/t/func_time.test | 7 +++++++ sql/item_timefunc.cc | 9 +++++++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 1e05443d8ac..63744d4ef29 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -1417,4 +1417,13 @@ NULL SELECT DATE_FORMAT('0000-00-11', '%w'); DATE_FORMAT('0000-00-11', '%w') NULL +# +# Bug#12403504 AFTER FIX FOR #11889186 : ASSERTION FAILED: DELSUM+(INT) Y/4-TEMP > 0 +# +SELECT MAKEDATE(11111111,1); +MAKEDATE(11111111,1) +NULL +SELECT WEEK(DATE_ADD(FROM_DAYS(1),INTERVAL 1 MONTH), 1); +WEEK(DATE_ADD(FROM_DAYS(1),INTERVAL 1 MONTH), 1) +NULL End of 5.1 tests diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 2000d81f80d..de92f313992 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -921,4 +921,11 @@ SELECT DATE_FORMAT('0000-00-11', '%W'); SELECT DATE_FORMAT('0000-00-11', '%a'); SELECT DATE_FORMAT('0000-00-11', '%w'); +--echo # +--echo # Bug#12403504 AFTER FIX FOR #11889186 : ASSERTION FAILED: DELSUM+(INT) Y/4-TEMP > 0 +--echo # + +SELECT MAKEDATE(11111111,1); +SELECT WEEK(DATE_ADD(FROM_DAYS(1),INTERVAL 1 MONTH), 1); + --echo End of 5.1 tests diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index a96922b94a1..9b312247017 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1519,6 +1519,11 @@ bool Item_func_from_days::get_date(MYSQL_TIME *ltime, uint fuzzy_date) return 1; bzero(ltime, sizeof(MYSQL_TIME)); get_date_from_daynr((long) value, <ime->year, <ime->month, <ime->day); + + if ((null_value= (fuzzy_date & TIME_NO_ZERO_DATE) && + (ltime->year == 0 || ltime->month == 0 || ltime->day == 0))) + return TRUE; + ltime->time_type= MYSQL_TIMESTAMP_DATE; return 0; } @@ -2697,7 +2702,7 @@ String *Item_func_makedate::val_str(String *str) long days; if (args[0]->null_value || args[1]->null_value || - year < 0 || daynr <= 0) + year < 0 || year > 9999 || daynr <= 0) goto err; if (year < 100) @@ -2740,7 +2745,7 @@ longlong Item_func_makedate::val_int() long days; if (args[0]->null_value || args[1]->null_value || - year < 0 || daynr <= 0) + year < 0 || year > 9999 || daynr <= 0) goto err; if (year < 100) From 89ec54264d095799f3247687d21dc5c6e02242de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Ronstr=C3=B6m?= Date: Wed, 18 May 2011 09:38:05 +0200 Subject: [PATCH 59/62] Split up unlink_thd in several functions --- include/mysql/thread_pool_priv.h | 4 +++- sql/mysqld.cc | 39 ++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/include/mysql/thread_pool_priv.h b/include/mysql/thread_pool_priv.h index 3f4cf371024..b0b0aadc7ff 100644 --- a/include/mysql/thread_pool_priv.h +++ b/include/mysql/thread_pool_priv.h @@ -94,8 +94,10 @@ bool thd_is_connection_alive(THD *thd); void close_connection(THD *thd, uint errcode); /* End the connection before closing it */ void end_connection(THD *thd); +/* Decrement connection counter */ +void dec_connection_count(); /* Destroy THD object */ -void unlink_thd(THD *thd); +void delete_thd(THD *thd); /* thread_created is maintained by thread pool when activated since diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f078c703a1a..2192b0f3ee9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2009,6 +2009,36 @@ extern "C" sig_handler end_thread_signal(int sig __attribute__((unused))) } +/* + Decrease number of connections + + SYNOPSIS + dec_connection_count() +*/ + +void dec_connection_count() +{ + mysql_mutex_lock(&LOCK_connection_count); + --connection_count; + mysql_mutex_unlock(&LOCK_connection_count); +} + + +/* + Delete the THD object and decrease number of threads + + SYNOPSIS + delete_thd() + thd Thread handler +*/ + +void delete_thd(THD *thd) +{ + thread_count--; + delete thd; +} + + /* Unlink thd from global list of available connections and free thd @@ -2024,15 +2054,10 @@ void unlink_thd(THD *thd) { DBUG_ENTER("unlink_thd"); DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); - thd->cleanup(); - - mysql_mutex_lock(&LOCK_connection_count); - --connection_count; - mysql_mutex_unlock(&LOCK_connection_count); + dec_connection_count(); mysql_mutex_lock(&LOCK_thread_count); - thread_count--; - delete thd; + delete_thd(thd); DBUG_VOID_RETURN; } From 47f7fc4353f4ee665b703bee6479ad1664db0f48 Mon Sep 17 00:00:00 2001 From: Mayank Prasad Date: Wed, 18 May 2011 19:47:29 +0530 Subject: [PATCH 60/62] merge from 5.1 for bug#11764633 --- libmysqld/lib_sql.cc | 28 ++++++++++++++++++++++++++-- sql/mysqld.h | 8 ++++++++ sql/sql_class.cc | 19 +++++++++++++++++++ sql/sql_class.h | 1 + 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index b07ae1de96b..34f8f685e45 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -50,6 +50,23 @@ extern "C" void unireg_clear(int exit_code) DBUG_VOID_RETURN; } +/* + Wrapper error handler for embedded server to call client/server error + handler based on whether thread is in client/server context +*/ + +static void embedded_error_handler(uint error, const char *str, myf MyFlags) +{ + DBUG_ENTER("embedded_error_handler"); + + /* + If current_thd is NULL, it means restore_global has been called and + thread is in client context, then call client error handler else call + server error handler. + */ + DBUG_RETURN(current_thd ? my_message_sql(error, str, MyFlags): + my_message_stderr(error, str, MyFlags)); +} /* Reads error information from the MYSQL_DATA and puts @@ -106,7 +123,8 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, if (mysql->status != MYSQL_STATUS_READY) { set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); - return 1; + result= 1; + goto end; } /* Clear result variables */ @@ -147,6 +165,9 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, #if defined(ENABLED_PROFILING) thd->profiling.finish_current_query(); #endif + +end: + thd->restore_globals(); return result; } @@ -545,7 +566,10 @@ int init_embedded_server(int argc, char **argv, char **groups) return 1; } - error_handler_hook = my_message_sql; + /* + set error_handler_hook to embedded_error_handler wrapper. + */ + error_handler_hook= embedded_error_handler; acl_error= 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/mysqld.h b/sql/mysqld.h index 303ee5bec0f..d2366224b3f 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -216,6 +216,10 @@ extern char err_shared_dir[]; extern TYPELIB thread_handling_typelib; extern my_decimal decimal_zero; +/* + THR_MALLOC is a key which will be used to set/get MEM_ROOT** for a thread, + using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr(). +*/ extern pthread_key(MEM_ROOT**,THR_MALLOC); #ifdef HAVE_PSI_INTERFACE @@ -503,6 +507,10 @@ get_thread_running() extern "C" THD *_current_thd_noinline(); #define _current_thd() _current_thd_noinline() #else +/* + THR_THD is a key which will be used to set/get THD* for a thread, + using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr(). +*/ extern pthread_key(THD*, THR_THD); inline THD *_current_thd(void) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 4af038bb4e0..733d46148c5 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1354,6 +1354,25 @@ bool THD::store_globals() return 0; } +/* + Remove the thread specific info (THD and mem_root pointer) stored during + store_global call for this thread. +*/ +bool THD::restore_globals() +{ + /* + Assert that thread_stack is initialized: it's necessary to be able + to track stack overrun. + */ + DBUG_ASSERT(thread_stack); + + /* Undocking the thread specific data. */ + my_pthread_setspecific_ptr(THR_THD, NULL); + my_pthread_setspecific_ptr(THR_MALLOC, NULL); + + return 0; +} + /* Cleanup after query. diff --git a/sql/sql_class.h b/sql/sql_class.h index 56d85e7cb6d..14658f46c94 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2199,6 +2199,7 @@ public: void cleanup(void); void cleanup_after_query(); bool store_globals(); + bool restore_globals(); #ifdef SIGNAL_WITH_VIO_CLOSE inline void set_active_vio(Vio* vio) { From d608ad2dd6ea45e3ef96a98f41702971a5edd215 Mon Sep 17 00:00:00 2001 From: Mayank Prasad Date: Wed, 18 May 2011 20:10:01 +0530 Subject: [PATCH 61/62] Bug#11764633 : 57491: THD->MAIN_DA.IS_OK() ASSERT IN EMBEDDED Issue: While running embedded server, if client issues TEE command (\T foo/bar) and "foo/bar" directory doesn't exist, it is suppose to give error. But it was aborting. This was happening because wrong error handler was being called. Solution: Modified calls to correct error handler. In embedded server case, there are two error handler (client and server) which are supposed to be called based on which context code is in. If it is in client context, client error handler should be called otherwise server. Test case: Test case automation is not possible as current (following) code doesn't allow '\T' to be executed from command line (OR command read from a file): [client/mysql.cc] ... static int com_tee(String *buffer __attribute__((unused)), char *line __attribute__((unused))) { char file_name[FN_REFLEN], *end, *param; if (status.batch) << THIS IS TRUE WHILE EXECUTING FROM COMMAND LINE. return 0; ... So, not adding test case in GA. WIll add a test case in mysql-trunk after removing above code so that this could be properly tested before GA. libmysqld/lib_sql.cc: Added code to call client/server error handler based on in control is in client/server code respectively. sql/mysql_priv.h: Added comments for THR_THD, THR_MALLOC keys. sql/sql_class.cc: Function definition of new function restore_global to removes thread specific data from stack (which was stored in store global). sql/sql_class.h: Function declaration of new function restore_global. --- libmysqld/lib_sql.cc | 28 ++++++++++++++++++++++++++-- sql/mysql_priv.h | 8 ++++++++ sql/sql_class.cc | 19 +++++++++++++++++++ sql/sql_class.h | 1 + 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 778d4874ad4..b6da6172039 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -51,6 +51,23 @@ extern "C" void unireg_clear(int exit_code) DBUG_VOID_RETURN; } +/* + Wrapper error handler for embedded server to call client/server error + handler based on whether thread is in client/server context +*/ + +static int embedded_error_handler(uint error, const char *str, myf MyFlags) +{ + DBUG_ENTER("embedded_error_handler"); + + /* + If current_thd is NULL, it means restore_global has been called and + thread is in client context, then call client error handler else call + server error handler. + */ + DBUG_RETURN(current_thd ? my_message_sql(error, str, MyFlags): + my_message_no_curses(error, str, MyFlags)); +} /* Reads error information from the MYSQL_DATA and puts @@ -107,7 +124,8 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, if (mysql->status != MYSQL_STATUS_READY) { set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); - return 1; + result= 1; + goto end; } /* Clear result variables */ @@ -147,6 +165,9 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, #if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.finish_current_query(); #endif + +end: + thd->restore_globals(); return result; } @@ -525,7 +546,10 @@ int init_embedded_server(int argc, char **argv, char **groups) return 1; } - error_handler_hook = my_message_sql; + /* + set error_handler_hook to embedded_error_handler wrapper. + */ + error_handler_hook= embedded_error_handler; acl_error= 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 8f9a9080d12..3ce73291206 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -670,6 +670,10 @@ enum enum_check_fields extern "C" THD *_current_thd_noinline(); #define _current_thd() _current_thd_noinline() #else +/* + THR_THD is a key which will be used to set/get THD* for a thread, + using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr(). +*/ extern pthread_key(THD*, THR_THD); inline THD *_current_thd(void) { @@ -2022,6 +2026,10 @@ extern TABLE_LIST general_log, slow_log; extern FILE *bootstrap_file; extern int bootstrap_error; extern FILE *stderror_file; +/* + THR_MALLOC is a key which will be used to set/get MEM_ROOT** for a thread, + using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr(). +*/ extern pthread_key(MEM_ROOT**,THR_MALLOC); extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open, LOCK_lock_db, LOCK_mapped_file,LOCK_user_locks, LOCK_status, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ae21a5335fd..04f981c6d6a 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1196,6 +1196,25 @@ bool THD::store_globals() return 0; } +/* + Remove the thread specific info (THD and mem_root pointer) stored during + store_global call for this thread. +*/ +bool THD::restore_globals() +{ + /* + Assert that thread_stack is initialized: it's necessary to be able + to track stack overrun. + */ + DBUG_ASSERT(thread_stack); + + /* Undocking the thread specific data. */ + my_pthread_setspecific_ptr(THR_THD, NULL); + my_pthread_setspecific_ptr(THR_MALLOC, NULL); + + return 0; +} + /* Cleanup after query. diff --git a/sql/sql_class.h b/sql/sql_class.h index b3e8fde8cda..6b82512677a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1943,6 +1943,7 @@ public: void cleanup(void); void cleanup_after_query(); bool store_globals(); + bool restore_globals(); #ifdef SIGNAL_WITH_VIO_CLOSE inline void set_active_vio(Vio* vio) { From 4f03d60096a599adfc8d7cf83aac480260c3348f Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Thu, 19 May 2011 16:45:45 +0100 Subject: [PATCH 62/62] BUG#11746302: 25228: RPL_RELAYSPACE.TEST FAILS ON POWERMACG5, VM-WIN2003-32-A, SLES10-IA64-A The test case waits for master_pos_wait not to timeout, which means that the deadlock between SQL and IO threads was succesfully and automatically dealt with. However, very rarely, master_pos_wait reports a timeout. This happens because the time set for master_pos_wait to wait was too small (6 seconds). On slow test env this could be a problem. We fix this by setting the timeout inline with the one used in sync_slave_with_master (300 seconds). In addition we refactored the test case and refined some comments. --- mysql-test/suite/rpl/r/rpl_relayspace.result | 10 ++--- mysql-test/suite/rpl/t/rpl_relayspace.test | 42 +++++++++++++------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_relayspace.result b/mysql-test/suite/rpl/r/rpl_relayspace.result index f12f177ff7c..fb21540aa31 100644 --- a/mysql-test/suite/rpl/r/rpl_relayspace.result +++ b/mysql-test/suite/rpl/r/rpl_relayspace.result @@ -1,6 +1,6 @@ include/master-slave.inc [connection master] -stop slave; +include/stop_slave.inc create table t1 (a int); drop table t1; create table t1 (a int); @@ -8,10 +8,8 @@ drop table t1; reset slave; start slave io_thread; include/wait_for_slave_param.inc [Slave_IO_State] -stop slave io_thread; +include/stop_slave_io.inc reset slave; -start slave; -select master_pos_wait('master-bin.001',200,6)=-1; -master_pos_wait('master-bin.001',200,6)=-1 -0 +include/start_slave.inc +include/assert.inc [Assert that master_pos_wait does not timeout nor it returns NULL] include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_relayspace.test b/mysql-test/suite/rpl/t/rpl_relayspace.test index bb34ec25bcd..fc33d6bc0ba 100644 --- a/mysql-test/suite/rpl/t/rpl_relayspace.test +++ b/mysql-test/suite/rpl/t/rpl_relayspace.test @@ -2,8 +2,9 @@ # to force the deadlock after one event. source include/master-slave.inc; +--let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1) connection slave; -stop slave; +--source include/stop_slave.inc connection master; # This will generate a master's binlog > 10 bytes create table t1 (a int); @@ -19,20 +20,33 @@ let $slave_param_value= Waiting for the slave SQL thread to free enough relay lo source include/wait_for_slave_param.inc; # A bug caused the I/O thread to refuse stopping. -stop slave io_thread; +--source include/stop_slave_io.inc reset slave; -start slave; -# The I/O thread stops filling the relay log when -# it's >10b. And the SQL thread cannot purge this relay log -# as purge is done only when the SQL thread switches to another -# relay log, which does not exist here. -# So we should have a deadlock. -# if it is not resolved automatically we'll detect -# it with master_pos_wait that waits for farther than 1Ob; -# it will timeout after 10 seconds; -# also the slave will probably not cooperate to shutdown -# (as 2 threads are locked) -select master_pos_wait('master-bin.001',200,6)=-1; +--source include/start_slave.inc + +# The I/O thread stops filling the relay log when it's >10b. And the +# SQL thread cannot purge this relay log as purge is done only when +# the SQL thread switches to another relay log, which does not exist +# here. So we should have a deadlock. If it is not resolved +# automatically we'll detect it with master_pos_wait that waits for +# farther than 1Ob; it will timeout after 300 seconds (which is inline +# with the default used for sync_slave_with_master and will protect us +# against slow test envs); also the slave will probably not cooperate +# to shutdown (as 2 threads are locked) +--let $outcome= `SELECT MASTER_POS_WAIT('$master_log_file',200,300) AS mpw;` + +# master_pos_wait returns: +# +# * >= 0, the number of events the slave had to wait to advance to the +# position +# +# * -1, if there was a timeout +# +# * NULL, if an error occurred, or the SQL thread was not started, +# slave master info is not initialized, the arguments are incorrect +--let $assert_text= Assert that master_pos_wait does not timeout nor it returns NULL +--let $assert_cond= $outcome IS NOT NULL AND $outcome <> -1 +--source include/assert.inc # End of 4.1 tests --source include/rpl_end.inc