diff options
author | unknown <petr@mysql.com> | 2004-10-23 11:32:52 +0400 |
---|---|---|
committer | unknown <petr@mysql.com> | 2004-10-23 11:32:52 +0400 |
commit | a5435ea78ab3d62223fd94ebd7c730f8ded30f1b (patch) | |
tree | 0b27802fdecb258338fcfe759144e818e42083c2 /server-tools/instance-manager/thread_registry.cc | |
parent | 746e6e53e7c945327aabf560ff0fbc3fe16bf7cb (diff) | |
download | mariadb-git-a5435ea78ab3d62223fd94ebd7c730f8ded30f1b.tar.gz |
Intermediate commit - just to make new files visible to bk in the new
tree
server-tools/instance-manager/Makefile.am:
Fixed IM linking to avoid using both mysys and libmysql as the define the
same symbols and therefore conflict
server-tools/instance-manager/listener.cc:
Added ability to listen network ports
server-tools/instance-manager/listener.h:
Various additions to the Listener_thread_args
server-tools/instance-manager/log.cc:
merge
server-tools/instance-manager/log.h:
merge
server-tools/instance-manager/manager.cc:
Fixes and additions to enable guardian functionality
server-tools/instance-manager/manager.h:
Changed manager() signature
server-tools/instance-manager/mysqlmanager.cc:
Various fixes
server-tools/instance-manager/options.cc:
Added handling of default values for new options in the Options struct. (such
as default_user, default_password, monitoring_interval e.t.c)
server-tools/instance-manager/options.h:
Added new options to the Options struct
sql/net_serv.cc:
Added MYSQL_INSTANCE_MANAGER defines to enable alarm handling in the IM
server-tools/instance-manager/buffer.cc:
Simple implementation of variable-length buffer
server-tools/instance-manager/command.cc:
Abstract command. All commands are derived from Command class
server-tools/instance-manager/commands.h:
Interfaces for all commands we have
server-tools/instance-manager/factory.cc:
Commands factory. This class hides command instantiation. The idea is to
handle various protocols this way. (different commands for different
protocols
server-tools/instance-manager/guardian.cc:
Guardian thread implementation (monitor and restart instances in case of a
failure
server-tools/instance-manager/guardian.h:
Guardian_thread and Guardian_thread_args class interface. The
Guardian_thread is responsible for monitoring and restarting instances
server-tools/instance-manager/instance.cc:
Instance class contains methods and data to manage a single instance
server-tools/instance-manager/instance.h:
This file contains class an instance class interface. The class is
responsible for starting/stopping an instance
server-tools/instance-manager/instance_map.cc:
The instance repository. This class is also responsible for initialization
of Instance class objects.
server-tools/instance-manager/instance_options.cc:
The Instance_options class contains all methods to get and handle options
of an instance
server-tools/instance-manager/mysql_connection.cc:
The class responsible for handling MySQL client/server protocol connections
server-tools/instance-manager/mysql_manager_error.h:
The list of Instance Manger-specific errors
server-tools/instance-manager/parse.cc:
Simple query parser
server-tools/instance-manager/parse.h:
Parser interface
server-tools/instance-manager/protocol.cc:
Here implemented functions used to handle mysql client/server protocol
server-tools/instance-manager/protocol.h:
Interface for MySQL client/server protocol
server-tools/instance-manager/thread_registry.cc:
Thread registry stores information about every thread. It's main function is
to provide graceful shutdown for all threads.
server-tools/instance-manager/user_map.h:
User map contains hash with user names and passwords
Diffstat (limited to 'server-tools/instance-manager/thread_registry.cc')
-rw-r--r-- | server-tools/instance-manager/thread_registry.cc | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/server-tools/instance-manager/thread_registry.cc b/server-tools/instance-manager/thread_registry.cc new file mode 100644 index 00000000000..4037da71880 --- /dev/null +++ b/server-tools/instance-manager/thread_registry.cc @@ -0,0 +1,206 @@ +/* Copyright (C) 2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + 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; either version 2 of the License, or + (at your option) any later version. + + 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 */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "thread_registry.h" + +#include <assert.h> +#include <signal.h> +#include <thr_alarm.h> +#include "log.h" + + +/* Kick-off signal handler */ + +enum { THREAD_KICK_OFF_SIGNAL= SIGUSR2 }; + +static void handle_signal(int __attribute__((unused)) sig_no) +{ +} + + +/* + TODO: think about moving signal information (now it's shutdown_in_progress) + to Thread_info. It will reduce contention and allow signal deliverence to + a particular thread, not to the whole worker crew +*/ + +Thread_registry::Thread_registry() : + shutdown_in_progress(false) + ,sigwait_thread_pid(pthread_self()) +{ + pthread_mutex_init(&LOCK_thread_registry, 0); + pthread_cond_init(&COND_thread_registry_is_empty, 0); + + /* head is used by-value to simplify nodes inserting */ + head.next= head.prev= &head; +} + + +Thread_registry::~Thread_registry() +{ + /* Check that no one uses the repository. */ + pthread_mutex_lock(&LOCK_thread_registry); + + /* All threads must unregister */ + DBUG_ASSERT(head.next == &head); + + pthread_mutex_unlock(&LOCK_thread_registry); + pthread_cond_destroy(&COND_thread_registry_is_empty); + pthread_mutex_destroy(&LOCK_thread_registry); +} + + +/* + Set signal handler for kick-off thread, and insert a thread info to the + repository. New node is appended to the end of the list; head.prev always + points to the last node. +*/ + +void Thread_registry::register_thread(Thread_info *info) +{ + struct sigaction sa; + sa.sa_handler= handle_signal; + sa.sa_flags= 0; + sigemptyset(&sa.sa_mask); + sigaction(THREAD_KICK_OFF_SIGNAL, &sa, 0); + + info->current_cond= 0; + + pthread_mutex_lock(&LOCK_thread_registry); + info->next= &head; + info->prev= head.prev; + head.prev->next= info; + head.prev= info; + pthread_mutex_unlock(&LOCK_thread_registry); +} + + +/* + Unregister a thread from the repository and free Thread_info structure. + Every registered thread must unregister. Unregistering should be the last + thing a thread is doing, otherwise it could have no time to finalize. +*/ + +void Thread_registry::unregister_thread(Thread_info *info) +{ + pthread_mutex_lock(&LOCK_thread_registry); + info->prev->next= info->next; + info->next->prev= info->prev; + if (head.next == &head) + pthread_cond_signal(&COND_thread_registry_is_empty); + pthread_mutex_unlock(&LOCK_thread_registry); +} + + +/* + Check whether shutdown is in progress, and if yes, return immediately. + Else set info->current_cond and call pthread_cond_wait. When + pthread_cond_wait returns, unregister current cond and check the shutdown + status again. + RETURN VALUE + return value from pthread_cond_wait +*/ + +int Thread_registry::cond_wait(Thread_info *info, pthread_cond_t *cond, + pthread_mutex_t *mutex, bool *is_shutdown) +{ + pthread_mutex_lock(&LOCK_thread_registry); + *is_shutdown= shutdown_in_progress; + if (*is_shutdown) + { + pthread_mutex_unlock(&LOCK_thread_registry); + return 0; + } + info->current_cond= cond; + pthread_mutex_unlock(&LOCK_thread_registry); + /* sic: race condition here, cond can be signaled in deliver_shutdown */ + int rc= pthread_cond_wait(cond, mutex); + pthread_mutex_lock(&LOCK_thread_registry); + info->current_cond= 0; + *is_shutdown= shutdown_in_progress; + pthread_mutex_unlock(&LOCK_thread_registry); + return rc; +} + + +/* + Deliver shutdown message to the workers crew. + As it's impossible to avoid all race conditions, signal latecomers + again. +*/ + +void Thread_registry::deliver_shutdown() +{ + struct timespec shutdown_time; + set_timespec(shutdown_time, 1); + + pthread_mutex_lock(&LOCK_thread_registry); + shutdown_in_progress= true; + + /* to stop reading from the network we need to flush alarm queue */ + end_thr_alarm(0); + /* + We have to deliver final alarms this way, as the main thread has already + stopped alarm processing. + */ + process_alarm(THR_SERVER_ALARM); + for (Thread_info *info= head.next; info != &head; info= info->next) + { + pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL); + /* + sic: race condition here, the thread may not yet fall into + pthread_cond_wait. + */ + if (info->current_cond) + pthread_cond_signal(info->current_cond); + } + /* + The common practice is to test predicate before pthread_cond_wait. + I don't do that here because the predicate is practically always false + before wait - is_shutdown's been just set, and the lock's still not + released - the only case when the predicate is false is when no other + threads exist. + */ + while (pthread_cond_timedwait(&COND_thread_registry_is_empty, + &LOCK_thread_registry, + &shutdown_time) != ETIMEDOUT && + head.next != &head) + ; + /* + If previous signals did not reach some threads, they must be sleeping + in pthread_cond_wait or in a blocking syscall. Wake them up: + every thread shall check signal variables after each syscall/cond_wait, + so this time everybody should be informed (presumably each worker can + get CPU during shutdown_time.) + */ + for (Thread_info *info= head.next; info != &head; info= info->next) + { + pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL); + if (info->current_cond) + pthread_cond_signal(info->current_cond); + } + pthread_mutex_unlock(&LOCK_thread_registry); +} + + +void Thread_registry::request_shutdown() +{ + pthread_kill(sigwait_thread_pid, SIGTERM); +} |