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/threadpool_unix.cc | |
parent | 8877fe7359b1eef81b62c6531674aaa5a5ce6051 (diff) | |
download | mariadb-git-cfa56f900acefcf228c26dfa39c1b9142ef3552b.tar.gz |
address second round review comments
Diffstat (limited to 'sql/threadpool_unix.cc')
-rw-r--r-- | sql/threadpool_unix.cc | 110 |
1 files changed, 60 insertions, 50 deletions
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; } |