2004-10-23 11:32:52 +04:00
|
|
|
/* 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 "commands.h"
|
2005-03-22 02:04:14 +03:00
|
|
|
|
2004-10-23 11:32:52 +04:00
|
|
|
#include "instance_map.h"
|
|
|
|
#include "messages.h"
|
2005-03-22 02:04:14 +03:00
|
|
|
#include "mysqld_error.h"
|
|
|
|
#include "mysql_manager_error.h"
|
2004-10-26 23:22:12 +04:00
|
|
|
#include "protocol.h"
|
|
|
|
#include "buffer.h"
|
2005-03-22 02:04:14 +03:00
|
|
|
|
2004-10-26 23:22:12 +04:00
|
|
|
#include <m_string.h>
|
2005-03-22 02:04:14 +03:00
|
|
|
#include <mysql.h>
|
2004-10-23 11:32:52 +04:00
|
|
|
|
|
|
|
|
|
|
|
/* implementation for Show_instances: */
|
|
|
|
|
2004-10-26 23:22:12 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
The method sends a list of instances in the instance map to the client.
|
|
|
|
|
|
|
|
SYNOPSYS
|
|
|
|
Show_instances::do_command()
|
|
|
|
net The network connection to the client.
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
0 - ok
|
|
|
|
1 - error occured
|
|
|
|
*/
|
|
|
|
|
|
|
|
int Show_instances::do_command(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;
|
2004-10-27 10:21:48 +04:00
|
|
|
Instance_map::Iterator iterator(instance_map);
|
2004-10-26 23:22:12 +04:00
|
|
|
|
|
|
|
instance_map->lock();
|
2004-12-12 20:59:15 +03:00
|
|
|
while ((instance= iterator.next()))
|
2004-10-26 23:22:12 +04:00
|
|
|
{
|
|
|
|
position= 0;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
instance_map->unlock();
|
|
|
|
}
|
|
|
|
if (send_eof(net))
|
|
|
|
goto err;
|
|
|
|
if (net_flush(net))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-23 11:32:52 +04:00
|
|
|
int Show_instances::execute(struct st_net *net, ulong connection_id)
|
|
|
|
{
|
2004-10-26 23:22:12 +04:00
|
|
|
if (do_command(net))
|
2004-10-23 11:32:52 +04:00
|
|
|
return ER_OUT_OF_RESOURCES;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* implementation for Flush_instances: */
|
|
|
|
|
|
|
|
int Flush_instances::execute(struct st_net *net, ulong connection_id)
|
|
|
|
{
|
2004-10-26 23:22:12 +04:00
|
|
|
if (instance_map->flush_instances())
|
2004-10-23 11:32:52 +04:00
|
|
|
return ER_OUT_OF_RESOURCES;
|
|
|
|
|
|
|
|
net_send_ok(net, connection_id);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* implementation for Show_instance_status: */
|
|
|
|
|
2004-10-27 10:21:48 +04:00
|
|
|
Show_instance_status::Show_instance_status(Instance_map *instance_map_arg,
|
2004-10-23 11:32:52 +04:00
|
|
|
const char *name, uint len)
|
2004-10-27 10:21:48 +04:00
|
|
|
:Command(instance_map_arg)
|
2004-10-23 11:32:52 +04:00
|
|
|
{
|
|
|
|
Instance *instance;
|
|
|
|
|
|
|
|
/* we make a search here, since we don't want t store the name */
|
2004-12-12 20:59:15 +03:00
|
|
|
if ((instance= instance_map->find(name, len)))
|
2004-10-23 11:32:52 +04:00
|
|
|
{
|
|
|
|
instance_name= instance->options.instance_name;
|
|
|
|
}
|
2004-10-25 14:23:31 +04:00
|
|
|
else
|
|
|
|
instance_name= NULL;
|
2004-10-23 11:32:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-26 23:22:12 +04:00
|
|
|
/*
|
|
|
|
The method sends a table with a status of requested instance to the client.
|
|
|
|
|
|
|
|
SYNOPSYS
|
|
|
|
Show_instance_status::do_command()
|
|
|
|
net The network connection to the client.
|
|
|
|
instance_name The name of the instance.
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
0 - ok
|
|
|
|
1 - error occured
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
int Show_instance_status::do_command(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);
|
2005-02-27 18:41:34 +03:00
|
|
|
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
|
2004-10-26 23:22:12 +04:00
|
|
|
goto err;
|
|
|
|
if (instance->is_running())
|
|
|
|
{
|
|
|
|
store_to_string(&send_buff, (char *) "online", &position);
|
2005-01-25 13:54:56 +03:00
|
|
|
store_to_string(&send_buff, "unknown", &position);
|
2004-10-26 23:22:12 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
store_to_string(&send_buff, (char *) "offline", &position);
|
|
|
|
store_to_string(&send_buff, (char *) "unknown", &position);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-13 15:13:33 +03:00
|
|
|
if (send_buff.is_error() ||
|
|
|
|
my_net_write(net, send_buff.buffer, (uint) position))
|
2004-11-02 10:11:03 +03:00
|
|
|
goto err;
|
2004-10-26 23:22:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
send_eof(net);
|
|
|
|
net_flush(net);
|
|
|
|
|
|
|
|
return 0;
|
2004-11-02 10:11:03 +03:00
|
|
|
|
|
|
|
err:
|
|
|
|
return 1;
|
2004-10-26 23:22:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-23 11:32:52 +04:00
|
|
|
int Show_instance_status::execute(struct st_net *net, ulong connection_id)
|
|
|
|
{
|
2005-02-27 18:41:34 +03:00
|
|
|
if ((instance_name))
|
2004-10-23 11:32:52 +04:00
|
|
|
{
|
2004-10-26 23:22:12 +04:00
|
|
|
if (do_command(net, instance_name))
|
2004-10-23 11:32:52 +04:00
|
|
|
return ER_OUT_OF_RESOURCES;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return ER_BAD_INSTANCE_NAME;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Implementation for Show_instance_options */
|
|
|
|
|
2004-10-27 10:21:48 +04:00
|
|
|
Show_instance_options::Show_instance_options(Instance_map *instance_map_arg,
|
2004-10-23 11:32:52 +04:00
|
|
|
const char *name, uint len):
|
2004-10-27 10:21:48 +04:00
|
|
|
Command(instance_map_arg)
|
2004-10-23 11:32:52 +04:00
|
|
|
{
|
|
|
|
Instance *instance;
|
|
|
|
|
|
|
|
/* we make a search here, since we don't want t store the name */
|
2004-12-12 20:59:15 +03:00
|
|
|
if ((instance= instance_map->find(name, len)))
|
2004-10-23 11:32:52 +04:00
|
|
|
{
|
|
|
|
instance_name= instance->options.instance_name;
|
|
|
|
}
|
2004-10-25 14:23:31 +04:00
|
|
|
else
|
|
|
|
instance_name= NULL;
|
2004-10-23 11:32:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-26 23:22:12 +04:00
|
|
|
int Show_instance_options::do_command(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;
|
|
|
|
|
2005-02-27 18:41:34 +03:00
|
|
|
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
|
2004-10-26 23:22:12 +04:00
|
|
|
goto err;
|
|
|
|
store_to_string(&send_buff, (char *) "instance_name", &position);
|
|
|
|
store_to_string(&send_buff, (char *) instance_name, &position);
|
2004-11-02 10:11:03 +03:00
|
|
|
if (my_net_write(net, send_buff.buffer, (uint) position))
|
|
|
|
goto err;
|
2005-02-27 18:41:34 +03:00
|
|
|
if ((instance->options.mysqld_path))
|
2004-10-26 23:22:12 +04:00
|
|
|
{
|
|
|
|
position= 0;
|
2004-12-29 00:13:32 +03:00
|
|
|
store_to_string(&send_buff, (char *) "mysqld-path", &position);
|
2004-10-26 23:22:12 +04:00
|
|
|
store_to_string(&send_buff,
|
|
|
|
(char *) instance->options.mysqld_path,
|
|
|
|
&position);
|
2005-02-13 15:13:33 +03:00
|
|
|
if (send_buff.is_error() ||
|
|
|
|
my_net_write(net, send_buff.buffer, (uint) position))
|
2004-11-02 10:11:03 +03:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2005-02-27 18:41:34 +03:00
|
|
|
if ((instance->options.nonguarded))
|
2004-11-02 10:11:03 +03:00
|
|
|
{
|
|
|
|
position= 0;
|
more fixes for IM to substitude mysqld_safe in startup scripts
BitKeeper/deleted/.del-thread_repository.cc~bba09f64f8cb4037:
Delete: server-tools/instance-manager/thread_repository.cc
BitKeeper/deleted/.del-thread_repository.h~e6a3b9cab7a6612a:
Delete: server-tools/instance-manager/thread_repository.h
server-tools/instance-manager/commands.cc:
All instances are guarded by default now, so we need to perform check on whether the instance is nonguarded,
rather then guarded when adding it to the list of guarded instnces.
server-tools/instance-manager/guardian.cc:
Guardian rewritten to start instances by default, and shut them down, when exiting. Behaviour of the guardian
in case of the instance crash has changed. Now it tries to restart an instance constantly in the first 2
seconds after the crash was noticed, and then it tries restart an instance once in the MONITORING_INTERVAL.
If it failed to restart instance for "restart_retry" (compiled-in value) times, guardian stops trying to
restart it.
server-tools/instance-manager/guardian.h:
Several new functions and variables declared.
server-tools/instance-manager/instance.cc:
now start doesn't call stop(), but rather tries to remove the pidfile itself
server-tools/instance-manager/instance.h:
cleanup
server-tools/instance-manager/instance_map.cc:
no more "admin" options
server-tools/instance-manager/instance_map.h:
User and password purged from instance_map options, as IM shouldn't know them
server-tools/instance-manager/instance_options.cc:
new option added -- shutdown_delay, guarded option now called nonguaded and has the opposite meaning
server-tools/instance-manager/instance_options.h:
appropriate changes, reflecting options addition/removal
server-tools/instance-manager/manager.cc:
shutdown process is complicated a bit -- at first signal thread should stop guardian, and only then the IM
itself
server-tools/instance-manager/messages.cc:
update error message
server-tools/instance-manager/options.cc:
admin user/password purged from mysqlmanager options
2005-01-31 23:54:08 +03:00
|
|
|
store_to_string(&send_buff, (char *) "nonguarded", &position);
|
2004-11-02 10:11:03 +03:00
|
|
|
store_to_string(&send_buff, "", &position);
|
2005-02-13 15:13:33 +03:00
|
|
|
if (send_buff.is_error() ||
|
|
|
|
my_net_write(net, send_buff.buffer, (uint) position))
|
2004-11-02 10:11:03 +03:00
|
|
|
goto err;
|
2004-10-26 23:22:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* loop through the options stored in DYNAMIC_ARRAY */
|
2004-12-12 20:59:15 +03:00
|
|
|
for (uint i= 0; i < instance->options.options_array.elements; i++)
|
2004-10-26 23:22:12 +04:00
|
|
|
{
|
|
|
|
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= '=';
|
2005-02-13 15:13:33 +03:00
|
|
|
if (send_buff.is_error() ||
|
|
|
|
my_net_write(net, send_buff.buffer, (uint) position))
|
2004-11-02 10:11:03 +03:00
|
|
|
goto err;
|
2004-10-26 23:22:12 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
send_eof(net);
|
|
|
|
net_flush(net);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-23 11:32:52 +04:00
|
|
|
int Show_instance_options::execute(struct st_net *net, ulong connection_id)
|
|
|
|
{
|
2005-02-27 18:41:34 +03:00
|
|
|
if ((instance_name))
|
2004-10-23 11:32:52 +04:00
|
|
|
{
|
2004-10-26 23:22:12 +04:00
|
|
|
if (do_command(net, instance_name))
|
2004-10-23 11:32:52 +04:00
|
|
|
return ER_OUT_OF_RESOURCES;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return ER_BAD_INSTANCE_NAME;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Implementation for Start_instance */
|
|
|
|
|
2004-10-27 10:21:48 +04:00
|
|
|
Start_instance::Start_instance(Instance_map *instance_map_arg,
|
2004-10-23 11:32:52 +04:00
|
|
|
const char *name, uint len)
|
2004-10-27 10:21:48 +04:00
|
|
|
:Command(instance_map_arg)
|
2004-10-23 11:32:52 +04:00
|
|
|
{
|
|
|
|
/* we make a search here, since we don't want t store the name */
|
2004-12-12 20:59:15 +03:00
|
|
|
if ((instance= instance_map->find(name, len)))
|
2004-10-23 11:32:52 +04:00
|
|
|
instance_name= instance->options.instance_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Start_instance::execute(struct st_net *net, ulong connection_id)
|
|
|
|
{
|
|
|
|
uint err_code;
|
|
|
|
if (instance == 0)
|
|
|
|
{
|
|
|
|
return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-02-27 18:41:34 +03:00
|
|
|
if ((err_code= instance->start()))
|
2004-10-23 11:32:52 +04:00
|
|
|
return err_code;
|
|
|
|
|
2005-02-27 18:41:34 +03:00
|
|
|
if (!(instance->options.nonguarded))
|
2004-10-26 23:22:12 +04:00
|
|
|
instance_map->guardian->guard(instance);
|
2004-10-23 11:32:52 +04:00
|
|
|
|
|
|
|
net_send_ok(net, connection_id);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Implementation for Stop_instance: */
|
|
|
|
|
2004-10-27 10:21:48 +04:00
|
|
|
Stop_instance::Stop_instance(Instance_map *instance_map_arg,
|
2004-10-23 11:32:52 +04:00
|
|
|
const char *name, uint len)
|
2004-10-27 10:21:48 +04:00
|
|
|
:Command(instance_map_arg)
|
2004-10-23 11:32:52 +04:00
|
|
|
{
|
|
|
|
/* we make a search here, since we don't want t store the name */
|
2004-12-12 20:59:15 +03:00
|
|
|
if ((instance= instance_map->find(name, len)))
|
2004-10-23 11:32:52 +04:00
|
|
|
instance_name= instance->options.instance_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Stop_instance::execute(struct st_net *net, ulong connection_id)
|
|
|
|
{
|
|
|
|
uint err_code;
|
|
|
|
|
|
|
|
if (instance == 0)
|
|
|
|
{
|
|
|
|
return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-02-27 18:41:34 +03:00
|
|
|
if (!(instance->options.nonguarded))
|
2004-10-26 23:22:12 +04:00
|
|
|
instance_map->guardian->
|
|
|
|
stop_guard(instance);
|
2004-12-12 20:59:15 +03:00
|
|
|
if ((err_code= instance->stop()))
|
2004-10-23 11:32:52 +04:00
|
|
|
return err_code;
|
|
|
|
net_send_ok(net, connection_id);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Syntax_error::execute(struct st_net *net, ulong connection_id)
|
|
|
|
{
|
|
|
|
return ER_SYNTAX_ERROR;
|
|
|
|
}
|