diff options
author | Vladislav Vaintroub <wlad@montyprogram.com> | 2012-02-16 16:59:04 +0100 |
---|---|---|
committer | Vladislav Vaintroub <wlad@montyprogram.com> | 2012-02-16 16:59:04 +0100 |
commit | cfa56f900acefcf228c26dfa39c1b9142ef3552b (patch) | |
tree | 6fa08e8fa99d31d69e9b7fda91c0e89f4635ee5e /sql | |
parent | 8877fe7359b1eef81b62c6531674aaa5a5ce6051 (diff) | |
download | mariadb-git-cfa56f900acefcf228c26dfa39c1b9142ef3552b.tar.gz |
address second round review comments
Diffstat (limited to 'sql')
-rw-r--r-- | sql/scheduler.cc | 16 | ||||
-rw-r--r-- | sql/scheduler.h | 1 | ||||
-rw-r--r-- | sql/sql_class.cc | 30 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/threadpool.h | 3 | ||||
-rw-r--r-- | sql/threadpool_common.cc | 18 | ||||
-rw-r--r-- | sql/threadpool_unix.cc | 110 |
7 files changed, 102 insertions, 78 deletions
diff --git a/sql/scheduler.cc b/sql/scheduler.cc index c174d300d2e..3f779337345 100644 --- a/sql/scheduler.cc +++ b/sql/scheduler.cc @@ -48,26 +48,26 @@ extern "C" { static void scheduler_wait_lock_begin(void) { THD *thd=current_thd; - scheduler_functions *func= thd->scheduler; - MYSQL_CALLBACK(func, thd_wait_begin, (thd, THD_WAIT_TABLE_LOCK)); + if(thd) + MYSQL_CALLBACK(thd->scheduler, thd_wait_begin, (thd, THD_WAIT_TABLE_LOCK)); } static void scheduler_wait_lock_end(void) { THD *thd=current_thd; - scheduler_functions *func= thd->scheduler; - MYSQL_CALLBACK(func, thd_wait_end, (thd)); + if(thd) + MYSQL_CALLBACK(thd->scheduler, thd_wait_end, (thd)); } static void scheduler_wait_sync_begin(void) { THD *thd=current_thd; - scheduler_functions *func= thd ? thd->scheduler : thread_scheduler; - MYSQL_CALLBACK(func, thd_wait_begin, (thd, THD_WAIT_TABLE_LOCK)); + if(thd) + MYSQL_CALLBACK(thd->scheduler, thd_wait_begin, (thd, THD_WAIT_TABLE_LOCK)); } static void scheduler_wait_sync_end(void) { THD *thd=current_thd; - scheduler_functions *func= thd ? thd->scheduler : thread_scheduler; - MYSQL_CALLBACK(func, thd_wait_end, (thd)); + if(thd) + MYSQL_CALLBACK(thd->scheduler, thd_wait_end, (thd)); } }; /**@}*/ diff --git a/sql/scheduler.h b/sql/scheduler.h index 302ccd7ab11..41e7b085a48 100644 --- a/sql/scheduler.h +++ b/sql/scheduler.h @@ -76,6 +76,7 @@ void one_thread_per_connection_scheduler(scheduler_functions *func, ulong *arg_max_connections, uint *arg_connection_count); void one_thread_scheduler(scheduler_functions *func); +extern void scheduler_init(); /* To be used for pool-of-threads (implemeneted differently on various OSs) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d99b24b33f3..af3cdf7b34f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1523,7 +1523,7 @@ void THD::awake(killed_state state_to_set) if (state_to_set >= KILL_CONNECTION || state_to_set == NOT_KILLED) { #ifdef SIGNAL_WITH_VIO_CLOSE - if (this != current_thd) + if (this != current_thd) { if(active_vio) vio_shutdown(active_vio, SHUT_RDWR); @@ -3935,10 +3935,16 @@ extern "C" bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd) */ extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type) { - if(!thd) - thd= current_thd; - if (thd) - MYSQL_CALLBACK(thd->scheduler, thd_wait_begin, (thd, wait_type)); + + if (unlikely(!thread_scheduler) || !thread_scheduler->thd_wait_begin) + return; + if (thd == NULL) + { + thd=current_thd; + if(unlikely(thd == NULL)) + return; + } + MYSQL_CALLBACK(thd->scheduler, thd_wait_begin, (thd, wait_type)); } /** @@ -3950,10 +3956,16 @@ extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type) */ extern "C" void thd_wait_end(MYSQL_THD thd) { - if(!thd) - thd= current_thd; - if (thd) - MYSQL_CALLBACK(thd->scheduler, thd_wait_end, (thd)); + if (unlikely(!thread_scheduler) || ! thread_scheduler->thd_wait_begin) + return; + if (thd == NULL) + { + thd=current_thd; + if(unlikely(thd == NULL)) + return; + } + if(likely(thd->scheduler == thread_scheduler)) + thread_scheduler->thd_wait_end(thd); } #endif // INNODB_COMPATIBILITY_HOOKS */ diff --git a/sql/sql_class.h b/sql/sql_class.h index 7c7ae1eb2af..ce000adc785 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4278,6 +4278,8 @@ inline int handler::ha_update_tmp_row(const uchar *old_data, uchar *new_data) return error; } +extern pthread_attr_t *get_connection_attrib(void); + #endif /* MYSQL_SERVER */ #endif /* SQL_CLASS_INCLUDED */ diff --git a/sql/threadpool.h b/sql/threadpool.h index 2b0d09c0d6d..a3ecca3302b 100644 --- a/sql/threadpool.h +++ b/sql/threadpool.h @@ -46,11 +46,10 @@ extern TP_STATISTICS tp_stats; /* Functions to set threadpool parameters */ extern void tp_set_min_threads(uint val); extern void tp_set_max_threads(uint val); -extern int tp_set_threadpool_size(uint val); +extern void tp_set_threadpool_size(uint val); extern void tp_set_threadpool_stall_limit(uint val); /* Activate threadpool scheduler */ extern void tp_scheduler(void); extern int show_threadpool_idle_threads(THD *thd, SHOW_VAR *var, char *buff); - diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index fd641b45faa..d003bae6727 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -136,7 +136,7 @@ int threadpool_add_connection(THD *thd) { retval= 0; thd->net.reading_or_writing= 1; - thd->skip_wait_timeout= true; + thd->skip_wait_timeout= true; } } } @@ -185,10 +185,11 @@ int threadpool_process_request(THD *thd) killed flag was set by timeout handler or KILL command. Return error. */ - worker_context.restore(); - return 1; + retval= 1; + goto end; } + for(;;) { Vio *vio; @@ -196,12 +197,12 @@ int threadpool_process_request(THD *thd) mysql_audit_release(thd); if ((retval= do_command(thd)) != 0) - break ; + goto end; if (!thd_is_connection_alive(thd)) { retval= 1; - break; + goto end; } vio= thd->net.vio; @@ -210,10 +211,11 @@ int threadpool_process_request(THD *thd) /* More info on this debug sync is in sql_parse.cc*/ DEBUG_SYNC(thd, "before_do_command_net_read"); thd->net.reading_or_writing= 1; - break; + goto end; } - } + } +end: worker_context.restore(); return retval; } @@ -234,8 +236,6 @@ static scheduler_functions tp_scheduler_functions= tp_end // end }; -extern void scheduler_init(); - void pool_of_threads_scheduler(struct scheduler_functions *func, ulong *arg_max_connections, uint *arg_connection_count) diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc index 0a1e3ceb8a7..ad44e237262 100644 --- a/sql/threadpool_unix.cc +++ b/sql/threadpool_unix.cc @@ -24,6 +24,11 @@ typedef struct kevent native_event; typedef port_event_t native_event; #endif +/** Maximum number of native events a listener can read in one go */ +#define MAX_EVENTS 1024 + +/** Indicates that threadpool was initialized*/ +static bool threadpool_started= false; /* Define PSI Keys for performance schema. @@ -130,7 +135,7 @@ static uint group_count; Used for printing "pool blocked" message, see print_pool_blocked_message(); */ -static time_t pool_block_start; +static ulonglong pool_block_start; /* Global timer for all groups */ struct pool_timer_t @@ -145,11 +150,6 @@ struct pool_timer_t static pool_timer_t pool_timer; - -/* Externals functions and variables we use */ -extern void scheduler_init(); -extern pthread_attr_t *get_connection_attrib(void); - static void queue_put(thread_group_t *thread_group, connection_t *connection); static int wake_thread(thread_group_t *thread_group); static void handle_event(connection_t *connection); @@ -462,6 +462,9 @@ static void timeout_check(pool_timer_t *timer) Besides checking for stalls, timer thread is also responsible for terminating clients that have been idle for longer than wait_timeout seconds. + + TODO: Let the timer sleep for long time if there is no work to be done. + Currently it wakes up rather often on and idle server. */ static void* timer_thread(void *param) @@ -491,7 +494,7 @@ static void* timer_thread(void *param) { timer->current_microtime= microsecond_interval_timer(); - /* Check stallls in thread groups */ + /* Check stalls in thread groups */ for(i=0; i< array_elements(all_groups);i++) { if(all_groups[i].connection_count) @@ -574,7 +577,6 @@ static void stop_timer(pool_timer_t *timer) DBUG_VOID_RETURN; } -#define MAX_EVENTS 1024 /** Poll for socket events and distribute them to worker threads @@ -586,10 +588,8 @@ static connection_t * listener(worker_thread_t *current_thread, thread_group_t *thread_group) { DBUG_ENTER("listener"); - connection_t *retval= NULL; - - + for(;;) { native_event ev[MAX_EVENTS]; @@ -767,7 +767,6 @@ static int create_worker(thread_group_t *thread_group) { my_errno= errno; } - end: if (err) @@ -897,11 +896,10 @@ static int wake_thread(thread_group_t *thread_group) { thread->woken= true; thread_group->waiting_threads.remove(thread); - if (mysql_cond_signal(&thread->cond)) - abort(); + mysql_cond_signal(&thread->cond); DBUG_RETURN(0); } - DBUG_RETURN(-1); /* no thread- missed wakeup*/ + DBUG_RETURN(1); /* no thread in waiter list => missed wakeup */ } @@ -1188,7 +1186,7 @@ void tp_add_connection(THD *thd) /* Assign connection to a group. */ thread_group_t *group= - &all_groups[connection->thd->thread_id%group_count]; + &all_groups[thd->thread_id%group_count]; connection->thread_group=group; @@ -1416,12 +1414,13 @@ static void handle_event(connection_t *connection) err= threadpool_process_request(connection->thd); } - if (!err) - { - set_wait_timeout(connection); - err= start_io(connection); - } + if(err) + goto end; + + set_wait_timeout(connection); + err= start_io(connection); +end: if (err) connection_abort(connection); @@ -1481,11 +1480,10 @@ static void *worker_main(void *param) } -static bool started=false; bool tp_init() { DBUG_ENTER("tp_init"); - started = true; + threadpool_started= true; scheduler_init(); for(uint i=0; i < array_elements(all_groups); i++) @@ -1493,7 +1491,12 @@ bool tp_init() thread_group_init(&all_groups[i], get_connection_attrib()); } tp_set_threadpool_size(threadpool_size); - + if(group_count == 0) + { + /* Something went wrong */ + sql_print_error("Can't set threadpool size to %d",threadpool_size); + DBUG_RETURN(1); + } PSI_register(mutex); PSI_register(cond); PSI_register(thread); @@ -1508,7 +1511,7 @@ void tp_end() { DBUG_ENTER("tp_end"); - if (!started) + if (!threadpool_started) DBUG_VOID_RETURN; stop_timer(&pool_timer); @@ -1516,18 +1519,18 @@ void tp_end() { thread_group_close(&all_groups[i]); } - started= false; + threadpool_started= false; DBUG_VOID_RETURN; } /** Ensure that poll descriptors are created when threadpool_size changes */ -int tp_set_threadpool_size(uint size) +void tp_set_threadpool_size(uint size) { bool success= true; - if (!started) - return 0; + if (!threadpool_started) + return; for(uint i=0; i< size; i++) { @@ -1537,21 +1540,25 @@ int tp_set_threadpool_size(uint size) { group->pollfd= io_poll_create(); success= (group->pollfd >= 0); + if(!success) + { + sql_print_error("io_poll_create() failed, errno=%d\n", errno); + break; + } } mysql_mutex_unlock(&all_groups[i].mutex); if (!success) { - group_count= i-1; - return -1; + group_count= i; + return; } } group_count= size; - return 0; } void tp_set_threadpool_stall_limit(uint limit) { - if (!started) + if (!threadpool_started) return; mysql_mutex_lock(&(pool_timer.mutex)); pool_timer.tick_interval= limit; @@ -1582,20 +1589,23 @@ int tp_get_idle_thread_count() /* Report threadpool problems */ -#define BLOCK_MSG_DELAY 30 +/** + Delay in microseconds, after which "pool blocked" message is printed. + (30 sec == 30 Mio usec) +*/ +#define BLOCK_MSG_DELAY 30*1000000 -static const char *max_threads_reached_msg= -"Threadpool could not create additional thread to handle queries, because the " -"number of allowed threads was reached. Increasing 'thread_pool_max_threads' " -"parameter can help in this situation.\n" -"If 'extra_port' parameter is set, you can still connect to the database with " -"superuser account (it must be TCP connection using extra_port as TCP port) " -"and troubleshoot the situation. " -"A likely cause of pool blocks are clients that lock resources for long time. " -"'show processlist' or 'show engine innodb status' can give additional hints."; +#define MAX_THREADS_REACHED_MSG \ +"Threadpool could not create additional thread to handle queries, because the \ +number of allowed threads was reached. Increasing 'thread_pool_max_threads' \ +parameter can help in this situation.\n \ +If 'extra_port' parameter is set, you can still connect to the database with \ +superuser account (it must be TCP connection using extra_port as TCP port) \ +and troubleshoot the situation. \ +A likely cause of pool blocks are clients that lock resources for long time. \ +'show processlist' or 'show engine innodb status' can give additional hints." -static const char *create_thread_error_msg= -"Can't create threads in threadpool (errno=%d)."; +#define CREATE_THREAD_ERROR_MSG "Can't create threads in threadpool (errno=%d)." /** Write a message when blocking situation in threadpool occurs. @@ -1606,10 +1616,10 @@ static const char *create_thread_error_msg= static void print_pool_blocked_message(bool max_threads_reached) { - time_t now; + ulonglong now; static bool msg_written; - now= time(NULL); + now= microsecond_interval_timer(); if (pool_block_start == 0) { pool_block_start= now; @@ -1620,12 +1630,12 @@ static void print_pool_blocked_message(bool max_threads_reached) if (now > pool_block_start + BLOCK_MSG_DELAY && !msg_written) { if (max_threads_reached) - sql_print_error(max_threads_reached_msg); + sql_print_error(MAX_THREADS_REACHED_MSG); else - sql_print_error(create_thread_error_msg, my_errno); + sql_print_error(CREATE_THREAD_ERROR_MSG, my_errno); sql_print_information("Threadpool has been blocked for %u seconds\n", - (uint)(now- pool_block_start)); + (uint)((now- pool_block_start)/1000000)); /* avoid reperated messages for the same blocking situation */ msg_written= true; } |