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/instance_map.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/instance_map.cc')
-rw-r--r-- | server-tools/instance-manager/instance_map.cc | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc new file mode 100644 index 00000000000..89731eb27b9 --- /dev/null +++ b/server-tools/instance-manager/instance_map.cc @@ -0,0 +1,450 @@ +/* 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 */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "instance_map.h" +#include "buffer.h" +#include "instance.h" +#include <m_ctype.h> +#include <my_sys.h> +#include <mysql_com.h> +#include <m_string.h> + +/* + TODO: Currently there are some mysql-connection specific functions. + As we are going to suppost different types of connections, we shouldn't + have them here in future. To avoid it we could put such + connection-specific functions to the Command-derived class instead. + The command could be easily constructed for a specific connection if + we would provide a special factory for each connection. +*/ + +C_MODE_START + +/* Procedure needed for HASH initialization */ + +static byte* get_instance_key(const byte* u, uint* len, + my_bool __attribute__((unused)) t) +{ + const Instance *instance= (const Instance *) u; + *len= instance->options.instance_name_len; + return (byte *) instance->options.instance_name; +} + +static void delete_instance(void *u) +{ + Instance *instance= (Instance *) u; + delete instance; +} + +/* + The option handler to pass to the process_default_option_files finction. + + SYNOPSYS + process_option() + ctx Handler context. Here it is an instance_map structure. + group_name The name of the group the option belongs to. + option The very option to be processed. It is already + prepared to be used in argv (has -- prefix) + + DESCRIPTION + + This handler checks whether a group is an instance group and adds + an option to the appropriate instance class. If this is the first + occurence of an instance name, we'll also create the instance + with such name and add it to the instance map. + + RETURN + 0 - ok + 1 - error occured +*/ + +static int process_option(void * ctx, const char *group, const char *option) +{ + Instance_map *map= NULL; + Instance *instance= NULL; + static const char prefix[]= { 'm', 'y', 's', 'q', 'l', 'd' }; + + map = (Instance_map*) ctx; + if (strncmp(group, prefix, sizeof prefix) == 0 && + (my_isdigit(default_charset_info, group[sizeof prefix]))) + { + if ((instance= map->find(group, strlen(group))) == NULL) + { + if ((instance= new Instance) == 0) + goto err_new_instance; + if (instance->init(group)) + goto err; + if (map->add_instance(instance)) + goto err; + } + + if (instance->options.add_option(option)) + goto err; + } + + return 0; + +err: + delete instance; +err_new_instance: + return 1; +} + +C_MODE_END + + +Instance_map::Instance_map() +{ + hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0, + get_instance_key, delete_instance, 0); + pthread_mutex_init(&LOCK_instance_map, 0); +} + + +Instance_map::~Instance_map() +{ + pthread_mutex_lock(&LOCK_instance_map); + hash_free(&hash); + pthread_mutex_unlock(&LOCK_instance_map); + pthread_mutex_destroy(&LOCK_instance_map); +} + + +int Instance_map::flush_instances() +{ + int rc; + + pthread_mutex_lock(&LOCK_instance_map); + hash_free(&hash); + hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0, + get_instance_key, delete_instance, 0); + rc= load(); + pthread_mutex_unlock(&LOCK_instance_map); + return rc; +} + + +int Instance_map::show_instance_options(struct st_net *net, + const char *instance_name) +{ + enum { MAX_VERSION_LENGTH= 40 }; + Buffer send_buff; /* buffer for packets */ + LIST name, option; + LIST *field_list; + NAME_WITH_LENGTH name_field, option_field; + uint position=0; + + /* create list of the fileds to be passed to send_fields */ + name_field.name= (char *) "option_name"; + name_field.length= 20; + name.data= &name_field; + option_field.name= (char *) "value"; + option_field.length= 20; + option.data= &option_field; + field_list= list_add(NULL, &option); + field_list= list_add(field_list, &name); + + send_fields(net, field_list); + + { + Instance *instance; + + if ((instance= find(instance_name, strlen(instance_name))) == NULL) + goto err; + store_to_string(&send_buff, (char *) "instance_name", &position); + store_to_string(&send_buff, (char *) instance_name, &position); + my_net_write(net, send_buff.buffer, (uint) position); + if (instance->options.mysqld_path != NULL) + { + position= 0; + store_to_string(&send_buff, (char *) "mysqld_path", &position); + store_to_string(&send_buff, + (char *) instance->options.mysqld_path, + &position); + my_net_write(net, send_buff.buffer, (uint) position); + } + + 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); + my_net_write(net, send_buff.buffer, (uint) position); + } + + 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); + my_net_write(net, send_buff.buffer, (uint) position); + } + + /* loop through the options stored in DYNAMIC_ARRAY */ + for (int i= 0; i < instance->options.options_array.elements; i++) + { + char *tmp_option, *option_value; + get_dynamic(&(instance->options.options_array), (gptr) &tmp_option, i); + option_value= strchr(tmp_option, '='); + /* split the option string into two parts */ + *option_value= 0; + position= 0; + store_to_string(&send_buff, tmp_option + 2, &position); + store_to_string(&send_buff, option_value + 1, &position); + /* join name and the value into the same option again */ + *option_value= '='; + my_net_write(net, send_buff.buffer, (uint) position); + } + } + + send_eof(net); + net_flush(net); + + return 0; + +err: + return 1; +} + +/* return the list of running guarded instances */ +int Instance_map::init_guardian() +{ + Instance *instance; + uint i= 0; + + while (i < hash.records) + { + instance= (Instance *) hash_element(&hash, i); + if ((instance->options.is_guarded != NULL) && (instance->is_running())) + if (guardian->guard(instance->options.instance_name, + instance->options.instance_name_len)) + return 1; + i++; + } + + return 0; +} + + +/* + The method sends a list of instances in the instance map to the client. + + SYNOPSYS + show_instances() + net The network connection to the client. + + RETURN + 0 - ok + 1 - error occured +*/ + +int Instance_map::show_instances(struct st_net *net) +{ + Buffer send_buff; /* buffer for packets */ + LIST name, status; + NAME_WITH_LENGTH name_field, status_field; + LIST *field_list; + uint position=0; + + name_field.name= (char *) "instance_name"; + name_field.length= 20; + name.data= &name_field; + status_field.name= (char *) "status"; + status_field.length= 20; + status.data= &status_field; + field_list= list_add(NULL, &status); + field_list= list_add(field_list, &name); + + send_fields(net, field_list); + + { + Instance *instance; + uint i= 0; + + pthread_mutex_lock(&LOCK_instance_map); + while (i < hash.records) + { + position= 0; + instance= (Instance *) hash_element(&hash, i); + store_to_string(&send_buff, instance->options.instance_name, &position); + if (instance->is_running()) + store_to_string(&send_buff, (char *) "online", &position); + else + store_to_string(&send_buff, (char *) "offline", &position); + if (my_net_write(net, send_buff.buffer, (uint) position)) + goto err; + i++; + } + pthread_mutex_unlock(&LOCK_instance_map); + } + if (send_eof(net)) + goto err; + if (net_flush(net)) + goto err; + + return 0; +err: + return 1; +} + + +/* + The method sends a table with a status of requested instance to the client. + + SYNOPSYS + show_instance_status() + net The network connection to the client. + instance_name The name of the instance. + + RETURN + 0 - ok + 1 - error occured +*/ + +int Instance_map::show_instance_status(struct st_net *net, + const char *instance_name) +{ + enum { MAX_VERSION_LENGTH= 40 }; + Buffer send_buff; /* buffer for packets */ + LIST name, status, version; + LIST *field_list; + NAME_WITH_LENGTH name_field, status_field, version_field; + uint position=0; + + /* create list of the fileds to be passed to send_fields */ + name_field.name= (char *) "instance_name"; + name_field.length= 20; + name.data= &name_field; + status_field.name= (char *) "status"; + status_field.length= 20; + status.data= &status_field; + version_field.name= (char *) "version"; + version_field.length= MAX_VERSION_LENGTH; + version.data= &version_field; + field_list= list_add(NULL, &version); + field_list= list_add(field_list, &status); + field_list= list_add(field_list, &name); + + send_fields(net, field_list); + + { + Instance *instance; + + store_to_string(&send_buff, (char *) instance_name, &position); + if ((instance= find(instance_name, strlen(instance_name))) == NULL) + goto err; + if (instance->is_running()) + { + store_to_string(&send_buff, (char *) "online", &position); + store_to_string(&send_buff, mysql_get_server_info(&(instance->mysql)), &position); + } + else + { + store_to_string(&send_buff, (char *) "offline", &position); + store_to_string(&send_buff, (char *) "unknown", &position); + } + + + my_net_write(net, send_buff.buffer, (uint) position); + } + + send_eof(net); + net_flush(net); + +err: + return 0; +} + + +int Instance_map::add_instance(Instance *instance) +{ + return my_hash_insert(&hash, (byte *) instance); +} + + +Instance * +Instance_map::find(const char *name, uint name_len) +{ + Instance *instance; + pthread_mutex_lock(&LOCK_instance_map); + instance= (Instance *) hash_search(&hash, (byte *) name, name_len); + pthread_mutex_unlock(&LOCK_instance_map); + return instance; +} + + +void Instance_map::complete_initialization() +{ + Instance *instance; + uint i= 0; + + while (i < hash.records) + { + instance= (Instance *) hash_element(&hash, i); + instance->options.complete_initialization(mysqld_path, user, password); + i++; + } +} + + +int Instance_map::cleanup() +{ + Instance *instance; + uint i= 0; + + while (i < hash.records) + { + instance= (Instance *) hash_element(&hash, i); + instance->cleanup(); + i++; + } +} + + +Instance * +Instance_map::find(uint instance_number) +{ + Instance *instance; + char name[80]; + + sprintf(name, "mysqld%i", instance_number); + pthread_mutex_lock(&LOCK_instance_map); + instance= (Instance *) hash_search(&hash, (byte *) name, strlen(name)); + pthread_mutex_unlock(&LOCK_instance_map); + return instance; +} + + +/* load options from config files and create appropriate instance structures */ + +int Instance_map::load() +{ + int error; + + error= process_default_option_files("my", process_option, (void *) this); + + complete_initialization(); + + return error; +} |