mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Port cleanups, trivial refactoring and code rearrangements from
Alik's patch for BUG#22306: STOP INSTANCE can not be applied for instances in Crashed, Failed and Abandoned" to ease review process. Evaluate global variable linuxthreads before starting threads to avoid a race.
This commit is contained in:
@ -27,7 +27,7 @@ const uint Buffer::MAX_BUFFER_SIZE= 16777216;
|
||||
/*
|
||||
Puts the given string to the buffer.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
append()
|
||||
position start position in the buffer
|
||||
string string to be put in the buffer
|
||||
@ -59,7 +59,7 @@ int Buffer::append(uint position, const char *string, uint len_arg)
|
||||
Checks whether the current buffer size is ok to put a string of the length
|
||||
"len_arg" starting from "position" and reallocs it if no.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
reserve()
|
||||
position the number starting byte on the buffer to store a buffer
|
||||
len_arg the length of the string.
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
/*
|
||||
This operation incapsulates behaviour of the command.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
net The network connection to the client.
|
||||
connection_id Client connection ID
|
||||
|
||||
|
@ -49,7 +49,7 @@ static const int modify_defaults_to_im_error[]= { 0, ER_OUT_OF_RESOURCES,
|
||||
/*
|
||||
Add a string to a buffer.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
put_to_buff()
|
||||
buff buffer to add the string
|
||||
str string to add
|
||||
@ -590,7 +590,7 @@ Create_instance::Create_instance(const LEX_STRING *instance_name_arg)
|
||||
/*
|
||||
This operation initializes Create_instance object.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
text [IN/OUT] a pointer to the text containing instance options.
|
||||
|
||||
RETURN
|
||||
@ -607,7 +607,7 @@ bool Create_instance::init(const char **text)
|
||||
/*
|
||||
This operation parses CREATE INSTANCE options.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
text [IN/OUT] a pointer to the text containing instance options.
|
||||
|
||||
RETURN
|
||||
@ -1255,7 +1255,7 @@ bool Abstract_option_cmd::init(const char **text)
|
||||
Correct the option file. The "skip" option is used to remove the found
|
||||
option.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
Abstract_option_cmd::correct_file()
|
||||
skip Skip the option, being searched while writing the result file.
|
||||
That is, to delete it.
|
||||
@ -1395,7 +1395,7 @@ int Abstract_option_cmd::execute_impl(st_net *net, ulong connection_id)
|
||||
/*
|
||||
This operation parses SET options.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
text [IN/OUT] a pointer to the text containing options.
|
||||
|
||||
RETURN
|
||||
@ -1569,7 +1569,7 @@ int Set_option::process_option(Instance *instance, Named_value *option)
|
||||
/*
|
||||
This operation parses UNSET options.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
text [IN/OUT] a pointer to the text containing options.
|
||||
|
||||
RETURN
|
||||
|
@ -32,15 +32,11 @@
|
||||
|
||||
/*
|
||||
Print all instances of this instance manager.
|
||||
Grammar: SHOW ISTANCES
|
||||
Grammar: SHOW INSTANCES
|
||||
*/
|
||||
|
||||
class Show_instances : public Command
|
||||
class Show_instances: public Command
|
||||
{
|
||||
public:
|
||||
Show_instances()
|
||||
{ }
|
||||
|
||||
public:
|
||||
int execute(st_net *net, ulong connection_id);
|
||||
|
||||
@ -57,10 +53,6 @@ private:
|
||||
|
||||
class Flush_instances : public Command
|
||||
{
|
||||
public:
|
||||
Flush_instances()
|
||||
{ }
|
||||
|
||||
public:
|
||||
int execute(st_net *net, ulong connection_id);
|
||||
};
|
||||
@ -103,7 +95,7 @@ private:
|
||||
|
||||
/*
|
||||
Print status of an instance.
|
||||
Grammar: SHOW ISTANCE STATUS <instance_name>
|
||||
Grammar: SHOW INSTANCE STATUS <instance_name>
|
||||
*/
|
||||
|
||||
class Show_instance_status : public Abstract_instance_cmd
|
||||
@ -319,10 +311,6 @@ private:
|
||||
|
||||
class Set_option : public Abstract_option_cmd
|
||||
{
|
||||
public:
|
||||
Set_option()
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual bool parse_args(const char **text);
|
||||
virtual int process_option(Instance *instance, Named_value *option);
|
||||
@ -336,10 +324,6 @@ protected:
|
||||
|
||||
class Unset_option: public Abstract_option_cmd
|
||||
{
|
||||
public:
|
||||
Unset_option()
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual bool parse_args(const char **text);
|
||||
virtual int process_option(Instance *instance, Named_value *option);
|
||||
@ -357,10 +341,6 @@ protected:
|
||||
|
||||
class Syntax_error : public Command
|
||||
{
|
||||
public:
|
||||
Syntax_error()
|
||||
{ }
|
||||
|
||||
public:
|
||||
int execute(st_net *net, ulong connection_id);
|
||||
};
|
||||
|
@ -91,7 +91,7 @@ Guardian::~Guardian()
|
||||
void Guardian::request_shutdown()
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_guardian);
|
||||
/* stop instances or just clean up Guardian repository */
|
||||
/* STOP Instances or just clean up Guardian repository */
|
||||
stop_instances();
|
||||
shutdown_requested= TRUE;
|
||||
pthread_mutex_unlock(&LOCK_guardian);
|
||||
@ -110,23 +110,14 @@ void Guardian::process_instance(Instance *instance,
|
||||
|
||||
if (current_node->state == STOPPING)
|
||||
{
|
||||
/* this branch is executed during shutdown */
|
||||
if (instance->options.shutdown_delay)
|
||||
{
|
||||
/*
|
||||
NOTE: it is important to check shutdown_delay here, but use
|
||||
shutdown_delay_val. The idea is that if the option is unset,
|
||||
shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
|
||||
*/
|
||||
waitchild= instance->options.shutdown_delay_val;
|
||||
}
|
||||
waitchild= instance->options.get_shutdown_delay();
|
||||
|
||||
/* this returns TRUE if and only if an instance was stopped for sure */
|
||||
if (instance->is_crashed())
|
||||
*guarded_instances= list_delete(*guarded_instances, node);
|
||||
else if ( (uint) (current_time - current_node->last_checked) > waitchild)
|
||||
{
|
||||
instance->kill_instance(SIGKILL);
|
||||
instance->kill_mysqld(SIGKILL);
|
||||
/*
|
||||
Later we do node= node->next. This is ok, as we are only removing
|
||||
the node from the list. The pointer to the next one is still valid.
|
||||
@ -137,20 +128,20 @@ void Guardian::process_instance(Instance *instance,
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance->is_running())
|
||||
if (instance->is_mysqld_running())
|
||||
{
|
||||
/* The instance can be contacted on it's port */
|
||||
|
||||
/* If STARTING also check that pidfile has been created */
|
||||
if (current_node->state == STARTING &&
|
||||
current_node->instance->options.get_pid() == 0)
|
||||
current_node->instance->options.load_pid() == 0)
|
||||
{
|
||||
/* Pid file not created yet, don't go to STARTED state yet */
|
||||
}
|
||||
else if (current_node->state != STARTED)
|
||||
{
|
||||
/* clear status fields */
|
||||
log_info("guardian: instance '%s' is running, set state to STARTED.",
|
||||
log_info("Guardian: '%s' is running, set state to STARTED.",
|
||||
(const char *) instance->options.instance_name.str);
|
||||
current_node->restart_counter= 0;
|
||||
current_node->crash_moment= 0;
|
||||
@ -161,7 +152,7 @@ void Guardian::process_instance(Instance *instance,
|
||||
{
|
||||
switch (current_node->state) {
|
||||
case NOT_STARTED:
|
||||
log_info("guardian: starting instance '%s'...",
|
||||
log_info("Guardian: starting '%s'...",
|
||||
(const char *) instance->options.instance_name.str);
|
||||
|
||||
/* NOTE, set state to STARTING _before_ start() is called */
|
||||
@ -186,7 +177,7 @@ void Guardian::process_instance(Instance *instance,
|
||||
if (instance->is_crashed())
|
||||
{
|
||||
instance->start();
|
||||
log_info("guardian: starting instance '%s'...",
|
||||
log_info("Guardian: starting '%s'...",
|
||||
(const char *) instance->options.instance_name.str);
|
||||
}
|
||||
}
|
||||
@ -204,14 +195,15 @@ void Guardian::process_instance(Instance *instance,
|
||||
instance->start();
|
||||
current_node->last_checked= current_time;
|
||||
current_node->restart_counter++;
|
||||
log_info("guardian: restarting instance '%s'...",
|
||||
log_info("Guardian: restarting '%s'...",
|
||||
(const char *) instance->options.instance_name.str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info("guardian: cannot start instance %s. Abandoning attempts "
|
||||
"to (re)start it", instance->options.instance_name.str);
|
||||
log_info("Guardian: can not start '%s'. "
|
||||
"Abandoning attempts to (re)start it",
|
||||
(const char *) instance->options.instance_name.str);
|
||||
current_node->state= CRASHED_AND_ABANDONED;
|
||||
}
|
||||
}
|
||||
@ -226,13 +218,12 @@ void Guardian::process_instance(Instance *instance,
|
||||
|
||||
|
||||
/*
|
||||
Run guardian thread
|
||||
Main function of Guardian thread.
|
||||
|
||||
SYNOPSIS
|
||||
run()
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Check for all guarded instances and restart them if needed. If everything
|
||||
is fine go and sleep for some time.
|
||||
*/
|
||||
@ -436,7 +427,7 @@ int Guardian::stop_instances()
|
||||
If instance is running or was running (and now probably hanging),
|
||||
request stop.
|
||||
*/
|
||||
if (current_node->instance->is_running() ||
|
||||
if (current_node->instance->is_mysqld_running() ||
|
||||
(current_node->state == STARTED))
|
||||
{
|
||||
current_node->state= STOPPING;
|
||||
@ -446,7 +437,7 @@ int Guardian::stop_instances()
|
||||
/* otherwise remove it from the list */
|
||||
guarded_instances= list_delete(guarded_instances, node);
|
||||
/* But try to kill it anyway. Just in case */
|
||||
current_node->instance->kill_instance(SIGTERM);
|
||||
current_node->instance->kill_mysqld(SIGTERM);
|
||||
node= node->next;
|
||||
}
|
||||
return 0;
|
||||
@ -499,5 +490,5 @@ bool Guardian::is_active(Instance *instance)
|
||||
if (guarded)
|
||||
return true;
|
||||
|
||||
return instance->is_running();
|
||||
return instance->is_mysqld_running();
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "instance.h"
|
||||
|
||||
#include <my_global.h>
|
||||
#include <mysql.h>
|
||||
|
||||
#include <signal.h>
|
||||
@ -29,21 +28,15 @@
|
||||
#endif
|
||||
|
||||
#include "guardian.h"
|
||||
#include "instance_map.h"
|
||||
#include "manager.h"
|
||||
#include "log.h"
|
||||
#include "mysql_manager_error.h"
|
||||
#include "portability.h"
|
||||
#include "priv.h"
|
||||
#include "thread_registry.h"
|
||||
#include "instance_map.h"
|
||||
|
||||
|
||||
const LEX_STRING
|
||||
Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") };
|
||||
|
||||
static const char * const INSTANCE_NAME_PREFIX= Instance::DFLT_INSTANCE_NAME.str;
|
||||
static const int INSTANCE_NAME_PREFIX_LEN= Instance::DFLT_INSTANCE_NAME.length;
|
||||
|
||||
|
||||
/* {{{ Platform-specific functions. */
|
||||
|
||||
#ifndef __WIN__
|
||||
typedef pid_t My_process_info;
|
||||
@ -73,15 +66,16 @@ private:
|
||||
|
||||
void Instance_monitor::run()
|
||||
{
|
||||
start_and_monitor_instance(&instance->options, instance->get_map(),
|
||||
&instance->thread_registry);
|
||||
start_and_monitor_instance(&instance->options,
|
||||
Manager::get_instance_map(),
|
||||
Manager::get_thread_registry());
|
||||
delete this;
|
||||
}
|
||||
|
||||
/*
|
||||
Wait for an instance
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
wait_process()
|
||||
pi Pointer to the process information structure
|
||||
(platform-dependent).
|
||||
@ -139,11 +133,10 @@ static int wait_process(My_process_info *pi)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Launch an instance
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
start_process()
|
||||
instance_options Pointer to the options of the instance to be
|
||||
launched.
|
||||
@ -151,13 +144,13 @@ static int wait_process(My_process_info *pi)
|
||||
(platform-dependent).
|
||||
|
||||
RETURN
|
||||
0 - Success
|
||||
1 - Cannot create an instance
|
||||
FALSE - Success
|
||||
TRUE - Cannot create an instance
|
||||
*/
|
||||
|
||||
#ifndef __WIN__
|
||||
static int start_process(Instance_options *instance_options,
|
||||
My_process_info *pi)
|
||||
static bool start_process(Instance_options *instance_options,
|
||||
My_process_info *pi)
|
||||
{
|
||||
#ifndef __QNX__
|
||||
*pi= fork();
|
||||
@ -177,15 +170,16 @@ static int start_process(Instance_options *instance_options,
|
||||
/* exec never returns */
|
||||
exit(1);
|
||||
case -1:
|
||||
log_info("cannot create a new process to start instance '%s'.",
|
||||
log_info("Instance '%s': can not start mysqld: fork() failed.",
|
||||
(const char *) instance_options->instance_name.str);
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
static int start_process(Instance_options *instance_options,
|
||||
My_process_info *pi)
|
||||
static bool start_process(Instance_options *instance_options,
|
||||
My_process_info *pi)
|
||||
{
|
||||
STARTUPINFO si;
|
||||
|
||||
@ -200,7 +194,7 @@ static int start_process(Instance_options *instance_options,
|
||||
|
||||
char *cmdline= new char[cmdlen];
|
||||
if (cmdline == NULL)
|
||||
return 1;
|
||||
return TRUE;
|
||||
|
||||
cmdline[0]= 0;
|
||||
for (int i= 0; instance_options->argv[i] != 0; i++)
|
||||
@ -224,352 +218,10 @@ static int start_process(Instance_options *instance_options,
|
||||
pi); /* Pointer to PROCESS_INFORMATION structure */
|
||||
delete cmdline;
|
||||
|
||||
return (!result);
|
||||
return !result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
Fork child, exec an instance and monitor it.
|
||||
|
||||
SYNOPSYS
|
||||
start_and_monitor_instance()
|
||||
old_instance_options Pointer to the options of the instance to be
|
||||
launched. This info is likely to become obsolete
|
||||
when function returns from wait_process()
|
||||
instance_map Pointer to the instance_map. We use it to protect
|
||||
the instance from deletion, while we are working
|
||||
with it.
|
||||
|
||||
DESCRIPTION
|
||||
Fork a child, then exec and monitor it. When the child is dead,
|
||||
find appropriate instance (for this purpose we save its name),
|
||||
set appropriate flags and wake all threads waiting for instance
|
||||
to stop.
|
||||
|
||||
RETURN
|
||||
Function returns no value
|
||||
*/
|
||||
|
||||
void
|
||||
Instance_monitor::
|
||||
start_and_monitor_instance(Instance_options *old_instance_options,
|
||||
Instance_map *instance_map,
|
||||
Thread_registry *thread_registry)
|
||||
{
|
||||
Instance_name instance_name(&old_instance_options->instance_name);
|
||||
Instance *current_instance;
|
||||
My_process_info process_info;
|
||||
Thread_info thread_info;
|
||||
|
||||
log_info("Monitoring thread (instance: '%s'): started.",
|
||||
(const char *) instance_name.get_c_str());
|
||||
|
||||
if (!old_instance_options->nonguarded)
|
||||
{
|
||||
/*
|
||||
Register thread in Thread_registry to wait for it to stop on shutdown
|
||||
only if instance is guarded. If instance is guarded, the thread will not
|
||||
finish, because nonguarded instances are not stopped on shutdown.
|
||||
*/
|
||||
thread_registry->register_thread(&thread_info, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
Lock instance map to guarantee that no instances are deleted during
|
||||
strmake() and execv() calls.
|
||||
*/
|
||||
instance_map->lock();
|
||||
|
||||
/*
|
||||
Save the instance name in the case if Instance object we
|
||||
are using is destroyed. (E.g. by "FLUSH INSTANCES")
|
||||
*/
|
||||
|
||||
log_info("starting instance %s...",
|
||||
(const char *) instance_name.get_c_str());
|
||||
|
||||
if (start_process(old_instance_options, &process_info))
|
||||
{
|
||||
instance_map->unlock();
|
||||
return; /* error is logged */
|
||||
}
|
||||
|
||||
/* allow users to delete instances */
|
||||
instance_map->unlock();
|
||||
|
||||
/* don't check for return value */
|
||||
wait_process(&process_info);
|
||||
|
||||
instance_map->lock();
|
||||
|
||||
current_instance= instance_map->find(instance_name.get_str());
|
||||
|
||||
if (current_instance)
|
||||
current_instance->set_crash_flag_n_wake_all();
|
||||
|
||||
instance_map->unlock();
|
||||
|
||||
if (!old_instance_options->nonguarded)
|
||||
thread_registry->unregister_thread(&thread_info);
|
||||
|
||||
log_info("Monitoring thread (instance: '%s'): finished.",
|
||||
(const char *) instance_name.get_c_str());
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_name_valid(const LEX_STRING *name)
|
||||
{
|
||||
const char *name_suffix= name->str + INSTANCE_NAME_PREFIX_LEN;
|
||||
|
||||
if (strncmp(name->str, INSTANCE_NAME_PREFIX, INSTANCE_NAME_PREFIX_LEN) != 0)
|
||||
return FALSE;
|
||||
|
||||
return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix);
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_mysqld_compatible_name(const LEX_STRING *name)
|
||||
{
|
||||
return strcmp(name->str, INSTANCE_NAME_PREFIX) == 0;
|
||||
}
|
||||
|
||||
|
||||
Instance_map *Instance::get_map()
|
||||
{
|
||||
return instance_map;
|
||||
}
|
||||
|
||||
|
||||
void Instance::remove_pid()
|
||||
{
|
||||
int pid;
|
||||
if ((pid= options.get_pid()) != 0) /* check the pidfile */
|
||||
if (options.unlink_pidfile()) /* remove stalled pidfile */
|
||||
log_error("cannot remove pidfile for instance '%s', this might be "
|
||||
"since IM lacks permmissions or hasn't found the pidifle",
|
||||
(const char *) options.instance_name.str);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The method starts an instance.
|
||||
|
||||
SYNOPSYS
|
||||
start()
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
ER_CANNOT_START_INSTANCE Cannot start instance
|
||||
ER_INSTANCE_ALREADY_STARTED The instance on the specified port/socket
|
||||
is already started
|
||||
*/
|
||||
|
||||
int Instance::start()
|
||||
{
|
||||
/* clear crash flag */
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
crashed= FALSE;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
|
||||
if (configured && !is_running())
|
||||
{
|
||||
Instance_monitor *instance_monitor;
|
||||
remove_pid();
|
||||
|
||||
instance_monitor= new Instance_monitor(this);
|
||||
|
||||
if (instance_monitor == NULL || instance_monitor->start_detached())
|
||||
{
|
||||
delete instance_monitor;
|
||||
log_error("Instance::start(): failed to create the monitoring thread"
|
||||
" to start an instance");
|
||||
return ER_CANNOT_START_INSTANCE;
|
||||
}
|
||||
/* The monitoring thread will delete itself when it's finished. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The instance is started already or misconfigured. */
|
||||
return configured ? ER_INSTANCE_ALREADY_STARTED : ER_INSTANCE_MISCONFIGURED;
|
||||
}
|
||||
|
||||
/*
|
||||
The method sets the crash flag and wakes all waiters on
|
||||
COND_instance_stopped and COND_guardian
|
||||
|
||||
SYNOPSYS
|
||||
set_crash_flag_n_wake_all()
|
||||
|
||||
DESCRIPTION
|
||||
The method is called when an instance is crashed or terminated.
|
||||
In the former case it might indicate that guardian probably should
|
||||
restart it.
|
||||
|
||||
RETURN
|
||||
Function returns no value
|
||||
*/
|
||||
|
||||
void Instance::set_crash_flag_n_wake_all()
|
||||
{
|
||||
/* set instance state to crashed */
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
crashed= TRUE;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
/*
|
||||
Wake connection threads waiting for an instance to stop. This
|
||||
is needed if a user issued command to stop an instance via
|
||||
mysql connection. This is not the case if Guardian stop the thread.
|
||||
*/
|
||||
pthread_cond_signal(&COND_instance_stopped);
|
||||
/* wake guardian */
|
||||
pthread_cond_signal(&instance_map->guardian->COND_guardian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Instance::Instance(Thread_registry &thread_registry_arg):
|
||||
thread_registry(thread_registry_arg), crashed(FALSE), configured(FALSE)
|
||||
{
|
||||
pthread_mutex_init(&LOCK_instance, 0);
|
||||
pthread_cond_init(&COND_instance_stopped, 0);
|
||||
}
|
||||
|
||||
|
||||
Instance::~Instance()
|
||||
{
|
||||
pthread_cond_destroy(&COND_instance_stopped);
|
||||
pthread_mutex_destroy(&LOCK_instance);
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_crashed()
|
||||
{
|
||||
bool val;
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
val= crashed;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_running()
|
||||
{
|
||||
MYSQL mysql;
|
||||
uint port= 0;
|
||||
const char *socket= NULL;
|
||||
static const char *password= "check_connection";
|
||||
static const char *username= "MySQL_Instance_Manager";
|
||||
static const char *access_denied_message= "Access denied for user";
|
||||
bool return_val;
|
||||
|
||||
if (options.mysqld_port)
|
||||
{
|
||||
/*
|
||||
NOTE: it is important to check mysqld_port here, but use
|
||||
mysqld_port_val. The idea is that if the option is unset, mysqld_port
|
||||
will be NULL, but mysqld_port_val will not be reset.
|
||||
*/
|
||||
port= options.mysqld_port_val;
|
||||
}
|
||||
|
||||
if (options.mysqld_socket)
|
||||
socket= options.mysqld_socket;
|
||||
|
||||
/* no port was specified => instance falled back to default value */
|
||||
if (!options.mysqld_port && !options.mysqld_socket)
|
||||
port= SERVER_DEFAULT_PORT;
|
||||
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
|
||||
mysql_init(&mysql);
|
||||
/* try to connect to a server with a fake username/password pair */
|
||||
if (mysql_real_connect(&mysql, LOCAL_HOST, username,
|
||||
password,
|
||||
NullS, port,
|
||||
socket, 0))
|
||||
{
|
||||
/*
|
||||
We have successfully connected to the server using fake
|
||||
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.");
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
return_val= TRUE; /* server is alive */
|
||||
}
|
||||
else
|
||||
return_val= test(!strncmp(access_denied_message, mysql_error(&mysql),
|
||||
sizeof(access_denied_message) - 1));
|
||||
|
||||
mysql_close(&mysql);
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Stop an instance.
|
||||
|
||||
SYNOPSYS
|
||||
stop()
|
||||
|
||||
RETURN:
|
||||
0 ok
|
||||
ER_INSTANCE_IS_NOT_STARTED Looks like the instance it is not started
|
||||
ER_STOP_INSTANCE mysql_shutdown reported an error
|
||||
*/
|
||||
|
||||
int Instance::stop()
|
||||
{
|
||||
struct timespec timeout;
|
||||
uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY;
|
||||
|
||||
if (is_running())
|
||||
{
|
||||
if (options.shutdown_delay)
|
||||
{
|
||||
/*
|
||||
NOTE: it is important to check shutdown_delay here, but use
|
||||
shutdown_delay_val. The idea is that if the option is unset,
|
||||
shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
|
||||
*/
|
||||
waitchild= options.shutdown_delay_val;
|
||||
}
|
||||
|
||||
kill_instance(SIGTERM);
|
||||
/* sleep on condition to wait for SIGCHLD */
|
||||
|
||||
timeout.tv_sec= time(NULL) + waitchild;
|
||||
timeout.tv_nsec= 0;
|
||||
if (pthread_mutex_lock(&LOCK_instance))
|
||||
return ER_STOP_INSTANCE;
|
||||
|
||||
while (options.get_pid() != 0) /* while server isn't stopped */
|
||||
{
|
||||
int status;
|
||||
|
||||
status= pthread_cond_timedwait(&COND_instance_stopped,
|
||||
&LOCK_instance,
|
||||
&timeout);
|
||||
if (status == ETIMEDOUT || status == ETIME)
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
kill_instance(SIGKILL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ER_INSTANCE_IS_NOT_STARTED;
|
||||
}
|
||||
|
||||
#ifdef __WIN__
|
||||
|
||||
BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
|
||||
@ -633,42 +285,167 @@ int kill(pid_t pid, int signum)
|
||||
}
|
||||
#endif
|
||||
|
||||
void Instance::kill_instance(int signum)
|
||||
{
|
||||
pid_t pid;
|
||||
/* if there are no pid, everything seems to be fine */
|
||||
if ((pid= options.get_pid()) != 0) /* get pid from pidfile */
|
||||
{
|
||||
if (kill(pid, signum) == 0)
|
||||
{
|
||||
/* Kill suceeded */
|
||||
if (signum == SIGKILL) /* really killed instance with SIGKILL */
|
||||
{
|
||||
log_error("The instance '%s' is being stopped forcibly. Normally"
|
||||
"it should not happen. Probably the instance has been"
|
||||
"hanging. You should also check your IM setup",
|
||||
(const char *) options.instance_name.str);
|
||||
/* After sucessful hard kill the pidfile need to be removed */
|
||||
options.unlink_pidfile();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Static constants. */
|
||||
|
||||
const LEX_STRING
|
||||
Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") };
|
||||
|
||||
/* }}} */
|
||||
|
||||
|
||||
/*
|
||||
Initialize instance parameters.
|
||||
Fork child, exec an instance and monitor it.
|
||||
|
||||
SYNOPSYS
|
||||
Instance::init()
|
||||
SYNOPSIS
|
||||
start_and_monitor_instance()
|
||||
old_instance_options Pointer to the options of the instance to be
|
||||
launched. This info is likely to become obsolete
|
||||
when function returns from wait_process()
|
||||
instance_map Pointer to the instance_map. We use it to protect
|
||||
the instance from deletion, while we are working
|
||||
with it.
|
||||
|
||||
DESCRIPTION
|
||||
Fork a child, then exec and monitor it. When the child is dead,
|
||||
find appropriate instance (for this purpose we save its name),
|
||||
set appropriate flags and wake all threads waiting for instance
|
||||
to stop.
|
||||
|
||||
NOTE
|
||||
A separate thread for starting/monitoring instance is a simple way
|
||||
to avoid all pitfalls of the threads implementation in the OS (e.g.
|
||||
LinuxThreads). For one, with such a thread we don't have to process
|
||||
SIGCHLD, which is a tricky business if we want to do it in a
|
||||
portable way.
|
||||
|
||||
RETURN
|
||||
Function returns no value
|
||||
*/
|
||||
|
||||
void
|
||||
Instance_monitor::
|
||||
start_and_monitor_instance(Instance_options *old_instance_options,
|
||||
Instance_map *instance_map,
|
||||
Thread_registry *thread_registry)
|
||||
{
|
||||
Instance_name instance_name(&old_instance_options->instance_name);
|
||||
Instance *current_instance;
|
||||
My_process_info process_info;
|
||||
Thread_info thread_info;
|
||||
|
||||
log_info("Instance '%s': Monitor: started.",
|
||||
(const char *) instance->get_name()->str);
|
||||
|
||||
if (!old_instance_options->nonguarded)
|
||||
{
|
||||
/*
|
||||
Register thread in Thread_registry to wait for it to stop on shutdown
|
||||
only if instance is guarded. If instance is guarded, the thread will not
|
||||
finish, because nonguarded instances are not stopped on shutdown.
|
||||
*/
|
||||
thread_registry->register_thread(&thread_info, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
Lock instance map to guarantee that no instances are deleted during
|
||||
strmake() and execv() calls.
|
||||
*/
|
||||
instance_map->lock();
|
||||
|
||||
/*
|
||||
Save the instance name in the case if Instance object we
|
||||
are using is destroyed. (E.g. by "FLUSH INSTANCES")
|
||||
*/
|
||||
|
||||
log_info("Instance '%s': Monitor: starting mysqld...",
|
||||
(const char *) instance->get_name()->str);
|
||||
|
||||
if (start_process(old_instance_options, &process_info))
|
||||
{
|
||||
instance_map->unlock();
|
||||
return; /* error is logged */
|
||||
}
|
||||
|
||||
/* allow users to delete instances */
|
||||
instance_map->unlock();
|
||||
|
||||
log_info("Instance '%s': Monitor: waiting for mysqld to stop...",
|
||||
(const char *) instance->get_name()->str);
|
||||
|
||||
wait_process(&process_info); /* Don't check for return value. */
|
||||
|
||||
instance_map->lock();
|
||||
|
||||
current_instance= instance_map->find(instance_name.get_str());
|
||||
|
||||
if (current_instance)
|
||||
current_instance->set_crash_flag_n_wake_all();
|
||||
|
||||
instance_map->unlock();
|
||||
|
||||
if (!old_instance_options->nonguarded)
|
||||
thread_registry->unregister_thread(&thread_info);
|
||||
|
||||
log_info("Instance '%s': Monitor: finished.",
|
||||
(const char *) instance->get_name()->str);
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_name_valid(const LEX_STRING *name)
|
||||
{
|
||||
const char *name_suffix= name->str + DFLT_INSTANCE_NAME.length;
|
||||
|
||||
if (strncmp(name->str, Instance::DFLT_INSTANCE_NAME.str,
|
||||
Instance::DFLT_INSTANCE_NAME.length) != 0)
|
||||
return FALSE;
|
||||
|
||||
return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix);
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_mysqld_compatible_name(const LEX_STRING *name)
|
||||
{
|
||||
return strcmp(name->str, DFLT_INSTANCE_NAME.str) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* {{{ Constructor & destructor */
|
||||
|
||||
Instance::Instance()
|
||||
:crashed(FALSE),
|
||||
configured(FALSE)
|
||||
{
|
||||
pthread_mutex_init(&LOCK_instance, 0);
|
||||
pthread_cond_init(&COND_instance_stopped, 0);
|
||||
}
|
||||
|
||||
|
||||
Instance::~Instance()
|
||||
{
|
||||
log_info("Instance '%s': destroying...", (const char *) get_name()->str);
|
||||
|
||||
pthread_cond_destroy(&COND_instance_stopped);
|
||||
pthread_mutex_destroy(&LOCK_instance);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
Initialize instance options.
|
||||
|
||||
SYNOPSIS
|
||||
init()
|
||||
name_arg name of the instance
|
||||
|
||||
RETURN:
|
||||
0 ok
|
||||
!0 error
|
||||
FALSE - ok
|
||||
TRUE - error
|
||||
*/
|
||||
|
||||
int Instance::init(const LEX_STRING *name_arg)
|
||||
bool Instance::init(const LEX_STRING *name_arg)
|
||||
{
|
||||
mysqld_compatible= is_mysqld_compatible_name(name_arg);
|
||||
|
||||
@ -676,14 +453,295 @@ int Instance::init(const LEX_STRING *name_arg)
|
||||
}
|
||||
|
||||
|
||||
int Instance::complete_initialization(Instance_map *instance_map_arg,
|
||||
const char *mysqld_path)
|
||||
/*
|
||||
Complete instance options initialization.
|
||||
|
||||
SYNOPSIS
|
||||
complete_initialization()
|
||||
|
||||
RETURN
|
||||
FALSE - ok
|
||||
TRUE - error
|
||||
*/
|
||||
|
||||
bool Instance::complete_initialization()
|
||||
{
|
||||
instance_map= instance_map_arg;
|
||||
configured= !options.complete_initialization(mysqld_path);
|
||||
return 0;
|
||||
configured= ! options.complete_initialization();
|
||||
return FALSE;
|
||||
/*
|
||||
TODO: return actual status (from
|
||||
Instance_options::complete_initialization()) here.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
Determine if mysqld is accepting connections.
|
||||
|
||||
SYNOPSIS
|
||||
is_mysqld_running()
|
||||
|
||||
DESCRIPTION
|
||||
Try to connect to mysqld with fake login/password to check whether it is
|
||||
accepting connections or not.
|
||||
|
||||
MT-NOTE: this operation must be called under acquired LOCK_instance.
|
||||
|
||||
RETURN
|
||||
TRUE - mysqld is alive and accept connections
|
||||
FALSE - otherwise.
|
||||
*/
|
||||
|
||||
bool Instance::is_mysqld_running()
|
||||
{
|
||||
MYSQL mysql;
|
||||
uint port= options.get_mysqld_port(); /* 0 if not specified. */
|
||||
const char *socket= NULL;
|
||||
static const char *password= "check_connection";
|
||||
static const char *username= "MySQL_Instance_Manager";
|
||||
static const char *access_denied_message= "Access denied for user";
|
||||
bool return_val;
|
||||
|
||||
if (options.mysqld_socket)
|
||||
socket= options.mysqld_socket;
|
||||
|
||||
/* no port was specified => instance falled back to default value */
|
||||
if (!port && !options.mysqld_socket)
|
||||
port= SERVER_DEFAULT_PORT;
|
||||
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
|
||||
mysql_init(&mysql);
|
||||
/* try to connect to a server with a fake username/password pair */
|
||||
if (mysql_real_connect(&mysql, LOCAL_HOST, username,
|
||||
password,
|
||||
NullS, port,
|
||||
socket, 0))
|
||||
{
|
||||
/*
|
||||
We have successfully connected to the server using fake
|
||||
username/password. Write a warning to the logfile.
|
||||
*/
|
||||
log_error("Instance '%s': was able to log into mysqld.",
|
||||
(const char *) get_name()->str);
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
return_val= TRUE; /* server is alive */
|
||||
}
|
||||
else
|
||||
return_val= test(!strncmp(access_denied_message, mysql_error(&mysql),
|
||||
sizeof(access_denied_message) - 1));
|
||||
|
||||
mysql_close(&mysql);
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
/*
|
||||
The method starts an instance.
|
||||
|
||||
SYNOPSIS
|
||||
start()
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
ER_CANNOT_START_INSTANCE Cannot start instance
|
||||
ER_INSTANCE_ALREADY_STARTED The instance on the specified port/socket
|
||||
is already started
|
||||
*/
|
||||
|
||||
int Instance::start()
|
||||
{
|
||||
/* clear crash flag */
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
crashed= FALSE;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
|
||||
if (configured && !is_mysqld_running())
|
||||
{
|
||||
Instance_monitor *instance_monitor;
|
||||
remove_pid();
|
||||
|
||||
instance_monitor= new Instance_monitor(this);
|
||||
|
||||
if (instance_monitor == NULL || instance_monitor->start_detached())
|
||||
{
|
||||
delete instance_monitor;
|
||||
log_error("Instance::start(): failed to create the monitoring thread"
|
||||
" to start an instance");
|
||||
return ER_CANNOT_START_INSTANCE;
|
||||
}
|
||||
/* The monitoring thread will delete itself when it's finished. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The instance is started already or misconfigured. */
|
||||
return configured ? ER_INSTANCE_ALREADY_STARTED : ER_INSTANCE_MISCONFIGURED;
|
||||
}
|
||||
|
||||
/*
|
||||
The method sets the crash flag and wakes all waiters on
|
||||
COND_instance_stopped and COND_guardian
|
||||
|
||||
SYNOPSIS
|
||||
set_crash_flag_n_wake_all()
|
||||
|
||||
DESCRIPTION
|
||||
The method is called when an instance is crashed or terminated.
|
||||
In the former case it might indicate that guardian probably should
|
||||
restart it.
|
||||
|
||||
RETURN
|
||||
Function returns no value
|
||||
*/
|
||||
|
||||
void Instance::set_crash_flag_n_wake_all()
|
||||
{
|
||||
/* set instance state to crashed */
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
crashed= TRUE;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
/*
|
||||
Wake connection threads waiting for an instance to stop. This
|
||||
is needed if a user issued command to stop an instance via
|
||||
mysql connection. This is not the case if Guardian stop the thread.
|
||||
*/
|
||||
pthread_cond_signal(&COND_instance_stopped);
|
||||
/* wake guardian */
|
||||
pthread_cond_signal(&Manager::get_guardian()->COND_guardian);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Stop an instance.
|
||||
|
||||
SYNOPSIS
|
||||
stop()
|
||||
|
||||
RETURN:
|
||||
0 ok
|
||||
ER_INSTANCE_IS_NOT_STARTED Looks like the instance it is not started
|
||||
ER_STOP_INSTANCE mysql_shutdown reported an error
|
||||
*/
|
||||
|
||||
int Instance::stop()
|
||||
{
|
||||
struct timespec timeout;
|
||||
uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY;
|
||||
|
||||
if (is_mysqld_running())
|
||||
{
|
||||
waitchild= options.get_shutdown_delay();
|
||||
|
||||
kill_mysqld(SIGTERM);
|
||||
/* sleep on condition to wait for SIGCHLD */
|
||||
|
||||
timeout.tv_sec= time(NULL) + waitchild;
|
||||
timeout.tv_nsec= 0;
|
||||
if (pthread_mutex_lock(&LOCK_instance))
|
||||
return ER_STOP_INSTANCE;
|
||||
|
||||
while (options.load_pid() != 0) /* while server isn't stopped */
|
||||
{
|
||||
int status;
|
||||
|
||||
status= pthread_cond_timedwait(&COND_instance_stopped,
|
||||
&LOCK_instance,
|
||||
&timeout);
|
||||
if (status == ETIMEDOUT || status == ETIME)
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
kill_mysqld(SIGKILL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ER_INSTANCE_IS_NOT_STARTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Send signal to mysqld.
|
||||
|
||||
SYNOPSIS
|
||||
kill_mysqld()
|
||||
*/
|
||||
|
||||
void Instance::kill_mysqld(int signum)
|
||||
{
|
||||
pid_t mysqld_pid= options.load_pid();
|
||||
|
||||
if (mysqld_pid == 0)
|
||||
{
|
||||
log_info("Instance '%s': no pid file to send a signal (%d).",
|
||||
(const char *) get_name()->str,
|
||||
(int) signum);
|
||||
return;
|
||||
}
|
||||
|
||||
log_info("Instance '%s': sending %d to %d...",
|
||||
(const char *) get_name()->str,
|
||||
(int) signum,
|
||||
(int) mysqld_pid);
|
||||
|
||||
if (kill(mysqld_pid, signum))
|
||||
{
|
||||
log_info("Instance '%s': kill() failed.",
|
||||
(const char *) get_name()->str);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Kill suceeded */
|
||||
if (signum == SIGKILL) /* really killed instance with SIGKILL */
|
||||
{
|
||||
log_error("The instance '%s' is being stopped forcibly. Normally"
|
||||
"it should not happen. Probably the instance has been"
|
||||
"hanging. You should also check your IM setup",
|
||||
(const char *) options.instance_name.str);
|
||||
/* After sucessful hard kill the pidfile need to be removed */
|
||||
options.unlink_pidfile();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Return crashed flag.
|
||||
|
||||
SYNOPSIS
|
||||
is_crashed()
|
||||
|
||||
RETURN
|
||||
TRUE - mysqld crashed
|
||||
FALSE - mysqld hasn't crashed yet
|
||||
*/
|
||||
|
||||
bool Instance::is_crashed()
|
||||
{
|
||||
bool val;
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
val= crashed;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove pid file.
|
||||
*/
|
||||
|
||||
void Instance::remove_pid()
|
||||
{
|
||||
int mysqld_pid= options.load_pid();
|
||||
|
||||
if (mysqld_pid == 0)
|
||||
return;
|
||||
|
||||
if (options.unlink_pidfile())
|
||||
{
|
||||
log_error("Instance '%s': can not unlink pid file.",
|
||||
(const char *) options.instance_name.str);
|
||||
}
|
||||
}
|
||||
|
@ -88,21 +88,19 @@ public:
|
||||
static bool is_mysqld_compatible_name(const LEX_STRING *name);
|
||||
|
||||
public:
|
||||
Instance(Thread_registry &thread_registry_arg);
|
||||
Instance();
|
||||
|
||||
~Instance();
|
||||
int init(const LEX_STRING *name_arg);
|
||||
int complete_initialization(Instance_map *instance_map_arg,
|
||||
const char *mysqld_path);
|
||||
bool init(const LEX_STRING *name_arg);
|
||||
bool complete_initialization();
|
||||
|
||||
bool is_running();
|
||||
bool is_mysqld_running();
|
||||
int start();
|
||||
int stop();
|
||||
/* send a signal to the instance */
|
||||
void kill_instance(int signo);
|
||||
void kill_mysqld(int signo);
|
||||
bool is_crashed();
|
||||
void set_crash_flag_n_wake_all();
|
||||
Instance_map *get_map();
|
||||
|
||||
/*
|
||||
The operation is intended to check if the instance is mysqld-compatible
|
||||
@ -121,7 +119,6 @@ public:
|
||||
public:
|
||||
enum { DEFAULT_SHUTDOWN_DELAY= 35 };
|
||||
Instance_options options;
|
||||
Thread_registry &thread_registry;
|
||||
|
||||
private:
|
||||
/* This attributes is a flag, specifies if the instance has been crashed. */
|
||||
@ -155,7 +152,6 @@ private:
|
||||
stop in Instance::stop()
|
||||
*/
|
||||
pthread_cond_t COND_instance_stopped;
|
||||
Instance_map *instance_map;
|
||||
|
||||
void remove_pid();
|
||||
};
|
||||
|
@ -63,7 +63,7 @@ static void delete_instance(void *u)
|
||||
/*
|
||||
The option handler to pass to the process_default_option_files finction.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
process_option()
|
||||
ctx Handler context. Here it is an instance_map structure.
|
||||
group_name The name of the group the option belongs to.
|
||||
@ -169,7 +169,7 @@ int Instance_map::process_one_option(const LEX_STRING *group,
|
||||
if (!(instance= (Instance *) hash_search(&hash, (byte *) group->str,
|
||||
group->length)))
|
||||
{
|
||||
if (!(instance= new Instance(thread_registry)))
|
||||
if (!(instance= new Instance()))
|
||||
return 1;
|
||||
|
||||
if (instance->init(group) || add_instance(instance))
|
||||
@ -213,16 +213,13 @@ int Instance_map::process_one_option(const LEX_STRING *group,
|
||||
}
|
||||
|
||||
|
||||
Instance_map::Instance_map(const char *default_mysqld_path_arg,
|
||||
Thread_registry &thread_registry_arg):
|
||||
mysqld_path(default_mysqld_path_arg),
|
||||
thread_registry(thread_registry_arg)
|
||||
Instance_map::Instance_map()
|
||||
{
|
||||
pthread_mutex_init(&LOCK_instance_map, 0);
|
||||
}
|
||||
|
||||
|
||||
int Instance_map::init()
|
||||
bool Instance_map::init()
|
||||
{
|
||||
return hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
|
||||
get_instance_key, delete_instance, 0);
|
||||
@ -310,7 +307,7 @@ bool Instance_map::is_there_active_instance()
|
||||
while ((instance= iterator.next()))
|
||||
{
|
||||
if (guardian->find_instance_node(instance) != NULL ||
|
||||
instance->is_running())
|
||||
instance->is_mysqld_running())
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@ -335,18 +332,18 @@ int Instance_map::remove_instance(Instance *instance)
|
||||
int Instance_map::create_instance(const LEX_STRING *instance_name,
|
||||
const Named_value_arr *options)
|
||||
{
|
||||
Instance *instance= new Instance(thread_registry);
|
||||
Instance *instance= new Instance();
|
||||
|
||||
if (!instance)
|
||||
{
|
||||
log_error("Error: can not initialize (name: '%s').",
|
||||
log_error("Error: can not allocate instance (name: '%s').",
|
||||
(const char *) instance_name->str);
|
||||
return ER_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (instance->init(instance_name))
|
||||
{
|
||||
log_error("Error: can not initialize (name: '%s').",
|
||||
log_error("Error: can not initialize instance (name: '%s').",
|
||||
(const char *) instance_name->str);
|
||||
delete instance;
|
||||
return ER_OUT_OF_RESOURCES;
|
||||
@ -374,7 +371,7 @@ int Instance_map::create_instance(const LEX_STRING *instance_name,
|
||||
log_info("Warning: instance name '%s' is mysqld-compatible.",
|
||||
(const char *) instance_name->str);
|
||||
|
||||
if (instance->complete_initialization(this, mysqld_path))
|
||||
if (instance->complete_initialization())
|
||||
{
|
||||
log_error("Error: can not complete initialization of instance (name: '%s').",
|
||||
(const char *) instance_name->str);
|
||||
@ -411,7 +408,7 @@ bool Instance_map::complete_initialization()
|
||||
{
|
||||
Instance *instance= (Instance *) hash_element(&hash, i);
|
||||
|
||||
if (instance->complete_initialization(this, mysqld_path))
|
||||
if (instance->complete_initialization())
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -543,14 +540,14 @@ const char *Instance_map::get_instance_state_name(Instance *instance)
|
||||
|
||||
/* The instance is not managed by Guardian: we can report status only. */
|
||||
|
||||
return instance->is_running() ? "online" : "offline";
|
||||
return instance->is_mysqld_running() ? "online" : "offline";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create a new configuration section for mysqld-instance in the config file.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
create_instance_in_file()
|
||||
instance_name mysqld-instance name
|
||||
options options for the new mysqld-instance
|
||||
|
@ -75,7 +75,7 @@ public:
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
int init();
|
||||
bool init();
|
||||
|
||||
/*
|
||||
Process a given option and assign it to appropricate instance. This is
|
||||
@ -105,8 +105,7 @@ public:
|
||||
int create_instance(const LEX_STRING *instance_name,
|
||||
const Named_value_arr *options);
|
||||
|
||||
Instance_map(const char *default_mysqld_path_arg,
|
||||
Thread_registry &thread_registry_arg);
|
||||
Instance_map();
|
||||
~Instance_map();
|
||||
|
||||
/*
|
||||
@ -132,8 +131,6 @@ private:
|
||||
enum { START_HASH_SIZE = 16 };
|
||||
pthread_mutex_t LOCK_instance_map;
|
||||
HASH hash;
|
||||
|
||||
Thread_registry &thread_registry;
|
||||
};
|
||||
|
||||
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H */
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "buffer.h"
|
||||
#include "instance.h"
|
||||
#include "log.h"
|
||||
#include "options.h"
|
||||
#include "parse_output.h"
|
||||
#include "priv.h"
|
||||
|
||||
@ -82,8 +83,12 @@ bool Instance_options::is_option_im_specific(const char *option_name)
|
||||
|
||||
Instance_options::Instance_options()
|
||||
:mysqld_version(NULL), mysqld_socket(NULL), mysqld_datadir(NULL),
|
||||
mysqld_pid_file(NULL), mysqld_port(NULL), mysqld_port_val(0),
|
||||
nonguarded(NULL), shutdown_delay(NULL), shutdown_delay_val(0),
|
||||
mysqld_pid_file(NULL),
|
||||
nonguarded(NULL),
|
||||
mysqld_port(NULL),
|
||||
mysqld_port_val(0),
|
||||
shutdown_delay(NULL),
|
||||
shutdown_delay_val(0),
|
||||
filled_default_options(0)
|
||||
{
|
||||
mysqld_path.str= NULL;
|
||||
@ -99,7 +104,7 @@ Instance_options::Instance_options()
|
||||
/*
|
||||
Get compiled-in value of default_option
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
get_default_option()
|
||||
result buffer to put found value
|
||||
result_len buffer size
|
||||
@ -139,7 +144,7 @@ err:
|
||||
/*
|
||||
Fill mysqld_version option (used at initialization stage)
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
fill_instance_version()
|
||||
|
||||
DESCRIPTION
|
||||
@ -182,7 +187,7 @@ int Instance_options::fill_instance_version()
|
||||
err:
|
||||
if (rc)
|
||||
log_error("fill_instance_version: Failed to get version of '%s'",
|
||||
mysqld_path.str);
|
||||
(const char *) mysqld_path.str);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -190,7 +195,7 @@ err:
|
||||
/*
|
||||
Fill mysqld_real_path
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
fill_mysqld_real_path()
|
||||
|
||||
DESCRIPTION
|
||||
@ -242,7 +247,7 @@ err:
|
||||
/*
|
||||
Fill various log options
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
fill_log_options()
|
||||
|
||||
DESCRIPTION
|
||||
@ -355,7 +360,7 @@ err:
|
||||
/*
|
||||
Get the full pid file name with path
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
get_pid_filaname()
|
||||
result buffer to sotre the pidfile value
|
||||
|
||||
@ -396,7 +401,7 @@ int Instance_options::unlink_pidfile()
|
||||
}
|
||||
|
||||
|
||||
pid_t Instance_options::get_pid()
|
||||
pid_t Instance_options::load_pid()
|
||||
{
|
||||
FILE *pid_file_stream;
|
||||
|
||||
@ -415,7 +420,7 @@ pid_t Instance_options::get_pid()
|
||||
}
|
||||
|
||||
|
||||
int Instance_options::complete_initialization(const char *default_path)
|
||||
bool Instance_options::complete_initialization()
|
||||
{
|
||||
int arg_idx;
|
||||
const char *tmp;
|
||||
@ -423,10 +428,14 @@ int Instance_options::complete_initialization(const char *default_path)
|
||||
|
||||
if (!mysqld_path.str)
|
||||
{
|
||||
// Need one extra byte, as convert_dirname() adds a slash at the end.
|
||||
if (!(mysqld_path.str= alloc_root(&alloc, strlen(default_path) + 2)))
|
||||
goto err;
|
||||
strcpy(mysqld_path.str, default_path);
|
||||
/* Need one extra byte, as convert_dirname() adds a slash at the end. */
|
||||
mysqld_path.str= alloc_root(&alloc,
|
||||
strlen(Options::Main::default_mysqld_path) + 2);
|
||||
|
||||
if (! mysqld_path.str)
|
||||
return TRUE;
|
||||
|
||||
strcpy(mysqld_path.str, Options::Main::default_mysqld_path);
|
||||
}
|
||||
|
||||
// it's safe to cast this to char* since this is a buffer we are allocating
|
||||
@ -442,7 +451,7 @@ int Instance_options::complete_initialization(const char *default_path)
|
||||
shutdown_delay_val= atoi(shutdown_delay);
|
||||
|
||||
if (!(tmp= strdup_root(&alloc, "--no-defaults")))
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
if (!mysqld_pid_file)
|
||||
{
|
||||
@ -477,21 +486,21 @@ int Instance_options::complete_initialization(const char *default_path)
|
||||
}
|
||||
|
||||
if (get_pid_filename(pid_file_with_path))
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
/* we need to reserve space for the final zero + possible default options */
|
||||
if (!(argv= (char**)
|
||||
alloc_root(&alloc, (get_num_options() + 1
|
||||
+ MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
|
||||
goto err;
|
||||
return TRUE;
|
||||
filled_default_options= 0;
|
||||
|
||||
/* the path must be first in the argv */
|
||||
if (add_to_argv(mysqld_path.str))
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
if (add_to_argv(tmp))
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
arg_idx= filled_default_options;
|
||||
for (int opt_idx= 0; opt_idx < get_num_options(); ++opt_idx)
|
||||
@ -514,12 +523,9 @@ int Instance_options::complete_initialization(const char *default_path)
|
||||
argv[arg_idx]= 0;
|
||||
|
||||
if (fill_log_options() || fill_mysqld_real_path() || fill_instance_version())
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -636,26 +642,26 @@ void Instance_options::print_argv()
|
||||
|
||||
/*
|
||||
We execute this function to initialize some options.
|
||||
Return value: 0 - ok. 1 - unable to allocate memory.
|
||||
|
||||
RETURN
|
||||
FALSE - ok
|
||||
TRUE - memory allocation error
|
||||
*/
|
||||
|
||||
int Instance_options::init(const LEX_STRING *instance_name_arg)
|
||||
bool Instance_options::init(const LEX_STRING *instance_name_arg)
|
||||
{
|
||||
instance_name.length= instance_name_arg->length;
|
||||
|
||||
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
||||
|
||||
if (options.init())
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
if (!(instance_name.str= strmake_root(&alloc, instance_name_arg->str,
|
||||
instance_name_arg->length)))
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -663,3 +669,29 @@ Instance_options::~Instance_options()
|
||||
{
|
||||
free_root(&alloc, MYF(0));
|
||||
}
|
||||
|
||||
|
||||
uint Instance_options::get_shutdown_delay() const
|
||||
{
|
||||
static const uint DEFAULT_SHUTDOWN_DELAY= 35;
|
||||
|
||||
/*
|
||||
NOTE: it is important to check shutdown_delay here, but use
|
||||
shutdown_delay_val. The idea is that if the option is unset,
|
||||
shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
|
||||
*/
|
||||
|
||||
return shutdown_delay ? shutdown_delay_val : DEFAULT_SHUTDOWN_DELAY;
|
||||
}
|
||||
|
||||
int Instance_options::get_mysqld_port() const
|
||||
{
|
||||
/*
|
||||
NOTE: it is important to check mysqld_port here, but use mysqld_port_val.
|
||||
The idea is that if the option is unset, mysqld_port will be NULL, but
|
||||
mysqld_port_val will not be reset.
|
||||
*/
|
||||
|
||||
return mysqld_port ? mysqld_port_val : 0;
|
||||
}
|
||||
|
||||
|
@ -45,8 +45,9 @@ public:
|
||||
public:
|
||||
Instance_options();
|
||||
~Instance_options();
|
||||
|
||||
/* fills in argv */
|
||||
int complete_initialization(const char *default_path);
|
||||
bool complete_initialization();
|
||||
|
||||
bool set_option(Named_value *option);
|
||||
void unset_option(const char *option_name);
|
||||
@ -55,12 +56,15 @@ public:
|
||||
inline Named_value get_option(int idx) const;
|
||||
|
||||
public:
|
||||
int init(const LEX_STRING *instance_name_arg);
|
||||
pid_t get_pid();
|
||||
bool init(const LEX_STRING *instance_name_arg);
|
||||
pid_t load_pid();
|
||||
int get_pid_filename(char *result);
|
||||
int unlink_pidfile();
|
||||
void print_argv();
|
||||
|
||||
uint get_shutdown_delay() const;
|
||||
int get_mysqld_port() const;
|
||||
|
||||
public:
|
||||
/*
|
||||
We need this value to be greater or equal then FN_REFLEN found in
|
||||
@ -79,14 +83,10 @@ public:
|
||||
const char *mysqld_socket;
|
||||
const char *mysqld_datadir;
|
||||
const char *mysqld_pid_file;
|
||||
const char *mysqld_port;
|
||||
uint mysqld_port_val;
|
||||
LEX_STRING instance_name;
|
||||
LEX_STRING mysqld_path;
|
||||
LEX_STRING mysqld_real_path;
|
||||
const char *nonguarded;
|
||||
const char *shutdown_delay;
|
||||
uint shutdown_delay_val;
|
||||
/* log enums are defined in parse.h */
|
||||
char *logs[3];
|
||||
|
||||
@ -102,6 +102,11 @@ private:
|
||||
int find_option(const char *option_name);
|
||||
|
||||
private:
|
||||
const char *mysqld_port;
|
||||
uint mysqld_port_val;
|
||||
const char *shutdown_delay;
|
||||
uint shutdown_delay_val;
|
||||
|
||||
uint filled_default_options;
|
||||
MEM_ROOT alloc;
|
||||
|
||||
|
@ -85,14 +85,7 @@ void Listener::run()
|
||||
log_info("Listener: started.");
|
||||
|
||||
#ifndef __WIN__
|
||||
/* we use this var to check whether we are running on LinuxThreads */
|
||||
pid_t thread_pid;
|
||||
|
||||
thread_pid= getpid();
|
||||
|
||||
struct sockaddr_un unix_socket_address;
|
||||
/* set global variable */
|
||||
linuxthreads= (thread_pid != manager_pid);
|
||||
#endif
|
||||
|
||||
thread_registry->register_thread(&thread_info);
|
||||
@ -151,10 +144,12 @@ void Listener::run()
|
||||
{
|
||||
set_no_inherit(client_fd);
|
||||
|
||||
Vio *vio= vio_new(client_fd, socket_index == 0 ?
|
||||
VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
|
||||
socket_index == 0 ? 1 : 0);
|
||||
if (vio != 0)
|
||||
struct st_vio *vio=
|
||||
vio_new(client_fd,
|
||||
socket_index == 0 ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
|
||||
socket_index == 0 ? 1 : 0);
|
||||
|
||||
if (vio != NULL)
|
||||
handle_new_mysql_connection(vio);
|
||||
else
|
||||
{
|
||||
@ -318,12 +313,12 @@ create_unix_socket(struct sockaddr_un &unix_socket_address)
|
||||
|
||||
/*
|
||||
Create new mysql connection. Created thread is responsible for deletion of
|
||||
the Mysql_connection_thread_args and Vio instances passed to it.
|
||||
SYNOPSYS
|
||||
the Mysql_connection and Vio instances passed to it.
|
||||
SYNOPSIS
|
||||
handle_new_mysql_connection()
|
||||
*/
|
||||
|
||||
void Listener::handle_new_mysql_connection(Vio *vio)
|
||||
void Listener::handle_new_mysql_connection(struct st_vio *vio)
|
||||
{
|
||||
Mysql_connection *mysql_connection=
|
||||
new Mysql_connection(thread_registry, user_map,
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
/*
|
||||
Format log entry and write it to the given stream.
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
log()
|
||||
*/
|
||||
|
||||
|
@ -93,17 +93,17 @@ int my_sigwait(const sigset_t *set, int *sig)
|
||||
#endif
|
||||
|
||||
|
||||
void stop_all(Guardian *guardian, Thread_registry *registry)
|
||||
void Manager::stop_all_threads()
|
||||
{
|
||||
/*
|
||||
Let guardian thread know that it should break it's processing cycle,
|
||||
once it wakes up.
|
||||
*/
|
||||
guardian->request_shutdown();
|
||||
p_guardian->request_shutdown();
|
||||
/* wake guardian */
|
||||
pthread_cond_signal(&guardian->COND_guardian);
|
||||
pthread_cond_signal(&p_guardian->COND_guardian);
|
||||
/* stop all threads */
|
||||
registry->deliver_shutdown();
|
||||
p_thread_registry->deliver_shutdown();
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
@ -112,6 +112,9 @@ void stop_all(Guardian *guardian, Thread_registry *registry)
|
||||
|
||||
Guardian *Manager::p_guardian;
|
||||
Instance_map *Manager::p_instance_map;
|
||||
Thread_registry *Manager::p_thread_registry;
|
||||
User_map *Manager::p_user_map;
|
||||
pid_t Manager::manager_pid;
|
||||
|
||||
/*
|
||||
manager - entry point to the main instance manager process: start
|
||||
@ -137,8 +140,7 @@ int Manager::main()
|
||||
*/
|
||||
|
||||
User_map user_map;
|
||||
Instance_map instance_map(Options::Main::default_mysqld_path,
|
||||
thread_registry);
|
||||
Instance_map instance_map;
|
||||
Guardian guardian(&thread_registry, &instance_map,
|
||||
Options::Main::monitoring_interval);
|
||||
|
||||
@ -147,6 +149,8 @@ int Manager::main()
|
||||
manager_pid= getpid();
|
||||
p_instance_map= &instance_map;
|
||||
p_guardian= instance_map.guardian= &guardian;
|
||||
p_thread_registry= &thread_registry;
|
||||
p_user_map= &user_map;
|
||||
|
||||
/* Initialize instance map. */
|
||||
|
||||
@ -199,14 +203,11 @@ int Manager::main()
|
||||
NOTE: To work nicely with LinuxThreads, the signal thread is the first
|
||||
thread in the process.
|
||||
|
||||
NOTE:
|
||||
After init_thr_alarm() call it's possible to call thr_alarm() (from
|
||||
different threads), that results in sending ALARM signal to the alarm
|
||||
thread (which can be the main thread). That signal can interrupt
|
||||
blocking calls.
|
||||
|
||||
In other words, a blocking call can be interrupted in the main thread
|
||||
after init_thr_alarm().
|
||||
NOTE: After init_thr_alarm() call it's possible to call thr_alarm()
|
||||
(from different threads), that results in sending ALARM signal to the
|
||||
alarm thread (which can be the main thread). That signal can interrupt
|
||||
blocking calls. In other words, a blocking call can be interrupted in
|
||||
the main thread after init_thr_alarm().
|
||||
*/
|
||||
|
||||
sigset_t mask;
|
||||
@ -230,11 +231,12 @@ int Manager::main()
|
||||
*/
|
||||
if (guardian.start_detached())
|
||||
{
|
||||
log_error("manager(): Failed to create the guardian thread");
|
||||
log_error("Error: can not start Guardian thread.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Load instances. */
|
||||
|
||||
{
|
||||
instance_map.guardian->lock();
|
||||
instance_map.lock();
|
||||
@ -246,19 +248,18 @@ int Manager::main()
|
||||
|
||||
if (flush_instances_status)
|
||||
{
|
||||
log_error("Cannot init instances repository. This might be caused by "
|
||||
"the wrong config file options. For instance, missing mysqld "
|
||||
"binary. Aborting.");
|
||||
stop_all(&guardian, &thread_registry);
|
||||
log_error("Error: can not init instances repository.");
|
||||
stop_all_threads();
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* start the listener */
|
||||
/* Initialize the Listener. */
|
||||
|
||||
if (listener.start_detached())
|
||||
{
|
||||
log_error("manager(): set_stacksize_n_create_thread(listener) failed");
|
||||
stop_all(&guardian, &thread_registry);
|
||||
log_error("Error: can not start Listener thread.");
|
||||
stop_all_threads();
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -268,7 +269,9 @@ int Manager::main()
|
||||
*/
|
||||
pthread_cond_signal(&guardian.COND_guardian);
|
||||
|
||||
log_info("Main loop: started.");
|
||||
/* Main loop. */
|
||||
|
||||
log_info("Manager: started.");
|
||||
|
||||
while (!shutdown_complete)
|
||||
{
|
||||
@ -277,8 +280,8 @@ int Manager::main()
|
||||
|
||||
if ((status= my_sigwait(&mask, &signo)) != 0)
|
||||
{
|
||||
log_error("sigwait() failed");
|
||||
stop_all(&guardian, &thread_registry);
|
||||
log_error("Error: sigwait() failed");
|
||||
stop_all_threads();
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -304,7 +307,7 @@ int Manager::main()
|
||||
Bug #14164 IM tests fail on MacOS X (powermacg5)
|
||||
*/
|
||||
#ifdef IGNORE_SIGHUP_SIGQUIT
|
||||
if ( SIGHUP == signo )
|
||||
if (SIGHUP == signo)
|
||||
continue;
|
||||
#endif
|
||||
if (THR_SERVER_ALARM == signo)
|
||||
@ -312,7 +315,7 @@ int Manager::main()
|
||||
else
|
||||
#endif
|
||||
{
|
||||
log_info("Main loop: got shutdown signal.");
|
||||
log_info("Manager: got shutdown signal.");
|
||||
|
||||
if (!guardian.is_stopped())
|
||||
{
|
||||
@ -327,7 +330,7 @@ int Manager::main()
|
||||
}
|
||||
}
|
||||
|
||||
log_info("Main loop: finished.");
|
||||
log_info("Manager: finished.");
|
||||
|
||||
rc= 0;
|
||||
|
||||
|
@ -19,9 +19,12 @@
|
||||
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
|
||||
#pragma interface
|
||||
#endif
|
||||
#include <my_global.h>
|
||||
|
||||
class Guardian;
|
||||
class Instance_map;
|
||||
class Thread_registry;
|
||||
class User_map;
|
||||
|
||||
class Manager
|
||||
{
|
||||
@ -33,12 +36,18 @@ public:
|
||||
*/
|
||||
static Instance_map *get_instance_map() { return p_instance_map; }
|
||||
static Guardian *get_guardian() { return p_guardian; }
|
||||
static Thread_registry *get_thread_registry() { return p_thread_registry; }
|
||||
static User_map *get_user_map() { return p_user_map; }
|
||||
static pid_t get_manager_pid() { return manager_pid; }
|
||||
|
||||
private:
|
||||
static int manager_impl();
|
||||
static void stop_all_threads();
|
||||
private:
|
||||
static pid_t manager_pid;
|
||||
static Guardian *p_guardian;
|
||||
static Instance_map *p_instance_map;
|
||||
static Thread_registry *p_thread_registry;
|
||||
static User_map *p_user_map;
|
||||
};
|
||||
|
||||
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
|
||||
|
@ -71,6 +71,7 @@ static void daemonize(const char *log_file_name);
|
||||
static void angel();
|
||||
static struct passwd *check_user(const char *user);
|
||||
static int set_user(const char *user, struct passwd *user_info);
|
||||
static bool check_if_linuxthreads();
|
||||
#endif
|
||||
|
||||
|
||||
@ -110,6 +111,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (check_if_linuxthreads())
|
||||
goto main_end; /* out of resources */
|
||||
|
||||
if (Options::Daemon::run_as_service)
|
||||
{
|
||||
/* forks, and returns only in child */
|
||||
@ -232,7 +236,7 @@ static void init_environment(char *progname)
|
||||
#ifndef __WIN__
|
||||
/*
|
||||
Become a UNIX service
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
daemonize()
|
||||
*/
|
||||
|
||||
@ -392,4 +396,27 @@ spawn:
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static void *check_if_linuxthreads_thread_func(void *arg)
|
||||
{
|
||||
pid_t main_pid= *(pid_t*) arg;
|
||||
linuxthreads= getpid() != main_pid;
|
||||
return NULL;
|
||||
}
|
||||
} /* extern "C" */
|
||||
|
||||
|
||||
static bool check_if_linuxthreads()
|
||||
{
|
||||
pid_t pid= getpid();
|
||||
pthread_t thread_id;
|
||||
int rc;
|
||||
|
||||
rc= pthread_create(&thread_id, NULL, check_if_linuxthreads_thread_func,
|
||||
(void*) &pid);
|
||||
if (rc == 0)
|
||||
rc= pthread_join(thread_id, NULL);
|
||||
|
||||
return test(rc);
|
||||
}
|
||||
#endif
|
||||
|
@ -43,7 +43,7 @@ void trim_space(const char **text, uint *word_len)
|
||||
/*
|
||||
Parse output of the given command
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
parse_output_and_get_value()
|
||||
|
||||
command the command to execue with popen.
|
||||
|
@ -22,14 +22,13 @@
|
||||
|
||||
#include "log.h"
|
||||
|
||||
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
|
||||
pid_t manager_pid;
|
||||
|
||||
#ifndef __WIN__
|
||||
/*
|
||||
This flag is set if mysqlmanager has detected that it is running on the
|
||||
system using LinuxThreads
|
||||
*/
|
||||
bool linuxthreads;
|
||||
#endif
|
||||
|
||||
/*
|
||||
The following string must be less then 80 characters, as
|
||||
|
@ -50,9 +50,6 @@ const int MAX_VERSION_LENGTH= 160;
|
||||
|
||||
const int MAX_INSTANCE_NAME_SIZE= FN_REFLEN;
|
||||
|
||||
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
|
||||
extern pid_t manager_pid;
|
||||
|
||||
#ifndef __WIN__
|
||||
/*
|
||||
This flag is set if mysqlmanager has detected that it is running on the
|
||||
|
@ -20,7 +20,7 @@
|
||||
This function must not be used in user-management command implementations.
|
||||
Use get_user_name() instead.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
get_user_name_impl()
|
||||
|
||||
RETURN
|
||||
@ -58,7 +58,7 @@ static char *get_user_name_impl()
|
||||
(not empty, not exceeds USERNAME_LENGTH). Report to stderr if something is
|
||||
wrong.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
get_user_name()
|
||||
user_name [OUT] on success contains user name
|
||||
|
||||
@ -102,7 +102,7 @@ static bool get_user_name(LEX_STRING *user_name)
|
||||
The password is retrieved from command-line options (if specified) or from
|
||||
console.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
get_password()
|
||||
|
||||
RETURN
|
||||
@ -131,7 +131,7 @@ static const char *get_password()
|
||||
/*
|
||||
Load password file into user map.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
load_password_file()
|
||||
user_map target user map
|
||||
|
||||
@ -160,7 +160,7 @@ static int load_password_file(User_map *user_map)
|
||||
/*
|
||||
Save user map into password file.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
save_password_file()
|
||||
user_map user map
|
||||
|
||||
|
@ -49,7 +49,7 @@ public:
|
||||
/*
|
||||
Executes user-management command.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
execute()
|
||||
|
||||
RETURN
|
||||
|
@ -159,7 +159,7 @@ User_map::~User_map()
|
||||
/*
|
||||
Load password database.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
load()
|
||||
password_file_name [IN] password file path
|
||||
err_msg [OUT] error message
|
||||
|
Reference in New Issue
Block a user