diff options
author | unknown <petr@mysql.com> | 2005-01-25 13:54:56 +0300 |
---|---|---|
committer | unknown <petr@mysql.com> | 2005-01-25 13:54:56 +0300 |
commit | fb3d6c39a0dc128f5310aac2906cc1e6c6b7db59 (patch) | |
tree | ada085796e1dc8387942522e6233d9a1b1a1d6d3 /server-tools | |
parent | 28f86d8ff1d042a2224c64712e31c65b1d6b7476 (diff) | |
download | mariadb-git-fb3d6c39a0dc128f5310aac2906cc1e6c6b7db59.tar.gz |
IM mostly fixed according to Brian's directions. Will need to do some additional option handling and cleanups
server-tools/instance-manager/Makefile.am:
New file added
server-tools/instance-manager/client_func.c:
typo fixed
server-tools/instance-manager/commands.cc:
there are no admin-user snd admin-password fields anymore, so no need to show their values
server-tools/instance-manager/guardian.cc:
Syncronization added -- now guardian wakes up whenever SIGCLD has been catched
server-tools/instance-manager/guardian.h:
Condition variable declared
server-tools/instance-manager/instance.cc:
Persistent connection to the instance removed. Now we use SIGTERM instead of com_shutdown for STOP. We also
manage SIGCHLD ourselves now (therefore no double fork).
server-tools/instance-manager/instance.h:
Pointer to the instance_map added, MySQL connection structures removed
server-tools/instance-manager/instance_map.cc:
More syncronization added (to make proper STOP)
server-tools/instance-manager/instance_map.h:
added condition variable and mutex for connection threads to wait for SIGCHLD
server-tools/instance-manager/instance_options.cc:
defaults-handling methods have been added.
server-tools/instance-manager/instance_options.h:
New functions and constants declared
server-tools/instance-manager/listener.cc:
No changes here (bk bug?)
server-tools/instance-manager/manager.cc:
SIGCHLD handling added
Diffstat (limited to 'server-tools')
-rw-r--r-- | server-tools/instance-manager/Makefile.am | 1 | ||||
-rw-r--r-- | server-tools/instance-manager/client_func.c | 2 | ||||
-rw-r--r-- | server-tools/instance-manager/commands.cc | 24 | ||||
-rw-r--r-- | server-tools/instance-manager/guardian.cc | 15 | ||||
-rw-r--r-- | server-tools/instance-manager/guardian.h | 3 | ||||
-rw-r--r-- | server-tools/instance-manager/instance.cc | 136 | ||||
-rw-r--r-- | server-tools/instance-manager/instance.h | 11 | ||||
-rw-r--r-- | server-tools/instance-manager/instance_map.cc | 9 | ||||
-rw-r--r-- | server-tools/instance-manager/instance_map.h | 8 | ||||
-rw-r--r-- | server-tools/instance-manager/instance_options.cc | 131 | ||||
-rw-r--r-- | server-tools/instance-manager/instance_options.h | 18 | ||||
-rw-r--r-- | server-tools/instance-manager/manager.cc | 22 | ||||
-rw-r--r-- | server-tools/instance-manager/parse_output.cc | 82 | ||||
-rw-r--r-- | server-tools/instance-manager/parse_output.h | 19 |
14 files changed, 377 insertions, 104 deletions
diff --git a/server-tools/instance-manager/Makefile.am b/server-tools/instance-manager/Makefile.am index c2bf501eca7..fcc4a60c7a8 100644 --- a/server-tools/instance-manager/Makefile.am +++ b/server-tools/instance-manager/Makefile.am @@ -75,6 +75,7 @@ mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \ instance_options.h instance_options.cc \ buffer.h buffer.cc parse.cc parse.h \ guardian.cc guardian.h \ + parse_output.cc parse_output.h \ mysql_manager_error.h client_func.c mysqlmanager_LDADD= liboptions.a \ diff --git a/server-tools/instance-manager/client_func.c b/server-tools/instance-manager/client_func.c index a7ff1d27a8f..92c106e5172 100644 --- a/server-tools/instance-manager/client_func.c +++ b/server-tools/instance-manager/client_func.c @@ -3,7 +3,7 @@ #include <mysql.h> /* - Currently we cannot use libmysqlclient directly becouse of the linking + Currently we cannot use libmysqlclient directly because of the linking issues. Here we provide needed libmysqlclient functions. TODO: to think how to use libmysqlclient code instead of copy&paste. The other possible solution is to use simple_command directly. diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc index dacace1af1e..4922aba4a06 100644 --- a/server-tools/instance-manager/commands.cc +++ b/server-tools/instance-manager/commands.cc @@ -175,7 +175,7 @@ int Show_instance_status::do_command(struct st_net *net, if (instance->is_running()) { store_to_string(&send_buff, (char *) "online", &position); - store_to_string(&send_buff, mysql_get_server_info(&(instance->mysql)), &position); + store_to_string(&send_buff, "unknown", &position); } else { @@ -283,28 +283,6 @@ int Show_instance_options::do_command(struct st_net *net, goto err; } - if (instance->options.mysqld_user != NULL) - { - position= 0; - store_to_string(&send_buff, (char *) "admin-user", &position); - store_to_string(&send_buff, - (char *) instance->options.mysqld_user, - &position); - if (my_net_write(net, send_buff.buffer, (uint) position)) - goto err; - } - - if (instance->options.mysqld_password != NULL) - { - position= 0; - store_to_string(&send_buff, (char *) "admin-password", &position); - store_to_string(&send_buff, - (char *) instance->options.mysqld_password, - &position); - if (my_net_write(net, send_buff.buffer, (uint) position)) - goto err; - } - /* loop through the options stored in DYNAMIC_ARRAY */ for (uint i= 0; i < instance->options.options_array.elements; i++) { diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index 7375453673b..f68ef6575a0 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -45,6 +45,7 @@ Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg, thread_info(pthread_self()) { pthread_mutex_init(&LOCK_guardian, 0); + pthread_cond_init(&COND_guardian, 0); thread_registry.register_thread(&thread_info); init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0); guarded_instances= NULL; @@ -60,6 +61,7 @@ Guardian_thread::~Guardian_thread() thread_registry.unregister_thread(&thread_info); pthread_mutex_unlock(&LOCK_guardian); pthread_mutex_destroy(&LOCK_guardian); + pthread_cond_destroy(&COND_guardian); } @@ -79,27 +81,32 @@ void Guardian_thread::run() { Instance *instance; LIST *loop; + struct timespec timeout; my_thread_init(); + pthread_mutex_lock(&LOCK_guardian); + while (!thread_registry.is_shutdown()) { - pthread_mutex_lock(&LOCK_guardian); loop= guarded_instances; while (loop != NULL) { instance= (Instance *) loop->data; - /* instance-> start already checks whether instance is running */ + /* instance-> start already checks whether the instance is running */ if (instance->start() != ER_INSTANCE_ALREADY_STARTED) log_info("guardian attempted to restart instance %s", instance->options.instance_name); loop= loop->next; } move_to_list(&starting_instances, &guarded_instances); - pthread_mutex_unlock(&LOCK_guardian); - sleep(monitoring_interval); + timeout.tv_sec= time(NULL) + monitoring_interval; + timeout.tv_nsec= 0; + + pthread_cond_timedwait(&COND_guardian, &LOCK_guardian, &timeout); } + pthread_mutex_unlock(&LOCK_guardian); my_thread_end(); } diff --git a/server-tools/instance-manager/guardian.h b/server-tools/instance-manager/guardian.h index 0ae2161f1dc..bcc249ed7d3 100644 --- a/server-tools/instance-manager/guardian.h +++ b/server-tools/instance-manager/guardian.h @@ -70,6 +70,9 @@ public: int guard(Instance *instance); int stop_guard(Instance *instance); +public: + pthread_cond_t COND_guardian; + private: int add_instance_to_list(Instance *instance, LIST **list); void move_to_list(LIST **from, LIST **to); diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 58bc5b85dd8..edb9ea61ad3 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -21,6 +21,7 @@ #include "instance.h" #include "mysql_manager_error.h" #include "log.h" +#include "instance_map.h" #include <my_sys.h> #include <signal.h> #include <m_string.h> @@ -41,24 +42,18 @@ int Instance::start() { - pid_t pid; - + /* echk for the pidfile and remove it */ if (!is_running()) { - log_info("trying to start instance %s", options.instance_name); + stop(); + log_info("starting instance %s", options.instance_name); switch (pid= fork()) { case 0: - if (fork()) /* zombie protection */ - exit(0); /* parent goes bye-bye */ - else - { - execv(options.mysqld_path, options.argv); - exit(1); - } + execv(options.mysqld_path, options.argv); + exit(1); case -1: return ER_CANNOT_START_INSTANCE; default: - waitpid(pid, NULL, 0); return 0; } } @@ -67,15 +62,9 @@ int Instance::start() return ER_INSTANCE_ALREADY_STARTED; } + int Instance::cleanup() { - /* - We cannot close connection in destructor, as mysql_close needs alarm - services which are definitely unavailaible at the time of destructor - call. - */ - if (is_connected) - mysql_close(&mysql); return 0; } @@ -88,8 +77,13 @@ Instance::~Instance() bool Instance::is_running() { + MYSQL mysql; uint port= 0; const char *socket= NULL; + const char *password= "321rarepassword213"; + const char *username= "645rareusername945"; + const char *access_denied_message= "Access denied for user"; + bool return_val; if (options.mysqld_port) port= atoi(strchr(options.mysqld_port, '=') + 1); @@ -98,30 +92,40 @@ bool Instance::is_running() socket= strchr(options.mysqld_socket, '=') + 1; pthread_mutex_lock(&LOCK_instance); - if (!is_connected) + + mysql_init(&mysql); + /* try to connect to a server with the fake username/password pair */ + if (mysql_real_connect(&mysql, LOCAL_HOST, username, + password, + NullS, port, + socket, 0)) { - mysql_init(&mysql); - if (mysql_real_connect(&mysql, LOCAL_HOST, options.mysqld_user, - options.mysqld_password, - NullS, port, - socket, 0)) - { - mysql.reconnect= 1; - is_connected= TRUE; - pthread_mutex_unlock(&LOCK_instance); - return TRUE; - } + /* + Very strange. We have successfully connected to the server using + bullshit as username/password. Write a warning to the logfile. + */ + log_info("The Instance Manager was able to log into you server \ + with faked compiled-in password while checking server status. \ + Looks like something is wrong."); mysql_close(&mysql); pthread_mutex_unlock(&LOCK_instance); - return FALSE; + return_val= TRUE; /* server is alive */ } - else if (!mysql_ping(&mysql)) + else { - pthread_mutex_unlock(&LOCK_instance); - return TRUE; + if (!strncmp(access_denied_message, mysql_error(&mysql), + sizeof(access_denied_message)-1)) + { + return_val= TRUE; + } + else + return_val= FALSE; } + + mysql_close(&mysql); pthread_mutex_unlock(&LOCK_instance); - return FALSE; + + return return_val; } @@ -139,13 +143,58 @@ bool Instance::is_running() int Instance::stop() { - if (is_running()) + pid_t pid; + struct timespec timeout; + time_t waitchild= 35; /* */ + + if ((pid= options.get_pid()) != 0) /* get pid from pidfile */ { - if (mysql_shutdown(&mysql, SHUTDOWN_DEFAULT)) - goto err; + /* + If we cannot kill mysqld, then it has propably crashed. + Let us try to remove staled pidfile and return succes as mysqld + is stopped + */ + if (kill(pid, SIGTERM)) + { + if (options.unlink_pidfile()) + log_error("cannot remove pidfile for instance %i, this might be \ + since IM lacks permmissions or hasn't found the pidifle", + options.instance_name); + + log_error("The instance %s has probably crashed or IM lacks permissions \ + to kill it. in either case something seems to be wrong. \ + Check your setup", options.instance_name); + return 0; + } + + /* sleep on condition to wait for SIGCHLD */ + + timeout.tv_sec= time(NULL) + waitchild; + timeout.tv_nsec= 0; + if (pthread_mutex_lock(&instance_map->pid_cond.LOCK_pid)) + goto err; /* perhaps this should be procecced differently */ + + while (options.get_pid() != 0) + { + int status; + + status= pthread_cond_timedwait(&instance_map->pid_cond.COND_pid, + &instance_map->pid_cond.LOCK_pid, + &timeout); + if (status == ETIMEDOUT) + break; + } + + pthread_mutex_unlock(&instance_map->pid_cond.LOCK_pid); + + if (!kill(pid, SIGKILL)) + { + log_error("The instance %s has been stopped forsibly. Normally \ + it should not happed. Probably the instance has been \ + hanging. You should also check your IM setup", + options.instance_name); + } - mysql_close(&mysql); - is_connected= FALSE; return 0; } @@ -166,3 +215,10 @@ int Instance::init(const char *name_arg) return options.init(name_arg); } + + +int Instance::complete_initialization(Instance_map *instance_map_arg) +{ + instance_map= instance_map_arg; + return 0; +} diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h index 6733985116a..78b7768c121 100644 --- a/server-tools/instance-manager/instance.h +++ b/server-tools/instance-manager/instance.h @@ -25,14 +25,14 @@ #pragma interface #endif +class Instance_map; + class Instance { public: - Instance(): is_connected(FALSE) - {} ~Instance(); - int init(const char *name); + int complete_initialization(Instance_map *instance_map_arg); /* check if the instance is running and set up mysql connection if yes */ bool is_running(); @@ -44,7 +44,7 @@ public: Instance_options options; /* connection to the instance */ - MYSQL mysql; + pid_t pid; private: /* @@ -53,8 +53,7 @@ private: and we issue the start command once more. */ pthread_mutex_t LOCK_instance; - /* Here we store the state of the following connection */ - bool is_connected; + Instance_map *instance_map; }; #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H */ diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc index 9399d6e2563..2573729841b 100644 --- a/server-tools/instance-manager/instance_map.cc +++ b/server-tools/instance-manager/instance_map.cc @@ -123,6 +123,9 @@ Instance_map::Instance_map(const char *default_mysqld_path_arg, int Instance_map::init() { + pthread_mutex_init(&pid_cond.LOCK_pid, 0); + pthread_cond_init(&pid_cond.COND_pid, 0); + if (hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0, get_instance_key, delete_instance, 0)) return 1; @@ -135,6 +138,8 @@ Instance_map::~Instance_map() hash_free(&hash); pthread_mutex_unlock(&LOCK_instance_map); pthread_mutex_destroy(&LOCK_instance_map); + pthread_mutex_destroy(&pid_cond.LOCK_pid); + pthread_cond_destroy(&pid_cond.COND_pid); } @@ -189,6 +194,7 @@ void Instance_map::complete_initialization() while (i < hash.records) { instance= (Instance *) hash_element(&hash, i); + instance->complete_initialization(this); instance->options.complete_initialization(mysqld_path, user, password); i++; } @@ -218,7 +224,8 @@ Instance_map::find(uint instance_number) Instance *instance; char name[80]; - sprintf(name, "mysqld%i", instance_number); + snprintf(name, sizeof(name) - 1, "mysqld%i", instance_number); + name[sizeof(name) - 1]= 0; /* safety */ pthread_mutex_lock(&LOCK_instance_map); instance= (Instance *) hash_search(&hash, (byte *) name, strlen(name)); pthread_mutex_unlock(&LOCK_instance_map); diff --git a/server-tools/instance-manager/instance_map.h b/server-tools/instance-manager/instance_map.h index 522785ce9b9..1f6072f2582 100644 --- a/server-tools/instance-manager/instance_map.h +++ b/server-tools/instance-manager/instance_map.h @@ -27,6 +27,12 @@ #include "protocol.h" #include "guardian.h" +typedef struct st_instance_cond +{ + pthread_mutex_t LOCK_pid; + pthread_cond_t COND_pid; +} CHILD_COND; + class Instance; extern int load_all_groups(char ***groups, const char *filename); extern void free_groups(char **groups); @@ -83,6 +89,8 @@ public: const char *user; const char *password; Guardian_thread *guardian; + /* structure used for syncronization reasons in the stop command */ + CHILD_COND pid_cond; private: enum { START_HASH_SIZE = 16 }; diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index fab69865c85..c29f136955e 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -19,20 +19,105 @@ #endif #include "instance_options.h" +#include "parse_output.h" +#include "buffer.h" #include <my_sys.h> #include <mysql.h> #include <signal.h> #include <m_string.h> + +/* option_name should be prefixed with "--" */ +int Instance_options::get_default_option(char *result, const char *option_name, + size_t result_len) +{ + int position= 0; + char verbose_option[]= " --no-defaults --verbose --help"; + Buffer cmd; + + cmd.append(position, mysqld_path, strlen(mysqld_path)); + position+= strlen(mysqld_path); + cmd.append(position, verbose_option, sizeof(verbose_option) - 1); + position+= sizeof(verbose_option) - 1; + cmd.append(position, "\0", 1); + /* get the value from "mysqld --help --verbose" */ + if (parse_output_and_get_value(cmd.buffer, option_name + 2, + result, result_len)) + return 1; + + return 0; +} + + +void Instance_options::get_pid_filename(char *result) +{ + const char *pid_file= mysqld_pid_file; + char datadir[MAX_PATH_LEN]; + + if (mysqld_datadir == NULL) + { + get_default_option(datadir, "--datadir", MAX_PATH_LEN); + } + else + strxnmov(datadir, MAX_PATH_LEN - 1, strchr(mysqld_datadir, '=') + 1, + "/", NullS); + + /* well, we should never get it */ + if (mysqld_pid_file != NULL) + pid_file= strchr(pid_file, '=') + 1; + else + DBUG_ASSERT(0); + + /* get the full path to the pidfile */ + my_load_path(result, pid_file, datadir); + +} + + +int Instance_options::unlink_pidfile() +{ + char pid_file_path[MAX_PATH_LEN]; + + /* + This works as we know that pid_file_path is of + MAX_PATH_LEN == FN_REFLEN length + */ + get_pid_filename((char *)&pid_file_path); + + return unlink(pid_file_path); +} + + +pid_t Instance_options::get_pid() +{ + char pid_file_path[MAX_PATH_LEN]; + + /* + This works as we know that pid_file_path is of + MAX_PATH_LEN == FN_REFLEN length + */ + get_pid_filename((char *)&pid_file_path); + + /* get the pid */ + if (FILE *pid_file_stream= my_fopen(pid_file_path, + O_RDONLY | O_BINARY, MYF(0))) + { + pid_t pid; + + fscanf(pid_file_stream, "%i", &pid); + my_fclose(pid_file_stream, MYF(0)); + return pid; + } + else + return 0; +} + + int Instance_options::complete_initialization(const char *default_path, const char *default_user, const char *default_password) { - /* we need to reserve space for the final zero + possible default options */ - if (!(argv= (char**) alloc_root(&alloc, (options_array.elements + 1 - + MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*)))) - goto err; - + const char *tmp; if (mysqld_path == NULL) { @@ -40,22 +125,34 @@ int Instance_options::complete_initialization(const char *default_path, goto err; } - /* this option must be first in the argv */ - if (add_to_argv(mysqld_path)) + if (!(tmp= strdup_root(&alloc, "--no-defaults"))) goto err; - /* the following options are not for argv */ - if (mysqld_user == NULL) + if (mysqld_pid_file == NULL) { - if (!(mysqld_user= strdup_root(&alloc, default_user))) - goto err; + char pidfilename[MAX_PATH_LEN]; + char hostname[MAX_PATH_LEN]; + if (!gethostname(hostname, sizeof(hostname) - 1)) + strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", hostname, "-", + instance_name, ".pid", NullS); + else + strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, + ".pid", NullS); + + add_option(pidfilename); } - if (mysqld_password == NULL) - { - if (!(mysqld_password= strdup_root(&alloc, default_password))) - goto err; - } + /* we need to reserve space for the final zero + possible default options */ + if (!(argv= (char**) alloc_root(&alloc, (options_array.elements + 1 + + MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*)))) + goto err; + + /* the path must be first in the argv */ + if (add_to_argv(mysqld_path)) + goto err; + + if (add_to_argv(tmp)) + goto err; memcpy((gptr) (argv + filled_default_options), options_array.buffer, options_array.elements*sizeof(char*)); @@ -102,8 +199,6 @@ int Instance_options::add_option(const char* option) {"--bind-address=", 15, &mysqld_bind_address, SAVE_WHOLE_AND_ADD}, {"--pid-file=", 11, &mysqld_pid_file, SAVE_WHOLE_AND_ADD}, {"--mysqld-path=", 14, &mysqld_path, SAVE_VALUE}, - {"--admin-user=", 13, &mysqld_user, SAVE_VALUE}, - {"--admin-password=", 17, &mysqld_password, SAVE_VALUE}, {"--guarded", 9, &is_guarded, SAVE_WHOLE}, {NULL, 0, NULL, 0} }; diff --git a/server-tools/instance-manager/instance_options.h b/server-tools/instance-manager/instance_options.h index 5bc46497d2a..26448c0c2b1 100644 --- a/server-tools/instance-manager/instance_options.h +++ b/server-tools/instance-manager/instance_options.h @@ -38,8 +38,8 @@ class Instance_options public: Instance_options() : mysqld_socket(0), mysqld_datadir(0), mysqld_bind_address(0), - mysqld_pid_file(0), mysqld_port(0), mysqld_path(0), mysqld_user(0), - mysqld_password(0), is_guarded(0), filled_default_options(0) + mysqld_pid_file(0), mysqld_port(0), mysqld_path(0), is_guarded(0), + filled_default_options(0) {} ~Instance_options(); /* fills in argv */ @@ -49,9 +49,17 @@ public: int add_option(const char* option); int init(const char *instance_name_arg); + pid_t get_pid(); + void get_pid_filename(char *result); + int unlink_pidfile(); public: - enum { MAX_NUMBER_OF_DEFAULT_OPTIONS= 1 }; + /* + We need this value to be greater or equal then FN_REFLEN found in + my_global.h to use my_load_path() + */ + enum { MAX_PATH_LEN= 512 }; + enum { MAX_NUMBER_OF_DEFAULT_OPTIONS= 2 }; enum { MEM_ROOT_BLOCK_SIZE= 512 }; char **argv; /* We need the some options, so we store them as a separate pointers */ @@ -63,12 +71,12 @@ public: uint instance_name_len; const char *instance_name; const char *mysqld_path; - const char *mysqld_user; - const char *mysqld_password; const char *is_guarded; DYNAMIC_ARRAY options_array; private: int add_to_argv(const char *option); + int get_default_option(char *result, const char *option_name, + size_t result_len); private: uint filled_default_options; MEM_ROOT alloc; diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index 07d4f1ed33e..a8c6406fb83 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -16,12 +16,6 @@ #include "manager.h" -#include <my_global.h> -#include <my_sys.h> -#include <m_string.h> -#include <signal.h> -#include <thr_alarm.h> - #include "thread_registry.h" #include "listener.h" #include "instance_map.h" @@ -30,6 +24,14 @@ #include "log.h" #include "guardian.h" +#include <my_global.h> +#include <my_sys.h> +#include <m_string.h> +#include <signal.h> +#include <thr_alarm.h> +#include <sys/wait.h> + + static int create_pid_file(const char *pid_file_name) { if (FILE *pid_file= my_fopen(pid_file_name, @@ -90,6 +92,7 @@ void manager(const Options &options) sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGTERM); + sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGPIPE); sigaddset(&mask, SIGHUP); /* @@ -170,6 +173,13 @@ void manager(const Options &options) case THR_SERVER_ALARM: process_alarm(signo); break; + case SIGCHLD: + wait(NULL); + /* wake threads waiting for an instance to shutdown */ + pthread_cond_broadcast(&instance_map.pid_cond.COND_pid); + /* wake guardian */ + pthread_cond_broadcast(&guardian_thread.COND_guardian); + break; default: thread_registry.deliver_shutdown(); shutdown_complete= TRUE; diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc new file mode 100644 index 00000000000..2bc51922e69 --- /dev/null +++ b/server-tools/instance-manager/parse_output.cc @@ -0,0 +1,82 @@ +/* Copyright (C) 2004 MySQL 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 */ + +#include <stdio.h> +#include <my_global.h> +#include <my_sys.h> +#include <string.h> + +/* buf should be of appropriate size. Otherwise the word will be truncated */ +static int get_word(FILE *file, char *buf, size_t size) +{ + int currchar; + + currchar= getc(file); + + /* skip space */ + while (my_isspace(default_charset_info, (char) currchar) && + currchar != EOF && size > 1) + { + currchar= getc(file); + } + + while (!my_isspace(default_charset_info, (char) currchar) && + currchar != EOF && size > 1) + { + *buf++= (char) currchar; + currchar= getc(file); + size--; + } + + *buf= '\0'; + return 0; +} + + +int parse_output_and_get_value(const char *command, const char *word, + char *result, size_t result_len) +{ + FILE *output; + int wordlen; + + wordlen= strlen(word); + + output= popen(command, "r"); + + /* + We want fully buffered stream. We also want system to + allocate appropriate buffer. + */ + setvbuf(output, NULL, _IOFBF, 0); + + get_word(output, result, result_len); + while (strncmp(word, result, wordlen) && *result != '\0') + { + get_word(output, result, result_len); + } + + /* + If we have found the word, return the next one. This is usually + an option value. + */ + if (*result != '\0') + get_word(output, result, result_len); + + if (pclose(output)) + return 1; + + return 0; +} diff --git a/server-tools/instance-manager/parse_output.h b/server-tools/instance-manager/parse_output.h new file mode 100644 index 00000000000..20503a74629 --- /dev/null +++ b/server-tools/instance-manager/parse_output.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2004 MySQL 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 */ + +int parse_output_and_get_value(const char *command, const char *word, + char *result, size_t result_len); + |