mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
This is an implementation of two WL items:
- WL#3158: IM: Instance configuration extensions; - WL#3159: IM: --bootstrap and --start-default-instance modes The following new statements have been added: - CREATE INSTANCE; - DROP INSTANCE; The behaviour of the following statements have been changed: - SET; - UNSET; - FLUSH INSTANCES; - SHOW INSTANCES; - SHOW INSTANCE OPTIONS;
This commit is contained in:
@ -20,27 +20,24 @@
|
||||
|
||||
#include "instance_options.h"
|
||||
|
||||
#include "parse_output.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#include <my_global.h>
|
||||
#include <my_sys.h>
|
||||
#include <signal.h>
|
||||
#include <m_string.h>
|
||||
|
||||
#ifdef __WIN__
|
||||
#define NEWLINE_LEN 2
|
||||
#else
|
||||
#define NEWLINE_LEN 1
|
||||
#endif
|
||||
#include <signal.h>
|
||||
|
||||
#include "buffer.h"
|
||||
#include "instance.h"
|
||||
#include "log.h"
|
||||
#include "parse_output.h"
|
||||
#include "priv.h"
|
||||
|
||||
|
||||
/* Create "mysqld ..." command in the buffer */
|
||||
|
||||
static inline int create_mysqld_command(Buffer *buf,
|
||||
const char *mysqld_path_str,
|
||||
uint mysqld_path_len,
|
||||
const char *option,
|
||||
uint option_len)
|
||||
const LEX_STRING *mysqld_path,
|
||||
const LEX_STRING *option)
|
||||
{
|
||||
int position= 0;
|
||||
|
||||
@ -49,13 +46,13 @@ static inline int create_mysqld_command(Buffer *buf,
|
||||
#ifdef __WIN__
|
||||
buf->append(position++, "\"", 1);
|
||||
#endif
|
||||
buf->append(position, mysqld_path_str, mysqld_path_len);
|
||||
position+= mysqld_path_len;
|
||||
buf->append(position, mysqld_path->str, mysqld_path->length);
|
||||
position+= mysqld_path->length;
|
||||
#ifdef __WIN__
|
||||
buf->append(position++, "\"", 1);
|
||||
#endif
|
||||
/* here the '\0' character is copied from the option string */
|
||||
buf->append(position, option, option_len);
|
||||
buf->append(position, option->str, option->length + 1);
|
||||
|
||||
return buf->is_error();
|
||||
}
|
||||
@ -63,6 +60,39 @@ static inline int create_mysqld_command(Buffer *buf,
|
||||
}
|
||||
|
||||
|
||||
bool Instance_options::is_option_im_specific(const char *option_name)
|
||||
{
|
||||
static const char *IM_SPECIFIC_OPTIONS[] =
|
||||
{
|
||||
"nonguarded",
|
||||
"mysqld-path",
|
||||
"shutdown-delay",
|
||||
NULL
|
||||
};
|
||||
|
||||
for (int i= 0; IM_SPECIFIC_OPTIONS[i]; ++i)
|
||||
{
|
||||
if (!strcmp(option_name, IM_SPECIFIC_OPTIONS[i]))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
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),
|
||||
filled_default_options(0)
|
||||
{
|
||||
mysqld_path.str= NULL;
|
||||
mysqld_path.length= 0;
|
||||
|
||||
memset(logs, 0, sizeof(logs));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Get compiled-in value of default_option
|
||||
|
||||
@ -86,13 +116,13 @@ int Instance_options::get_default_option(char *result, size_t result_len,
|
||||
const char *option_name)
|
||||
{
|
||||
int rc= 1;
|
||||
char verbose_option[]= " --no-defaults --verbose --help";
|
||||
LEX_STRING verbose_option=
|
||||
{ C_STRING_WITH_SIZE(" --no-defaults --verbose --help") };
|
||||
|
||||
/* reserve space fot the path + option + final '\0' */
|
||||
Buffer cmd(mysqld_path_len + sizeof(verbose_option));
|
||||
/* reserve space for the path + option + final '\0' */
|
||||
Buffer cmd(mysqld_path.length + verbose_option.length + 1);
|
||||
|
||||
if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len,
|
||||
verbose_option, sizeof(verbose_option)))
|
||||
if (create_mysqld_command(&cmd, &mysqld_path, &verbose_option))
|
||||
goto err;
|
||||
|
||||
/* +2 eats first "--" from the option string (E.g. "--datadir") */
|
||||
@ -120,21 +150,19 @@ err:
|
||||
|
||||
int Instance_options::fill_instance_version()
|
||||
{
|
||||
enum { MAX_VERSION_STRING_LENGTH= 160 };
|
||||
char result[MAX_VERSION_STRING_LENGTH];
|
||||
char version_option[]= " --no-defaults --version";
|
||||
char result[MAX_VERSION_LENGTH];
|
||||
LEX_STRING version_option=
|
||||
{ C_STRING_WITH_SIZE(" --no-defaults --version") };
|
||||
int rc= 1;
|
||||
Buffer cmd(mysqld_path_len + sizeof(version_option));
|
||||
Buffer cmd(mysqld_path.length + version_option.length + 1);
|
||||
|
||||
if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len,
|
||||
version_option, sizeof(version_option)))
|
||||
if (create_mysqld_command(&cmd, &mysqld_path, &version_option))
|
||||
goto err;
|
||||
|
||||
bzero(result, MAX_VERSION_STRING_LENGTH);
|
||||
bzero(result, MAX_VERSION_LENGTH);
|
||||
|
||||
rc= parse_output_and_get_value(cmd.buffer, "Ver",
|
||||
result, MAX_VERSION_STRING_LENGTH,
|
||||
GET_LINE);
|
||||
rc= parse_output_and_get_value(cmd.buffer, "Ver", result,
|
||||
MAX_VERSION_LENGTH, GET_LINE);
|
||||
|
||||
if (*result != '\0')
|
||||
{
|
||||
@ -145,6 +173,7 @@ int Instance_options::fill_instance_version()
|
||||
start= result;
|
||||
while (my_isspace(default_charset_info, *start))
|
||||
++start;
|
||||
|
||||
mysqld_version= strdup_root(&alloc, start);
|
||||
}
|
||||
err:
|
||||
@ -200,8 +229,7 @@ int Instance_options::fill_log_options()
|
||||
else
|
||||
{
|
||||
/* below is safe, as --datadir always has a value */
|
||||
strmake(datadir,
|
||||
strchr(mysqld_datadir, '=') + 1, MAX_LOG_OPTION_LENGTH - 1);
|
||||
strmake(datadir, mysqld_datadir, MAX_LOG_OPTION_LENGTH - 1);
|
||||
}
|
||||
|
||||
if (gethostname(hostname,sizeof(hostname)-1) < 0)
|
||||
@ -287,7 +315,6 @@ err:
|
||||
|
||||
int Instance_options::get_pid_filename(char *result)
|
||||
{
|
||||
const char *pid_file= mysqld_pid_file;
|
||||
char datadir[MAX_PATH_LEN];
|
||||
|
||||
if (mysqld_datadir == NULL)
|
||||
@ -297,14 +324,10 @@ int Instance_options::get_pid_filename(char *result)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
strxnmov(datadir, MAX_PATH_LEN - 1, strchr(mysqld_datadir, '=') + 1,
|
||||
"/", NullS);
|
||||
|
||||
DBUG_ASSERT(mysqld_pid_file);
|
||||
pid_file= strchr(pid_file, '=') + 1;
|
||||
strxnmov(datadir, MAX_PATH_LEN - 1, mysqld_datadir, "/", NullS);
|
||||
|
||||
/* get the full path to the pidfile */
|
||||
my_load_path(result, pid_file, datadir);
|
||||
my_load_path(result, mysqld_pid_file, datadir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -333,23 +356,22 @@ pid_t Instance_options::get_pid()
|
||||
}
|
||||
|
||||
|
||||
int Instance_options::complete_initialization(const char *default_path,
|
||||
uint instance_type)
|
||||
int Instance_options::complete_initialization(const char *default_path)
|
||||
{
|
||||
const char *tmp;
|
||||
char *end;
|
||||
|
||||
if (!mysqld_path && !(mysqld_path= strdup_root(&alloc, default_path)))
|
||||
if (!mysqld_path.str && !(mysqld_path.str= strdup_root(&alloc, default_path)))
|
||||
goto err;
|
||||
|
||||
// it's safe to cast this to char* since this is a buffer we are allocating
|
||||
end= convert_dirname((char*)mysqld_path, mysqld_path, NullS);
|
||||
end= convert_dirname((char*)mysqld_path.str, mysqld_path.str, NullS);
|
||||
end[-1]= 0;
|
||||
|
||||
mysqld_path_len= strlen(mysqld_path);
|
||||
mysqld_path.length= strlen(mysqld_path.str);
|
||||
|
||||
if (mysqld_port)
|
||||
mysqld_port_val= atoi(strchr(mysqld_port, '=') + 1);
|
||||
mysqld_port_val= atoi(mysqld_port);
|
||||
|
||||
if (shutdown_delay)
|
||||
shutdown_delay_val= atoi(shutdown_delay);
|
||||
@ -357,7 +379,7 @@ int Instance_options::complete_initialization(const char *default_path,
|
||||
if (!(tmp= strdup_root(&alloc, "--no-defaults")))
|
||||
goto err;
|
||||
|
||||
if (!(mysqld_pid_file))
|
||||
if (!mysqld_pid_file)
|
||||
{
|
||||
char pidfilename[MAX_PATH_LEN];
|
||||
char hostname[MAX_PATH_LEN];
|
||||
@ -366,26 +388,27 @@ int Instance_options::complete_initialization(const char *default_path,
|
||||
If we created only one istance [mysqld], because no config. files were
|
||||
found, we would like to model mysqld pid file values.
|
||||
*/
|
||||
|
||||
if (!gethostname(hostname, sizeof(hostname) - 1))
|
||||
{
|
||||
if (instance_type & DEFAULT_SINGLE_INSTANCE)
|
||||
strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", hostname,
|
||||
".pid", NullS);
|
||||
if (Instance::is_mysqld_compatible_name(&instance_name))
|
||||
strxnmov(pidfilename, MAX_PATH_LEN - 1, hostname, ".pid", NullS);
|
||||
else
|
||||
strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name,
|
||||
"-", hostname, ".pid", NullS);
|
||||
strxnmov(pidfilename, MAX_PATH_LEN - 1, instance_name.str, "-",
|
||||
hostname, ".pid", NullS);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (instance_type & DEFAULT_SINGLE_INSTANCE)
|
||||
strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", "mysql",
|
||||
".pid", NullS);
|
||||
if (Instance::is_mysqld_compatible_name(&instance_name))
|
||||
strxnmov(pidfilename, MAX_PATH_LEN - 1, "mysql", ".pid", NullS);
|
||||
else
|
||||
strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name,
|
||||
".pid", NullS);
|
||||
strxnmov(pidfilename, MAX_PATH_LEN - 1, instance_name.str, ".pid",
|
||||
NullS);
|
||||
}
|
||||
|
||||
add_option(pidfilename);
|
||||
Named_value option((char *) "pid-file", pidfilename);
|
||||
|
||||
set_option(&option);
|
||||
}
|
||||
|
||||
if (get_pid_filename(pid_file_with_path))
|
||||
@ -393,20 +416,37 @@ int Instance_options::complete_initialization(const char *default_path,
|
||||
|
||||
/* we need to reserve space for the final zero + possible default options */
|
||||
if (!(argv= (char**)
|
||||
alloc_root(&alloc, (options_array.elements + 1
|
||||
alloc_root(&alloc, (get_num_options() + 1
|
||||
+ MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
|
||||
goto err;
|
||||
filled_default_options= 0;
|
||||
|
||||
/* the path must be first in the argv */
|
||||
if (add_to_argv(mysqld_path))
|
||||
if (add_to_argv(mysqld_path.str))
|
||||
goto err;
|
||||
|
||||
if (add_to_argv(tmp))
|
||||
goto err;
|
||||
|
||||
memcpy((gptr) (argv + filled_default_options), options_array.buffer,
|
||||
options_array.elements*sizeof(char*));
|
||||
argv[filled_default_options + options_array.elements]= 0;
|
||||
int arg_idx= filled_default_options;
|
||||
for (int opt_idx= 0; opt_idx < get_num_options(); ++opt_idx)
|
||||
{
|
||||
char option_str[MAX_OPTION_STR_LEN];
|
||||
Named_value option= get_option(opt_idx);
|
||||
|
||||
if (is_option_im_specific(option.get_name()))
|
||||
continue;
|
||||
|
||||
char *ptr= strxnmov(option_str, MAX_OPTION_LEN + 3, "--", option.get_name(),
|
||||
NullS);
|
||||
|
||||
if (option.get_value()[0])
|
||||
strxnmov(ptr, MAX_OPTION_LEN + 2, "=", option.get_value(), NullS);
|
||||
|
||||
argv[arg_idx++]= strdup_root(&alloc, option_str);
|
||||
}
|
||||
|
||||
argv[arg_idx]= 0;
|
||||
|
||||
if (fill_log_options() || fill_instance_version())
|
||||
goto err;
|
||||
@ -418,75 +458,91 @@ err:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Assigns given value to the appropriate option from the class.
|
||||
|
||||
SYNOPSYS
|
||||
add_option()
|
||||
option string with the option prefixed by --
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
The method is called from the option handling routine.
|
||||
|
||||
RETURN
|
||||
0 - ok
|
||||
1 - error occured
|
||||
*/
|
||||
|
||||
int Instance_options::add_option(const char* option)
|
||||
bool Instance_options::set_option(Named_value *option)
|
||||
{
|
||||
char *tmp;
|
||||
enum { SAVE_VALUE= 1, SAVE_WHOLE, SAVE_WHOLE_AND_ADD };
|
||||
struct selected_options_st
|
||||
bool err_status;
|
||||
int idx= find_option(option->get_name());
|
||||
char *option_name_str;
|
||||
char *option_value_str;
|
||||
|
||||
if (!(option_name_str= Named_value::alloc_str(option->get_name())))
|
||||
return TRUE;
|
||||
|
||||
if (!(option_value_str= Named_value::alloc_str(option->get_value())))
|
||||
{
|
||||
Named_value::free_str(&option_name_str);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Named_value option_copy(option_name_str, option_value_str);
|
||||
|
||||
if (idx < 0)
|
||||
err_status= options.add_element(&option_copy);
|
||||
else
|
||||
err_status= options.replace_element(idx, &option_copy);
|
||||
|
||||
if (!err_status)
|
||||
update_var(option_copy.get_name(), option_copy.get_value());
|
||||
else
|
||||
option_copy.free();
|
||||
|
||||
return err_status;
|
||||
}
|
||||
|
||||
|
||||
void Instance_options::unset_option(const char *option_name)
|
||||
{
|
||||
int idx= find_option(option_name);
|
||||
|
||||
if (idx < 0)
|
||||
return; /* the option has not been set. */
|
||||
|
||||
options.remove_element(idx);
|
||||
|
||||
update_var(option_name, NULL);
|
||||
}
|
||||
|
||||
|
||||
void Instance_options::update_var(const char *option_name,
|
||||
const char *option_value)
|
||||
{
|
||||
struct options_st
|
||||
{
|
||||
const char *name;
|
||||
uint length;
|
||||
const char **value;
|
||||
uint type;
|
||||
} options[]=
|
||||
uint name_len;
|
||||
const char **var;
|
||||
} options_def[]=
|
||||
{
|
||||
{"--socket=", 9, &mysqld_socket, SAVE_WHOLE_AND_ADD},
|
||||
{"--port=", 7, &mysqld_port, SAVE_WHOLE_AND_ADD},
|
||||
{"--datadir=", 10, &mysqld_datadir, SAVE_WHOLE_AND_ADD},
|
||||
{"--bind-address=", 15, &mysqld_bind_address, SAVE_WHOLE_AND_ADD},
|
||||
{"--pid-file=", 11, &mysqld_pid_file, SAVE_WHOLE_AND_ADD},
|
||||
{"--mysqld-path=", 14, &mysqld_path, SAVE_VALUE},
|
||||
{"--nonguarded", 9, &nonguarded, SAVE_WHOLE},
|
||||
{"--shutdown_delay", 9, &shutdown_delay, SAVE_VALUE},
|
||||
{NULL, 0, NULL, 0}
|
||||
{"socket", 6, &mysqld_socket},
|
||||
{"port", 4, &mysqld_port},
|
||||
{"datadir", 7, &mysqld_datadir},
|
||||
{"pid-file", 8, &mysqld_pid_file},
|
||||
{"nonguarded", 10, &nonguarded},
|
||||
{"mysqld-path", 11, (const char **) &mysqld_path.str},
|
||||
{"shutdown-delay", 14, &shutdown_delay},
|
||||
{NULL, 0, NULL}
|
||||
};
|
||||
struct selected_options_st *selected_options;
|
||||
|
||||
if (!(tmp= strdup_root(&alloc, option)))
|
||||
goto err;
|
||||
for (options_st *opt= options_def; opt->name; ++opt)
|
||||
{
|
||||
if (!strncmp(opt->name, option_name, opt->name_len))
|
||||
{
|
||||
*(opt->var)= option_value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (selected_options= options; selected_options->name; selected_options++)
|
||||
{
|
||||
if (strncmp(tmp, selected_options->name, selected_options->length) == 0)
|
||||
switch (selected_options->type) {
|
||||
case SAVE_WHOLE_AND_ADD:
|
||||
*(selected_options->value)= tmp;
|
||||
insert_dynamic(&options_array,(gptr) &tmp);
|
||||
return 0;
|
||||
case SAVE_VALUE:
|
||||
*(selected_options->value)= strchr(tmp, '=') + 1;
|
||||
return 0;
|
||||
case SAVE_WHOLE:
|
||||
*(selected_options->value)= tmp;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we haven't returned earlier we should just save the option */
|
||||
insert_dynamic(&options_array,(gptr) &tmp);
|
||||
int Instance_options::find_option(const char *option_name)
|
||||
{
|
||||
for (int i= 0; i < get_num_options(); i++)
|
||||
{
|
||||
if (!strcmp(get_option(i).get_name(), option_name))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -504,7 +560,10 @@ int Instance_options::add_to_argv(const char* option)
|
||||
void Instance_options::print_argv()
|
||||
{
|
||||
int i;
|
||||
printf("printing out an instance %s argv:\n", instance_name);
|
||||
|
||||
printf("printing out an instance %s argv:\n",
|
||||
(const char *) instance_name.str);
|
||||
|
||||
for (i=0; argv[i] != NULL; i++)
|
||||
printf("argv: %s\n", argv[i]);
|
||||
}
|
||||
@ -515,17 +574,17 @@ void Instance_options::print_argv()
|
||||
Return value: 0 - ok. 1 - unable to allocate memory.
|
||||
*/
|
||||
|
||||
int Instance_options::init(const char *instance_name_arg)
|
||||
int Instance_options::init(const LEX_STRING *instance_name_arg)
|
||||
{
|
||||
instance_name_len= strlen(instance_name_arg);
|
||||
instance_name.length= instance_name_arg->length;
|
||||
|
||||
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
||||
|
||||
if (my_init_dynamic_array(&options_array, sizeof(char*), 0, 32))
|
||||
if (options.init())
|
||||
goto err;
|
||||
|
||||
if (!(instance_name= strmake_root(&alloc, (char*) instance_name_arg,
|
||||
instance_name_len)))
|
||||
if (!(instance_name.str= strmake_root(&alloc, instance_name_arg->str,
|
||||
instance_name_arg->length)))
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
@ -538,6 +597,4 @@ err:
|
||||
Instance_options::~Instance_options()
|
||||
{
|
||||
free_root(&alloc, MYF(0));
|
||||
delete_dynamic(&options_array);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user