Merge
This commit is contained in:
commit
834c47f336
@ -778,6 +778,11 @@ extern void reset_root_defaults(MEM_ROOT *mem_root, uint block_size,
|
|||||||
extern char *strdup_root(MEM_ROOT *root,const char *str);
|
extern char *strdup_root(MEM_ROOT *root,const char *str);
|
||||||
extern char *strmake_root(MEM_ROOT *root,const char *str,uint len);
|
extern char *strmake_root(MEM_ROOT *root,const char *str,uint len);
|
||||||
extern char *memdup_root(MEM_ROOT *root,const char *str,uint len);
|
extern char *memdup_root(MEM_ROOT *root,const char *str,uint len);
|
||||||
|
extern int my_correct_defaults_file(const char *file_location,
|
||||||
|
const char *option,
|
||||||
|
const char *option_value,
|
||||||
|
const char *section_name,
|
||||||
|
int remove_option);
|
||||||
extern void get_defaults_files(int argc, char **argv,
|
extern void get_defaults_files(int argc, char **argv,
|
||||||
char **defaults, char **extra_defaults);
|
char **defaults, char **extra_defaults);
|
||||||
extern int load_defaults(const char *conf_file, const char **groups,
|
extern int load_defaults(const char *conf_file, const char **groups,
|
||||||
|
@ -67,7 +67,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
|
|||||||
mf_iocache2.lo my_seek.lo my_sleep.lo \
|
mf_iocache2.lo my_seek.lo my_sleep.lo \
|
||||||
my_pread.lo mf_cache.lo md5.lo sha1.lo \
|
my_pread.lo mf_cache.lo md5.lo sha1.lo \
|
||||||
my_getopt.lo my_gethostbyname.lo my_port.lo \
|
my_getopt.lo my_gethostbyname.lo my_port.lo \
|
||||||
my_rename.lo
|
my_rename.lo my_chsize.lo
|
||||||
sqlobjects = net.lo
|
sqlobjects = net.lo
|
||||||
sql_cmn_objects = pack.lo client.lo my_time.lo
|
sql_cmn_objects = pack.lo client.lo my_time.lo
|
||||||
|
|
||||||
|
138
mysys/default.c
138
mysys/default.c
@ -50,9 +50,11 @@ const char *default_directories[MAX_DEFAULT_DIRS + 1];
|
|||||||
|
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
static const char *f_extensions[]= { ".ini", ".cnf", 0 };
|
static const char *f_extensions[]= { ".ini", ".cnf", 0 };
|
||||||
|
#define NEWLINE "\r\n"
|
||||||
static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN];
|
static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN];
|
||||||
#else
|
#else
|
||||||
static const char *f_extensions[]= { ".cnf", 0 };
|
static const char *f_extensions[]= { ".cnf", 0 };
|
||||||
|
#define NEWLINE "\n"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -79,6 +81,142 @@ static void init_default_directories();
|
|||||||
|
|
||||||
static char *remove_end_comment(char *ptr);
|
static char *remove_end_comment(char *ptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add/remove option to the option file section.
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
my_correct_file()
|
||||||
|
file_location The location of configuration file to edit
|
||||||
|
option option to look for
|
||||||
|
option value The value of the option we would like to set
|
||||||
|
section_name the name of the section
|
||||||
|
remove_option This is true if we want to remove the option.
|
||||||
|
False otherwise.
|
||||||
|
IMPLEMENTATION
|
||||||
|
We open the option file first, then read the file line-by-line,
|
||||||
|
looking for the section we need. At the same time we put these lines
|
||||||
|
into a buffer. Then we look for the option within this section and
|
||||||
|
change/remove it. In the end we get a buffer with modified version of the
|
||||||
|
file. Then we write it to the file, truncate it if needed and close it.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - ok
|
||||||
|
1 - some error has occured. Probably due to the lack of resourses
|
||||||
|
-1 - cannot open the file
|
||||||
|
*/
|
||||||
|
|
||||||
|
int my_correct_defaults_file(const char *file_location, const char *option,
|
||||||
|
const char *option_value,
|
||||||
|
const char *section_name, int remove_option)
|
||||||
|
{
|
||||||
|
FILE *cnf_file;
|
||||||
|
struct stat file_stat;
|
||||||
|
char linebuff[512], *ptr;
|
||||||
|
uint optlen;
|
||||||
|
uint len;
|
||||||
|
char *file_buffer;
|
||||||
|
uint position= 0;
|
||||||
|
int is_found= FALSE;
|
||||||
|
|
||||||
|
optlen= strlen(option);
|
||||||
|
|
||||||
|
DBUG_ENTER("my_correct_file");
|
||||||
|
|
||||||
|
if (!(cnf_file= my_fopen(file_location, O_RDWR, MYF(0))))
|
||||||
|
goto err_fopen;
|
||||||
|
|
||||||
|
/* my_fstat doesn't use the flag parameter */
|
||||||
|
if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Reserve space to read the contents of the file and some more
|
||||||
|
for the option we want ot add.
|
||||||
|
*/
|
||||||
|
file_buffer= (char*) my_malloc(sizeof(char)*
|
||||||
|
(file_stat.st_size + /* current file size */
|
||||||
|
optlen + /* option name len */
|
||||||
|
2 + /* reserve space for newline */
|
||||||
|
1 + /* reserve for '=' char */
|
||||||
|
strlen(option_value)), /* option value len */
|
||||||
|
MYF(MY_WME));
|
||||||
|
|
||||||
|
if (!file_buffer)
|
||||||
|
goto malloc_err;
|
||||||
|
while (fgets(linebuff, sizeof(linebuff), cnf_file))
|
||||||
|
{
|
||||||
|
len= strlen(linebuff);
|
||||||
|
|
||||||
|
/* if the section is found traverse it */
|
||||||
|
if (is_found)
|
||||||
|
{
|
||||||
|
/* skip the old value of the option we are changing */
|
||||||
|
if (strncmp(linebuff, option, optlen))
|
||||||
|
{
|
||||||
|
/* copy all other lines */
|
||||||
|
strmake(file_buffer + position, linebuff, len);
|
||||||
|
position+= len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strmake(file_buffer + position, linebuff, len);
|
||||||
|
position+= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* looking for appropriate section */
|
||||||
|
for (ptr= linebuff ; my_isspace(&my_charset_latin1,*ptr) ; ptr++)
|
||||||
|
{}
|
||||||
|
|
||||||
|
if (*ptr == '[')
|
||||||
|
{
|
||||||
|
/* copy the line to the buffer */
|
||||||
|
if (!strncmp(++ptr, section_name, strlen(section_name)))
|
||||||
|
{
|
||||||
|
is_found= TRUE;
|
||||||
|
/* add option */
|
||||||
|
if (!remove_option)
|
||||||
|
{
|
||||||
|
strmake(file_buffer + position, option, optlen);
|
||||||
|
position+= optlen;
|
||||||
|
if (*option_value)
|
||||||
|
{
|
||||||
|
*(file_buffer + position++)= '=';
|
||||||
|
strmake(file_buffer + position, option_value,
|
||||||
|
strlen(option_value));
|
||||||
|
position+= strlen(option_value);
|
||||||
|
}
|
||||||
|
/* add a newline */
|
||||||
|
strcat(file_buffer + position, NEWLINE);
|
||||||
|
position+= strlen(NEWLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
is_found= FALSE; /* mark that this section is of no interest to us */
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_chsize(fileno(cnf_file), position, 0, MYF(MY_WME)) ||
|
||||||
|
my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
|
||||||
|
my_fwrite(cnf_file, file_buffer, position, MYF(MY_NABP)) ||
|
||||||
|
my_fclose(cnf_file, MYF(MY_WME)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
my_free(file_buffer, MYF(0));
|
||||||
|
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
err:
|
||||||
|
my_free(file_buffer, MYF(0));
|
||||||
|
malloc_err:
|
||||||
|
my_fclose(cnf_file, MYF(0));
|
||||||
|
DBUG_RETURN(1); /* out of resources */
|
||||||
|
err_fopen:
|
||||||
|
DBUG_RETURN(-1); /* cannot access the option file */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Process config files in default directories.
|
Process config files in default directories.
|
||||||
|
@ -30,7 +30,9 @@
|
|||||||
MyFlags Flags
|
MyFlags Flags
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
my_chsize() truncates file if shorter else fill with the filler character
|
my_chsize() truncates file if shorter else fill with the filler character.
|
||||||
|
The function also changes the file pointer. Usually it points to the end
|
||||||
|
of the file after execution.
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 Ok
|
0 Ok
|
||||||
|
@ -64,7 +64,7 @@ int Buffer::append(uint position, const char *string, uint len_arg)
|
|||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
|
||||||
The method checks whether it is possible to pus a string of teh "len_arg"
|
The method checks whether it is possible to put a string of the "len_arg"
|
||||||
length into the buffer, starting from "position" byte. In the case when the
|
length into the buffer, starting from "position" byte. In the case when the
|
||||||
buffer is too small it reallocs the buffer. The total size of the buffer is
|
buffer is too small it reallocs the buffer. The total size of the buffer is
|
||||||
restricted with 16 Mb.
|
restricted with 16 Mb.
|
||||||
@ -81,7 +81,7 @@ int Buffer::reserve(uint position, uint len_arg)
|
|||||||
|
|
||||||
if (position + len_arg >= buffer_size)
|
if (position + len_arg >= buffer_size)
|
||||||
{
|
{
|
||||||
buffer= (char *) my_realloc(buffer,
|
buffer= (char*) my_realloc(buffer,
|
||||||
min(MAX_BUFFER_SIZE,
|
min(MAX_BUFFER_SIZE,
|
||||||
max((uint) (buffer_size*1.5),
|
max((uint) (buffer_size*1.5),
|
||||||
position + len_arg)), MYF(0));
|
position + len_arg)), MYF(0));
|
||||||
|
@ -25,6 +25,40 @@
|
|||||||
|
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
#include <my_dir.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add a string to a buffer
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
put_to_buff()
|
||||||
|
buff buffer to add the string
|
||||||
|
str string to add
|
||||||
|
uint offset in the buff to add a string
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
|
||||||
|
Function to add a string to the buffer. It is different from
|
||||||
|
store_to_string, which is used in the protocol.cc. The last
|
||||||
|
one also stores the length of the string in a special way.
|
||||||
|
This is required for MySQL client/server protocol support only.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - ok
|
||||||
|
1 - error occured
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static inline int put_to_buff(Buffer *buff, const char *str, uint *position)
|
||||||
|
{
|
||||||
|
uint len= strlen(str);
|
||||||
|
if (buff->append(*position, str, len))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
*position+= len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* implementation for Show_instances: */
|
/* implementation for Show_instances: */
|
||||||
@ -34,15 +68,16 @@
|
|||||||
The method sends a list of instances in the instance map to the client.
|
The method sends a list of instances in the instance map to the client.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSYS
|
||||||
Show_instances::do_command()
|
Show_instances::execute()
|
||||||
net The network connection to the client.
|
net The network connection to the client.
|
||||||
|
connection_id Client connection ID
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 - ok
|
0 - ok
|
||||||
1 - error occured
|
1 - error occured
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int Show_instances::do_command(struct st_net *net)
|
int Show_instances::execute(struct st_net *net, ulong connection_id)
|
||||||
{
|
{
|
||||||
Buffer send_buff; /* buffer for packets */
|
Buffer send_buff; /* buffer for packets */
|
||||||
LIST name, status;
|
LIST name, status;
|
||||||
@ -50,11 +85,11 @@ int Show_instances::do_command(struct st_net *net)
|
|||||||
LIST *field_list;
|
LIST *field_list;
|
||||||
uint position=0;
|
uint position=0;
|
||||||
|
|
||||||
name_field.name= (char *) "instance_name";
|
name_field.name= (char*) "instance_name";
|
||||||
name_field.length= 20;
|
name_field.length= DEFAULT_FIELD_LENGTH;
|
||||||
name.data= &name_field;
|
name.data= &name_field;
|
||||||
status_field.name= (char *) "status";
|
status_field.name= (char*) "status";
|
||||||
status_field.length= 20;
|
status_field.length= DEFAULT_FIELD_LENGTH;
|
||||||
status.data= &status_field;
|
status.data= &status_field;
|
||||||
field_list= list_add(NULL, &status);
|
field_list= list_add(NULL, &status);
|
||||||
field_list= list_add(field_list, &name);
|
field_list= list_add(field_list, &name);
|
||||||
@ -71,9 +106,9 @@ int Show_instances::do_command(struct st_net *net)
|
|||||||
position= 0;
|
position= 0;
|
||||||
store_to_string(&send_buff, instance->options.instance_name, &position);
|
store_to_string(&send_buff, instance->options.instance_name, &position);
|
||||||
if (instance->is_running())
|
if (instance->is_running())
|
||||||
store_to_string(&send_buff, (char *) "online", &position);
|
store_to_string(&send_buff, (char*) "online", &position);
|
||||||
else
|
else
|
||||||
store_to_string(&send_buff, (char *) "offline", &position);
|
store_to_string(&send_buff, (char*) "offline", &position);
|
||||||
if (my_net_write(net, send_buff.buffer, (uint) position))
|
if (my_net_write(net, send_buff.buffer, (uint) position))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -86,16 +121,7 @@ int Show_instances::do_command(struct st_net *net)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
return 1;
|
return ER_OUT_OF_RESOURCES;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int Show_instances::execute(struct st_net *net, ulong connection_id)
|
|
||||||
{
|
|
||||||
if (do_command(net))
|
|
||||||
return ER_OUT_OF_RESOURCES;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -103,10 +129,10 @@ int Show_instances::execute(struct st_net *net, ulong connection_id)
|
|||||||
|
|
||||||
int Flush_instances::execute(struct st_net *net, ulong connection_id)
|
int Flush_instances::execute(struct st_net *net, ulong connection_id)
|
||||||
{
|
{
|
||||||
if (instance_map->flush_instances())
|
if (instance_map->flush_instances() ||
|
||||||
|
net_send_ok(net, connection_id, NULL))
|
||||||
return ER_OUT_OF_RESOURCES;
|
return ER_OUT_OF_RESOURCES;
|
||||||
|
|
||||||
net_send_ok(net, connection_id);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,11 +145,9 @@ Show_instance_status::Show_instance_status(Instance_map *instance_map_arg,
|
|||||||
{
|
{
|
||||||
Instance *instance;
|
Instance *instance;
|
||||||
|
|
||||||
/* we make a search here, since we don't want t store the name */
|
/* we make a search here, since we don't want to store the name */
|
||||||
if ((instance= instance_map->find(name, len)))
|
if ((instance= instance_map->find(name, len)))
|
||||||
{
|
|
||||||
instance_name= instance->options.instance_name;
|
instance_name= instance->options.instance_name;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
instance_name= NULL;
|
instance_name= NULL;
|
||||||
}
|
}
|
||||||
@ -143,8 +167,8 @@ Show_instance_status::Show_instance_status(Instance_map *instance_map_arg,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
int Show_instance_status::do_command(struct st_net *net,
|
int Show_instance_status::execute(struct st_net *net,
|
||||||
const char *instance_name)
|
ulong connection_id)
|
||||||
{
|
{
|
||||||
enum { MAX_VERSION_LENGTH= 40 };
|
enum { MAX_VERSION_LENGTH= 40 };
|
||||||
Buffer send_buff; /* buffer for packets */
|
Buffer send_buff; /* buffer for packets */
|
||||||
@ -153,14 +177,17 @@ int Show_instance_status::do_command(struct st_net *net,
|
|||||||
NAME_WITH_LENGTH name_field, status_field, version_field;
|
NAME_WITH_LENGTH name_field, status_field, version_field;
|
||||||
uint position=0;
|
uint position=0;
|
||||||
|
|
||||||
|
if (!instance_name)
|
||||||
|
return ER_BAD_INSTANCE_NAME;
|
||||||
|
|
||||||
/* create list of the fileds to be passed to send_fields */
|
/* create list of the fileds to be passed to send_fields */
|
||||||
name_field.name= (char *) "instance_name";
|
name_field.name= (char*) "instance_name";
|
||||||
name_field.length= 20;
|
name_field.length= DEFAULT_FIELD_LENGTH;
|
||||||
name.data= &name_field;
|
name.data= &name_field;
|
||||||
status_field.name= (char *) "status";
|
status_field.name= (char*) "status";
|
||||||
status_field.length= 20;
|
status_field.length= DEFAULT_FIELD_LENGTH;
|
||||||
status.data= &status_field;
|
status.data= &status_field;
|
||||||
version_field.name= (char *) "version";
|
version_field.name= (char*) "version";
|
||||||
version_field.length= MAX_VERSION_LENGTH;
|
version_field.length= MAX_VERSION_LENGTH;
|
||||||
version.data= &version_field;
|
version.data= &version_field;
|
||||||
field_list= list_add(NULL, &version);
|
field_list= list_add(NULL, &version);
|
||||||
@ -172,18 +199,18 @@ int Show_instance_status::do_command(struct st_net *net,
|
|||||||
{
|
{
|
||||||
Instance *instance;
|
Instance *instance;
|
||||||
|
|
||||||
store_to_string(&send_buff, (char *) instance_name, &position);
|
store_to_string(&send_buff, (char*) instance_name, &position);
|
||||||
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
|
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
|
||||||
goto err;
|
goto err;
|
||||||
if (instance->is_running())
|
if (instance->is_running())
|
||||||
{
|
{
|
||||||
store_to_string(&send_buff, (char *) "online", &position);
|
store_to_string(&send_buff, (char*) "online", &position);
|
||||||
store_to_string(&send_buff, "unknown", &position);
|
store_to_string(&send_buff, "unknown", &position);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
store_to_string(&send_buff, (char *) "offline", &position);
|
store_to_string(&send_buff, (char*) "offline", &position);
|
||||||
store_to_string(&send_buff, (char *) "unknown", &position);
|
store_to_string(&send_buff, (char*) "unknown", &position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -192,28 +219,13 @@ int Show_instance_status::do_command(struct st_net *net,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_eof(net);
|
if (send_eof(net) || net_flush(net))
|
||||||
net_flush(net);
|
goto err;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return 1;
|
return ER_OUT_OF_RESOURCES;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int Show_instance_status::execute(struct st_net *net, ulong connection_id)
|
|
||||||
{
|
|
||||||
if ((instance_name))
|
|
||||||
{
|
|
||||||
if (do_command(net, instance_name))
|
|
||||||
return ER_OUT_OF_RESOURCES;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ER_BAD_INSTANCE_NAME;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -225,32 +237,31 @@ Show_instance_options::Show_instance_options(Instance_map *instance_map_arg,
|
|||||||
{
|
{
|
||||||
Instance *instance;
|
Instance *instance;
|
||||||
|
|
||||||
/* we make a search here, since we don't want t store the name */
|
/* we make a search here, since we don't want to store the name */
|
||||||
if ((instance= instance_map->find(name, len)))
|
if ((instance= instance_map->find(name, len)))
|
||||||
{
|
|
||||||
instance_name= instance->options.instance_name;
|
instance_name= instance->options.instance_name;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
instance_name= NULL;
|
instance_name= NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Show_instance_options::do_command(struct st_net *net,
|
int Show_instance_options::execute(struct st_net *net, ulong connection_id)
|
||||||
const char *instance_name)
|
|
||||||
{
|
{
|
||||||
enum { MAX_VERSION_LENGTH= 40 };
|
|
||||||
Buffer send_buff; /* buffer for packets */
|
Buffer send_buff; /* buffer for packets */
|
||||||
LIST name, option;
|
LIST name, option;
|
||||||
LIST *field_list;
|
LIST *field_list;
|
||||||
NAME_WITH_LENGTH name_field, option_field;
|
NAME_WITH_LENGTH name_field, option_field;
|
||||||
uint position=0;
|
uint position=0;
|
||||||
|
|
||||||
|
if (!instance_name)
|
||||||
|
return ER_BAD_INSTANCE_NAME;
|
||||||
|
|
||||||
/* create list of the fileds to be passed to send_fields */
|
/* create list of the fileds to be passed to send_fields */
|
||||||
name_field.name= (char *) "option_name";
|
name_field.name= (char*) "option_name";
|
||||||
name_field.length= 20;
|
name_field.length= DEFAULT_FIELD_LENGTH;
|
||||||
name.data= &name_field;
|
name.data= &name_field;
|
||||||
option_field.name= (char *) "value";
|
option_field.name= (char*) "value";
|
||||||
option_field.length= 20;
|
option_field.length= DEFAULT_FIELD_LENGTH;
|
||||||
option.data= &option_field;
|
option.data= &option_field;
|
||||||
field_list= list_add(NULL, &option);
|
field_list= list_add(NULL, &option);
|
||||||
field_list= list_add(field_list, &name);
|
field_list= list_add(field_list, &name);
|
||||||
@ -262,16 +273,16 @@ int Show_instance_options::do_command(struct st_net *net,
|
|||||||
|
|
||||||
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
|
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
|
||||||
goto err;
|
goto err;
|
||||||
store_to_string(&send_buff, (char *) "instance_name", &position);
|
store_to_string(&send_buff, (char*) "instance_name", &position);
|
||||||
store_to_string(&send_buff, (char *) instance_name, &position);
|
store_to_string(&send_buff, (char*) instance_name, &position);
|
||||||
if (my_net_write(net, send_buff.buffer, (uint) position))
|
if (my_net_write(net, send_buff.buffer, (uint) position))
|
||||||
goto err;
|
goto err;
|
||||||
if ((instance->options.mysqld_path))
|
if ((instance->options.mysqld_path))
|
||||||
{
|
{
|
||||||
position= 0;
|
position= 0;
|
||||||
store_to_string(&send_buff, (char *) "mysqld-path", &position);
|
store_to_string(&send_buff, (char*) "mysqld-path", &position);
|
||||||
store_to_string(&send_buff,
|
store_to_string(&send_buff,
|
||||||
(char *) instance->options.mysqld_path,
|
(char*) instance->options.mysqld_path,
|
||||||
&position);
|
&position);
|
||||||
if (send_buff.is_error() ||
|
if (send_buff.is_error() ||
|
||||||
my_net_write(net, send_buff.buffer, (uint) position))
|
my_net_write(net, send_buff.buffer, (uint) position))
|
||||||
@ -281,7 +292,7 @@ int Show_instance_options::do_command(struct st_net *net,
|
|||||||
if ((instance->options.nonguarded))
|
if ((instance->options.nonguarded))
|
||||||
{
|
{
|
||||||
position= 0;
|
position= 0;
|
||||||
store_to_string(&send_buff, (char *) "nonguarded", &position);
|
store_to_string(&send_buff, (char*) "nonguarded", &position);
|
||||||
store_to_string(&send_buff, "", &position);
|
store_to_string(&send_buff, "", &position);
|
||||||
if (send_buff.is_error() ||
|
if (send_buff.is_error() ||
|
||||||
my_net_write(net, send_buff.buffer, (uint) position))
|
my_net_write(net, send_buff.buffer, (uint) position))
|
||||||
@ -305,7 +316,8 @@ int Show_instance_options::do_command(struct st_net *net,
|
|||||||
/* join name and the value into the same option again */
|
/* join name and the value into the same option again */
|
||||||
*option_value= '=';
|
*option_value= '=';
|
||||||
}
|
}
|
||||||
else store_to_string(&send_buff, tmp_option + 2, &position);
|
else
|
||||||
|
store_to_string(&send_buff, tmp_option + 2, &position);
|
||||||
|
|
||||||
if (send_buff.is_error() ||
|
if (send_buff.is_error() ||
|
||||||
my_net_write(net, send_buff.buffer, (uint) position))
|
my_net_write(net, send_buff.buffer, (uint) position))
|
||||||
@ -313,28 +325,13 @@ int Show_instance_options::do_command(struct st_net *net,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
send_eof(net);
|
if (send_eof(net) || net_flush(net))
|
||||||
net_flush(net);
|
goto err;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return 1;
|
return ER_OUT_OF_RESOURCES;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int Show_instance_options::execute(struct st_net *net, ulong connection_id)
|
|
||||||
{
|
|
||||||
if ((instance_name))
|
|
||||||
{
|
|
||||||
if (do_command(net, instance_name))
|
|
||||||
return ER_OUT_OF_RESOURCES;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ER_BAD_INSTANCE_NAME;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -344,7 +341,7 @@ Start_instance::Start_instance(Instance_map *instance_map_arg,
|
|||||||
const char *name, uint len)
|
const char *name, uint len)
|
||||||
:Command(instance_map_arg)
|
:Command(instance_map_arg)
|
||||||
{
|
{
|
||||||
/* we make a search here, since we don't want t store the name */
|
/* we make a search here, since we don't want to store the name */
|
||||||
if ((instance= instance_map->find(name, len)))
|
if ((instance= instance_map->find(name, len)))
|
||||||
instance_name= instance->options.instance_name;
|
instance_name= instance->options.instance_name;
|
||||||
}
|
}
|
||||||
@ -354,9 +351,7 @@ int Start_instance::execute(struct st_net *net, ulong connection_id)
|
|||||||
{
|
{
|
||||||
uint err_code;
|
uint err_code;
|
||||||
if (instance == 0)
|
if (instance == 0)
|
||||||
{
|
|
||||||
return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
|
return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((err_code= instance->start()))
|
if ((err_code= instance->start()))
|
||||||
@ -365,19 +360,408 @@ int Start_instance::execute(struct st_net *net, ulong connection_id)
|
|||||||
if (!(instance->options.nonguarded))
|
if (!(instance->options.nonguarded))
|
||||||
instance_map->guardian->guard(instance);
|
instance_map->guardian->guard(instance);
|
||||||
|
|
||||||
net_send_ok(net, connection_id);
|
net_send_ok(net, connection_id, "Instance started");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* implementation for Show_instance_log: */
|
||||||
|
|
||||||
|
Show_instance_log::Show_instance_log(Instance_map *instance_map_arg,
|
||||||
|
const char *name, uint len,
|
||||||
|
Log_type log_type_arg,
|
||||||
|
const char *size_arg,
|
||||||
|
const char *offset_arg)
|
||||||
|
:Command(instance_map_arg)
|
||||||
|
{
|
||||||
|
Instance *instance;
|
||||||
|
|
||||||
|
if (offset_arg != NULL)
|
||||||
|
offset= atoi(offset_arg);
|
||||||
|
else
|
||||||
|
offset= 0;
|
||||||
|
size= atoi(size_arg);
|
||||||
|
log_type= log_type_arg;
|
||||||
|
|
||||||
|
/* we make a search here, since we don't want to store the name */
|
||||||
|
if ((instance= instance_map->find(name, len)))
|
||||||
|
instance_name= instance->options.instance_name;
|
||||||
|
else
|
||||||
|
instance_name= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Open the logfile, read requested part of the log and send the info
|
||||||
|
to the client.
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
Show_instance_log::execute()
|
||||||
|
net The network connection to the client.
|
||||||
|
connection_id Client connection ID
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
|
||||||
|
Send a table with the content of the log requested. The function also
|
||||||
|
deals with errro handling, to be verbose.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
ER_OFFSET_ERROR We were requested to read negative number of bytes
|
||||||
|
from the log
|
||||||
|
ER_NO_SUCH_LOG The kind log being read is not enabled in the instance
|
||||||
|
ER_GUESS_LOGFILE IM wasn't able to figure out the log placement, while
|
||||||
|
it is enabled. Probably user should specify the path
|
||||||
|
to the logfile explicitly.
|
||||||
|
ER_OPEN_LOGFILE Cannot open the logfile
|
||||||
|
ER_READ_FILE Cannot read the logfile
|
||||||
|
ER_OUT_OF_RESOURCES We weren't able to allocate some resources
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Show_instance_log::execute(struct st_net *net, ulong connection_id)
|
||||||
|
{
|
||||||
|
Buffer send_buff; /* buffer for packets */
|
||||||
|
LIST name;
|
||||||
|
LIST *field_list;
|
||||||
|
NAME_WITH_LENGTH name_field;
|
||||||
|
uint position= 0;
|
||||||
|
|
||||||
|
/* create list of the fileds to be passed to send_fields */
|
||||||
|
name_field.name= (char*) "Log";
|
||||||
|
name_field.length= DEFAULT_FIELD_LENGTH;
|
||||||
|
name.data= &name_field;
|
||||||
|
field_list= list_add(NULL, &name);
|
||||||
|
|
||||||
|
if (!instance_name)
|
||||||
|
return ER_BAD_INSTANCE_NAME;
|
||||||
|
|
||||||
|
/* cannot read negative number of bytes */
|
||||||
|
if (offset > size)
|
||||||
|
return ER_OFFSET_ERROR;
|
||||||
|
|
||||||
|
send_fields(net, field_list);
|
||||||
|
|
||||||
|
{
|
||||||
|
Instance *instance;
|
||||||
|
const char *logpath;
|
||||||
|
File fd;
|
||||||
|
|
||||||
|
if ((instance= instance_map->find(instance_name,
|
||||||
|
strlen(instance_name))) == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
logpath= instance->options.logs[log_type];
|
||||||
|
|
||||||
|
/* Instance has no such log */
|
||||||
|
if (logpath == NULL)
|
||||||
|
return ER_NO_SUCH_LOG;
|
||||||
|
else if (*logpath == '\0')
|
||||||
|
return ER_GUESS_LOGFILE;
|
||||||
|
|
||||||
|
|
||||||
|
if ((fd= my_open(logpath, O_RDONLY | O_BINARY, MYF(MY_WME))) >= 0)
|
||||||
|
{
|
||||||
|
size_t buff_size;
|
||||||
|
int read_len;
|
||||||
|
/* calculate buffer size */
|
||||||
|
struct stat file_stat;
|
||||||
|
|
||||||
|
/* my_fstat doesn't use the flag parameter */
|
||||||
|
if (my_fstat(fd, &file_stat, MYF(0)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
buff_size= (size - offset);
|
||||||
|
|
||||||
|
/* read in one chunk */
|
||||||
|
read_len= my_seek(fd, file_stat.st_size - size, MY_SEEK_SET, MYF(0));
|
||||||
|
|
||||||
|
char *bf= (char*) malloc(sizeof(char)*buff_size);
|
||||||
|
if ((read_len= my_read(fd, bf, buff_size, MYF(0))) < 0)
|
||||||
|
return ER_READ_FILE;
|
||||||
|
store_to_string(&send_buff, (char*) bf, &position, read_len);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ER_OPEN_LOGFILE;
|
||||||
|
|
||||||
|
if (my_net_write(net, send_buff.buffer, (uint) position))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send_eof(net) || net_flush(net))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return ER_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* implementation for Show_instance_log_files: */
|
||||||
|
|
||||||
|
Show_instance_log_files::Show_instance_log_files
|
||||||
|
(Instance_map *instance_map_arg, const char *name, uint len)
|
||||||
|
:Command(instance_map_arg)
|
||||||
|
{
|
||||||
|
Instance *instance;
|
||||||
|
|
||||||
|
/* we make a search here, since we don't want to store the name */
|
||||||
|
if ((instance= instance_map->find(name, len)))
|
||||||
|
instance_name= instance->options.instance_name;
|
||||||
|
else
|
||||||
|
instance_name= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
The method sends a table with a list of log files
|
||||||
|
used by the instance.
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
Show_instance_log_files::execute()
|
||||||
|
net The network connection to the client.
|
||||||
|
connection_id The ID of the client connection
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
ER_BAD_INSTANCE_NAME The instance name specified is not valid
|
||||||
|
ER_OUT_OF_RESOURCES some error occured
|
||||||
|
0 - ok
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Show_instance_log_files::execute(struct st_net *net, ulong connection_id)
|
||||||
|
{
|
||||||
|
Buffer send_buff; /* buffer for packets */
|
||||||
|
LIST name, path, size;
|
||||||
|
LIST *field_list;
|
||||||
|
NAME_WITH_LENGTH name_field, path_field, size_field;
|
||||||
|
uint position= 0;
|
||||||
|
|
||||||
|
if (!instance_name)
|
||||||
|
return ER_BAD_INSTANCE_NAME;
|
||||||
|
|
||||||
|
/* create list of the fileds to be passed to send_fields */
|
||||||
|
name_field.name= (char*) "Logfile";
|
||||||
|
name_field.length= DEFAULT_FIELD_LENGTH;
|
||||||
|
name.data= &name_field;
|
||||||
|
path_field.name= (char*) "Path";
|
||||||
|
path_field.length= DEFAULT_FIELD_LENGTH;
|
||||||
|
path.data= &path_field;
|
||||||
|
size_field.name= (char*) "Filesize";
|
||||||
|
size_field.length= DEFAULT_FIELD_LENGTH;
|
||||||
|
size.data= &size_field;
|
||||||
|
field_list= list_add(NULL, &size);
|
||||||
|
field_list= list_add(field_list, &path);
|
||||||
|
field_list= list_add(field_list, &name);
|
||||||
|
|
||||||
|
send_fields(net, field_list);
|
||||||
|
|
||||||
|
Instance *instance;
|
||||||
|
|
||||||
|
if ((instance= instance_map->
|
||||||
|
find(instance_name, strlen(instance_name))) == NULL)
|
||||||
|
goto err;
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We have alike structure in instance_options.cc. We use such to be able
|
||||||
|
to loop through the options, which we need to handle in some common way.
|
||||||
|
*/
|
||||||
|
struct log_files_st
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
const char *value;
|
||||||
|
} logs[]=
|
||||||
|
{
|
||||||
|
{"ERROR LOG", instance->options.logs[LOG_ERROR]},
|
||||||
|
{"GENERAL LOG", instance->options.logs[LOG_GENERAL]},
|
||||||
|
{"SLOW LOG", instance->options.logs[LOG_SLOW]},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
struct log_files_st *log_files;
|
||||||
|
|
||||||
|
for (log_files= logs; log_files->name; log_files++)
|
||||||
|
{
|
||||||
|
if (log_files->value != NULL)
|
||||||
|
{
|
||||||
|
struct stat file_stat;
|
||||||
|
/*
|
||||||
|
Save some more space for the log file names. In fact all
|
||||||
|
we need is srtlen("GENERAL_LOG") + 1
|
||||||
|
*/
|
||||||
|
enum { LOG_NAME_BUFFER_SIZE= 20 };
|
||||||
|
char buff[LOG_NAME_BUFFER_SIZE];
|
||||||
|
|
||||||
|
position= 0;
|
||||||
|
/* store the type of the log in the send buffer */
|
||||||
|
store_to_string(&send_buff, log_files->name, &position);
|
||||||
|
if (stat(log_files->value, &file_stat))
|
||||||
|
{
|
||||||
|
store_to_string(&send_buff, "", &position);
|
||||||
|
store_to_string(&send_buff, (char*) "0", &position);
|
||||||
|
}
|
||||||
|
else if (S_ISREG(file_stat.st_mode))
|
||||||
|
{
|
||||||
|
store_to_string(&send_buff,
|
||||||
|
(char*) log_files->value,
|
||||||
|
&position);
|
||||||
|
int10_to_str(file_stat.st_size, buff, 10);
|
||||||
|
store_to_string(&send_buff, (char*) buff, &position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_net_write(net, send_buff.buffer, (uint) position))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send_eof(net) || net_flush(net))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return ER_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* implementation for SET instance_name.option=option_value: */
|
||||||
|
|
||||||
|
Set_option::Set_option(Instance_map *instance_map_arg,
|
||||||
|
const char *name, uint len,
|
||||||
|
const char *option_arg, uint option_len_arg,
|
||||||
|
const char *option_value_arg, uint option_value_len_arg)
|
||||||
|
:Command(instance_map_arg)
|
||||||
|
{
|
||||||
|
Instance *instance;
|
||||||
|
|
||||||
|
/* we make a search here, since we don't want to store the name */
|
||||||
|
if ((instance= instance_map->find(name, len)))
|
||||||
|
{
|
||||||
|
instance_name= instance->options.instance_name;
|
||||||
|
/* add prefix for add_option */
|
||||||
|
if ((option_len_arg < MAX_OPTION_LEN - 1) ||
|
||||||
|
(option_value_len_arg < MAX_OPTION_LEN - 1))
|
||||||
|
{
|
||||||
|
strmake(option, option_arg, option_len_arg);
|
||||||
|
strmake(option_value, option_value_arg, option_value_len_arg);
|
||||||
|
/* strncpy(option, option_arg, option_len_arg);
|
||||||
|
option[option_len_arg]= 0;
|
||||||
|
strncpy(option_value, option_value_arg, option_value_len_arg);
|
||||||
|
option_value[option_value_len_arg]= 0; */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
option[0]= 0;
|
||||||
|
option_value[0]= 0;
|
||||||
|
}
|
||||||
|
instance_name_len= len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
instance_name= NULL;
|
||||||
|
instance_name_len= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
The method sends a table with a list of log files
|
||||||
|
used by the instance.
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
Set_option::correct_file()
|
||||||
|
skip Skip the option, being searched while writing the result file.
|
||||||
|
That is, to delete it.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
|
||||||
|
Correct the option file. The "skip" option is used to remove the found
|
||||||
|
option.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
ER_BAD_INSTANCE_NAME The instance name specified is not valid
|
||||||
|
ER_ACCESS_OPTION_FILE Cannot access the option file
|
||||||
|
0 - ok
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Set_option::correct_file(int skip)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error= my_correct_defaults_file("/etc/my.cnf", option,
|
||||||
|
option_value, instance_name, skip);
|
||||||
|
if (error > 0)
|
||||||
|
return ER_OUT_OF_RESOURCES;
|
||||||
|
else if (error < 0)
|
||||||
|
return ER_ACCESS_OPTION_FILE;
|
||||||
|
|
||||||
|
/* everything was fine */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
The method sets an option in the the default config file (/etc/my.cnf).
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
Set_option::do_command()
|
||||||
|
net The network connection to the client.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - ok
|
||||||
|
1 - error occured
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
int Set_option::do_command(struct st_net *net)
|
||||||
|
{
|
||||||
|
int error= 0;
|
||||||
|
|
||||||
|
/* we must hold the instance_map mutex while changing config file */
|
||||||
|
instance_map->lock();
|
||||||
|
error= correct_file(FALSE);
|
||||||
|
instance_map->unlock();
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Set_option::execute(struct st_net *net, ulong connection_id)
|
||||||
|
{
|
||||||
|
if (instance_name != NULL)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
|
||||||
|
val= do_command(net);
|
||||||
|
if (val == 0)
|
||||||
|
{
|
||||||
|
net_send_ok(net, connection_id, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ER_BAD_INSTANCE_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* the only function from Unset_option we need to Implement */
|
||||||
|
|
||||||
|
int Unset_option::do_command(struct st_net *net)
|
||||||
|
{
|
||||||
|
return correct_file(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Implementation for Stop_instance: */
|
/* Implementation for Stop_instance: */
|
||||||
|
|
||||||
Stop_instance::Stop_instance(Instance_map *instance_map_arg,
|
Stop_instance::Stop_instance(Instance_map *instance_map_arg,
|
||||||
const char *name, uint len)
|
const char *name, uint len)
|
||||||
:Command(instance_map_arg)
|
:Command(instance_map_arg)
|
||||||
{
|
{
|
||||||
/* we make a search here, since we don't want t store the name */
|
/* we make a search here, since we don't want to store the name */
|
||||||
if ((instance= instance_map->find(name, len)))
|
if ((instance= instance_map->find(name, len)))
|
||||||
instance_name= instance->options.instance_name;
|
instance_name= instance->options.instance_name;
|
||||||
}
|
}
|
||||||
@ -388,9 +772,7 @@ int Stop_instance::execute(struct st_net *net, ulong connection_id)
|
|||||||
uint err_code;
|
uint err_code;
|
||||||
|
|
||||||
if (instance == 0)
|
if (instance == 0)
|
||||||
{
|
|
||||||
return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
|
return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(instance->options.nonguarded))
|
if (!(instance->options.nonguarded))
|
||||||
@ -398,7 +780,7 @@ int Stop_instance::execute(struct st_net *net, ulong connection_id)
|
|||||||
stop_guard(instance);
|
stop_guard(instance);
|
||||||
if ((err_code= instance->stop()))
|
if ((err_code= instance->stop()))
|
||||||
return err_code;
|
return err_code;
|
||||||
net_send_ok(net, connection_id);
|
net_send_ok(net, connection_id, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Print all instances of this instance manager.
|
Print all instances of this instance manager.
|
||||||
@ -30,7 +31,6 @@ public:
|
|||||||
Show_instances(Instance_map *instance_map_arg): Command(instance_map_arg)
|
Show_instances(Instance_map *instance_map_arg): Command(instance_map_arg)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int do_command(struct st_net *net);
|
|
||||||
int execute(struct st_net *net, ulong connection_id);
|
int execute(struct st_net *net, ulong connection_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,8 +59,8 @@ class Show_instance_status : public Command
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Show_instance_status(Instance_map *instance_map_arg, const char *name, uint len);
|
Show_instance_status(Instance_map *instance_map_arg,
|
||||||
int do_command(struct st_net *net, const char *instance_name);
|
const char *name, uint len);
|
||||||
int execute(struct st_net *net, ulong connection_id);
|
int execute(struct st_net *net, ulong connection_id);
|
||||||
const char *instance_name;
|
const char *instance_name;
|
||||||
};
|
};
|
||||||
@ -75,10 +75,10 @@ class Show_instance_options : public Command
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Show_instance_options(Instance_map *instance_map_arg, const char *name, uint len);
|
Show_instance_options(Instance_map *instance_map_arg,
|
||||||
|
const char *name, uint len);
|
||||||
|
|
||||||
int execute(struct st_net *net, ulong connection_id);
|
int execute(struct st_net *net, ulong connection_id);
|
||||||
int do_command(struct st_net *net, const char *instance_name);
|
|
||||||
const char *instance_name;
|
const char *instance_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,10 +116,48 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Syntax error command. This command is issued if parser reported a syntax error.
|
Print requested part of the log
|
||||||
We need it to distinguish the parse error and the situation when parser internal
|
Grammar:
|
||||||
error occured. E.g. parsing failed because we hadn't had enought memory. In the
|
SHOW <instance_name> log {ERROR | SLOW | GENERAL} size[, offset_from_end]
|
||||||
latter case parse_command() should return an error.
|
*/
|
||||||
|
|
||||||
|
class Show_instance_log : public Command
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Show_instance_log(Instance_map *instance_map_arg, const char *name,
|
||||||
|
uint len, Log_type log_type_arg, const char *size_arg,
|
||||||
|
const char *offset_arg);
|
||||||
|
int execute(struct st_net *net, ulong connection_id);
|
||||||
|
Log_type log_type;
|
||||||
|
const char *instance_name;
|
||||||
|
uint size;
|
||||||
|
uint offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Shows the list of the log files, used by an instance.
|
||||||
|
Grammar: SHOW <instance_name> LOG FILES
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Show_instance_log_files : public Command
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Show_instance_log_files(Instance_map *instance_map_arg,
|
||||||
|
const char *name, uint len);
|
||||||
|
int execute(struct st_net *net, ulong connection_id);
|
||||||
|
const char *instance_name;
|
||||||
|
const char *option;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Syntax error command. This command is issued if parser reported a syntax
|
||||||
|
error. We need it to distinguish the parse error and the situation when
|
||||||
|
parser internal error occured. E.g. parsing failed because we hadn't had
|
||||||
|
enought memory. In the latter case parse_command() should return an error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Syntax_error : public Command
|
class Syntax_error : public Command
|
||||||
@ -128,4 +166,50 @@ public:
|
|||||||
int execute(struct st_net *net, ulong connection_id);
|
int execute(struct st_net *net, ulong connection_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set an option for the instance.
|
||||||
|
Grammar: SET instance_name.option=option_value
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Set_option : public Command
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Set_option(Instance_map *instance_map_arg, const char *name, uint len,
|
||||||
|
const char *option_arg, uint option_len,
|
||||||
|
const char *option_value_arg, uint option_value_len);
|
||||||
|
/*
|
||||||
|
the following function is virtual to let Unset_option to use
|
||||||
|
*/
|
||||||
|
virtual int do_command(struct st_net *net);
|
||||||
|
int execute(struct st_net *net, ulong connection_id);
|
||||||
|
protected:
|
||||||
|
int correct_file(int skip);
|
||||||
|
public:
|
||||||
|
const char *instance_name;
|
||||||
|
uint instance_name_len;
|
||||||
|
/* buffer for the option */
|
||||||
|
enum { MAX_OPTION_LEN= 1024 };
|
||||||
|
char option[MAX_OPTION_LEN];
|
||||||
|
char option_value[MAX_OPTION_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove option of the instance from config file
|
||||||
|
Grammar: UNSET instance_name.option
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Unset_option: public Set_option
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Unset_option(Instance_map *instance_map_arg, const char *name, uint len,
|
||||||
|
const char *option_arg, uint option_len,
|
||||||
|
const char *option_value_arg, uint option_value_len):
|
||||||
|
Set_option(instance_map_arg, name, len, option_arg, option_len,
|
||||||
|
option_value_arg, option_value_len)
|
||||||
|
{}
|
||||||
|
int do_command(struct st_net *net);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H */
|
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H */
|
||||||
|
@ -16,40 +16,85 @@
|
|||||||
|
|
||||||
#include "factory.h"
|
#include "factory.h"
|
||||||
|
|
||||||
|
|
||||||
Show_instances *Command_factory::new_Show_instances()
|
Show_instances *Command_factory::new_Show_instances()
|
||||||
{
|
{
|
||||||
return new Show_instances(&instance_map);
|
return new Show_instances(&instance_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Flush_instances *Command_factory::new_Flush_instances()
|
Flush_instances *Command_factory::new_Flush_instances()
|
||||||
{
|
{
|
||||||
return new Flush_instances(&instance_map);
|
return new Flush_instances(&instance_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Show_instance_status *Command_factory::
|
Show_instance_status *Command_factory::
|
||||||
new_Show_instance_status(const char *name, uint len)
|
new_Show_instance_status(const char *name, uint len)
|
||||||
{
|
{
|
||||||
return new Show_instance_status(&instance_map, name, len);
|
return new Show_instance_status(&instance_map, name, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Show_instance_options *Command_factory::
|
Show_instance_options *Command_factory::
|
||||||
new_Show_instance_options(const char *name, uint len)
|
new_Show_instance_options(const char *name, uint len)
|
||||||
{
|
{
|
||||||
return new Show_instance_options(&instance_map, name, len);
|
return new Show_instance_options(&instance_map, name, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Start_instance *Command_factory::
|
Start_instance *Command_factory::
|
||||||
new_Start_instance(const char *name, uint len)
|
new_Start_instance(const char *name, uint len)
|
||||||
{
|
{
|
||||||
return new Start_instance(&instance_map, name, len);
|
return new Start_instance(&instance_map, name, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Stop_instance *Command_factory::new_Stop_instance(const char *name, uint len)
|
Stop_instance *Command_factory::new_Stop_instance(const char *name, uint len)
|
||||||
{
|
{
|
||||||
return new Stop_instance(&instance_map, name, len);
|
return new Stop_instance(&instance_map, name, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Syntax_error *Command_factory::new_Syntax_error()
|
Syntax_error *Command_factory::new_Syntax_error()
|
||||||
{
|
{
|
||||||
return new Syntax_error();
|
return new Syntax_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Set_option *Command_factory::
|
||||||
|
new_Set_option(const char* name, uint len,
|
||||||
|
const char *option_arg, uint option_len,
|
||||||
|
const char *option_value_arg, uint option_value_len)
|
||||||
|
{
|
||||||
|
return new Set_option(&instance_map, name, len, option_arg,
|
||||||
|
option_len, option_value_arg, option_value_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Unset_option *Command_factory::
|
||||||
|
new_Unset_option(const char* name, uint len,
|
||||||
|
const char *option_arg, uint option_len,
|
||||||
|
const char *option_value_arg, uint option_value_len)
|
||||||
|
{
|
||||||
|
return new Unset_option(&instance_map, name, len, option_arg,
|
||||||
|
option_len, option_value_arg, option_value_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Show_instance_log *Command_factory::
|
||||||
|
new_Show_instance_log(const char *name, uint len,
|
||||||
|
Log_type log_type_arg,
|
||||||
|
const char *size, const char *offset)
|
||||||
|
{
|
||||||
|
return new Show_instance_log(&instance_map, name, len,
|
||||||
|
log_type_arg, size, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Show_instance_log_files *Command_factory::
|
||||||
|
new_Show_instance_log_files(const char *name, uint len)
|
||||||
|
{
|
||||||
|
return new Show_instance_log_files(&instance_map, name, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
Http_command_factory e.t.c. Also see comment in the instance_map.cc
|
Http_command_factory e.t.c. Also see comment in the instance_map.cc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class Show_instances;
|
||||||
|
|
||||||
class Command_factory
|
class Command_factory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -33,12 +35,26 @@ public:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
Show_instances *new_Show_instances ();
|
Show_instances *new_Show_instances ();
|
||||||
|
Flush_instances *new_Flush_instances ();
|
||||||
|
Syntax_error *new_Syntax_error ();
|
||||||
Show_instance_status *new_Show_instance_status (const char *name, uint len);
|
Show_instance_status *new_Show_instance_status (const char *name, uint len);
|
||||||
Show_instance_options *new_Show_instance_options (const char *name, uint len);
|
Show_instance_options *new_Show_instance_options (const char *name, uint len);
|
||||||
Start_instance *new_Start_instance (const char *name, uint len);
|
Start_instance *new_Start_instance (const char *name, uint len);
|
||||||
Stop_instance *new_Stop_instance (const char *name, uint len);
|
Stop_instance *new_Stop_instance (const char *name, uint len);
|
||||||
Flush_instances *new_Flush_instances ();
|
Show_instance_log *new_Show_instance_log (const char *name, uint len,
|
||||||
Syntax_error *new_Syntax_error ();
|
Log_type log_type_arg,
|
||||||
|
const char *size,
|
||||||
|
const char *offset);
|
||||||
|
Set_option *new_Set_option (const char *name, uint len,
|
||||||
|
const char *option_arg, uint option_len,
|
||||||
|
const char *option_value_arg,
|
||||||
|
uint option_value_len);
|
||||||
|
Unset_option *new_Unset_option (const char *name, uint len,
|
||||||
|
const char *option_arg, uint option_len,
|
||||||
|
const char *option_value_arg,
|
||||||
|
uint option_value_len);
|
||||||
|
Show_instance_log_files *new_Show_instance_log_files (const char *name,
|
||||||
|
uint len);
|
||||||
|
|
||||||
Instance_map &instance_map;
|
Instance_map &instance_map;
|
||||||
};
|
};
|
||||||
|
@ -315,7 +315,7 @@ int Guardian_thread::guard(Instance *instance, bool nolock)
|
|||||||
content->restart_counter= 0;
|
content->restart_counter= 0;
|
||||||
content->crash_moment= 0;
|
content->crash_moment= 0;
|
||||||
content->state= NOT_STARTED;
|
content->state= NOT_STARTED;
|
||||||
node->data= (void *) content;
|
node->data= (void*) content;
|
||||||
|
|
||||||
if (nolock)
|
if (nolock)
|
||||||
guarded_instances= list_add(guarded_instances, node);
|
guarded_instances= list_add(guarded_instances, node);
|
||||||
|
@ -304,12 +304,11 @@ void Instance::kill_instance(int signum)
|
|||||||
*/
|
*/
|
||||||
if (!kill(pid, signum))
|
if (!kill(pid, signum))
|
||||||
options.unlink_pidfile();
|
options.unlink_pidfile();
|
||||||
else
|
else if (signum == SIGKILL) /* really killed instance with SIGKILL */
|
||||||
if (signum == SIGKILL) /* really killed instance with SIGKILL */
|
log_error("The instance %s is being stopped forsibly. Normally \
|
||||||
log_error("The instance %s is being stopped forsibly. Normally \
|
it should not happed. Probably the instance has been \
|
||||||
it should not happed. Probably the instance has been \
|
hanging. You should also check your IM setup",
|
||||||
hanging. You should also check your IM setup",
|
options.instance_name);
|
||||||
options.instance_name);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ int Instance_map::load()
|
|||||||
argv_options[1]= '\0';
|
argv_options[1]= '\0';
|
||||||
|
|
||||||
if (my_search_option_files("my", &argc, (char ***) &argv, &args_used,
|
if (my_search_option_files("my", &argc, (char ***) &argv, &args_used,
|
||||||
process_option, (void *) this) ||
|
process_option, (void*) this) ||
|
||||||
complete_initialization())
|
complete_initialization())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
#include <mysql.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
|
|
||||||
@ -36,7 +35,7 @@
|
|||||||
get_default_option()
|
get_default_option()
|
||||||
result buffer to put found value
|
result buffer to put found value
|
||||||
result_len buffer size
|
result_len buffer size
|
||||||
oprion_name the name of the option, prefixed with "--"
|
option_name the name of the option, prefixed with "--"
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
|
||||||
@ -47,6 +46,7 @@
|
|||||||
1 - error occured
|
1 - error occured
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
int Instance_options::get_default_option(char *result, size_t result_len,
|
int Instance_options::get_default_option(char *result, size_t result_len,
|
||||||
const char *option_name)
|
const char *option_name)
|
||||||
{
|
{
|
||||||
@ -54,7 +54,7 @@ int Instance_options::get_default_option(char *result, size_t result_len,
|
|||||||
int rc= 1;
|
int rc= 1;
|
||||||
char verbose_option[]= " --no-defaults --verbose --help";
|
char verbose_option[]= " --no-defaults --verbose --help";
|
||||||
|
|
||||||
Buffer cmd(strlen(mysqld_path)+sizeof(verbose_option)+1);
|
Buffer cmd(strlen(mysqld_path) + sizeof(verbose_option) + 1);
|
||||||
if (cmd.get_size()) /* malloc succeeded */
|
if (cmd.get_size()) /* malloc succeeded */
|
||||||
{
|
{
|
||||||
cmd.append(position, mysqld_path, strlen(mysqld_path));
|
cmd.append(position, mysqld_path, strlen(mysqld_path));
|
||||||
@ -76,6 +76,146 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get compiled-in value of default_option
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
get_default_option()
|
||||||
|
result buffer to put found value
|
||||||
|
result_len buffer size
|
||||||
|
option_name the name of the option, prefixed with "--"
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
|
||||||
|
Get compile-in value of requested option from server
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - ok
|
||||||
|
1 - error occured
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Instance_options::fill_log_options()
|
||||||
|
{
|
||||||
|
Buffer buff;
|
||||||
|
uint position= 0;
|
||||||
|
char **tmp_argv= argv;
|
||||||
|
enum { MAX_LOG_OPTION_LENGTH= 256 };
|
||||||
|
char datadir[MAX_LOG_OPTION_LENGTH];
|
||||||
|
char hostname[MAX_LOG_OPTION_LENGTH];
|
||||||
|
uint hostname_length;
|
||||||
|
struct log_files_st
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
uint length;
|
||||||
|
char **value;
|
||||||
|
const char *default_suffix;
|
||||||
|
} logs_st[]=
|
||||||
|
{
|
||||||
|
{"--log-error", 11, &(logs[LOG_ERROR]), ".err"},
|
||||||
|
{"--log", 5, &(logs[LOG_GENERAL]), ".log"},
|
||||||
|
{"--log-slow-queries", 18, &(logs[LOG_SLOW]), "-slow.log"},
|
||||||
|
{NULL, 0, NULL, NULL}
|
||||||
|
};
|
||||||
|
struct log_files_st *log_files;
|
||||||
|
|
||||||
|
/* compute hostname and datadir for the instance */
|
||||||
|
if (mysqld_datadir == NULL)
|
||||||
|
{
|
||||||
|
if (get_default_option(datadir,
|
||||||
|
MAX_LOG_OPTION_LENGTH, "--datadir"))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
else /* below is safe, as --datadir always has a value */
|
||||||
|
strncpy(datadir, strchr(mysqld_datadir, '=') + 1,
|
||||||
|
MAX_LOG_OPTION_LENGTH);
|
||||||
|
|
||||||
|
if (gethostname(hostname,sizeof(hostname)-1) < 0)
|
||||||
|
strmov(hostname, "mysql");
|
||||||
|
|
||||||
|
hostname[MAX_LOG_OPTION_LENGTH - 1]= 0; /* Safety */
|
||||||
|
hostname_length= strlen(hostname);
|
||||||
|
|
||||||
|
|
||||||
|
for (log_files= logs_st; log_files->name; log_files++)
|
||||||
|
{
|
||||||
|
for (int i=0; (argv[i] != 0); i++)
|
||||||
|
{
|
||||||
|
if (!strncmp(argv[i], log_files->name, log_files->length))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
This is really log_files->name option if and only if it is followed
|
||||||
|
by '=', '\0' or space character. This way we can distinguish such
|
||||||
|
options as '--log' and '--log-bin'. This is checked in the following
|
||||||
|
two statements.
|
||||||
|
*/
|
||||||
|
if (argv[i][log_files->length] == '\0' ||
|
||||||
|
my_isspace(default_charset_info, argv[i][log_files->length]))
|
||||||
|
{
|
||||||
|
char full_name[MAX_LOG_OPTION_LENGTH];
|
||||||
|
|
||||||
|
fn_format(full_name, hostname, datadir, "",
|
||||||
|
MY_UNPACK_FILENAME | MY_SAFE_PATH);
|
||||||
|
|
||||||
|
|
||||||
|
if ((MAX_LOG_OPTION_LENGTH - strlen(full_name)) >
|
||||||
|
strlen(log_files->default_suffix))
|
||||||
|
{
|
||||||
|
strcpy(full_name + strlen(full_name),
|
||||||
|
log_files->default_suffix);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If there were specified two identical logfiles options,
|
||||||
|
we would loose some memory in MEM_ROOT here. However
|
||||||
|
this situation is not typical.
|
||||||
|
*/
|
||||||
|
*(log_files->value)= strdup_root(&alloc, full_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[i][log_files->length] == '=')
|
||||||
|
{
|
||||||
|
char full_name[MAX_LOG_OPTION_LENGTH];
|
||||||
|
|
||||||
|
fn_format(full_name, argv[i] +log_files->length + 1,
|
||||||
|
datadir, "", MY_UNPACK_FILENAME | MY_SAFE_PATH);
|
||||||
|
|
||||||
|
if (!(*(log_files->value)=
|
||||||
|
strdup_root(&alloc, full_name)))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the full pid file name with path
|
||||||
|
|
||||||
|
SYNOPSYS
|
||||||
|
get_pid_filaname()
|
||||||
|
result buffer to sotre the pidfile value
|
||||||
|
|
||||||
|
IMPLEMENTATION
|
||||||
|
Get the data directory, then get the pid filename
|
||||||
|
(which is always set for an instance), then load the
|
||||||
|
full path with my_load_path(). It takes into account
|
||||||
|
whether it is already an absolute path or it should be
|
||||||
|
prefixed with the datadir and so on.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - ok
|
||||||
|
1 - error occured
|
||||||
|
*/
|
||||||
|
|
||||||
int Instance_options::get_pid_filename(char *result)
|
int Instance_options::get_pid_filename(char *result)
|
||||||
{
|
{
|
||||||
const char *pid_file= mysqld_pid_file;
|
const char *pid_file= mysqld_pid_file;
|
||||||
@ -190,6 +330,8 @@ int Instance_options::complete_initialization(const char *default_path,
|
|||||||
options_array.elements*sizeof(char*));
|
options_array.elements*sizeof(char*));
|
||||||
argv[filled_default_options + options_array.elements]= 0;
|
argv[filled_default_options + options_array.elements]= 0;
|
||||||
|
|
||||||
|
fill_log_options();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@ -274,7 +416,7 @@ int Instance_options::add_to_argv(const char* option)
|
|||||||
DBUG_ASSERT(filled_default_options < MAX_NUMBER_OF_DEFAULT_OPTIONS);
|
DBUG_ASSERT(filled_default_options < MAX_NUMBER_OF_DEFAULT_OPTIONS);
|
||||||
|
|
||||||
if ((option))
|
if ((option))
|
||||||
argv[filled_default_options++]= (char *) option;
|
argv[filled_default_options++]= (char*) option;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,10 +444,10 @@ int Instance_options::init(const char *instance_name_arg)
|
|||||||
|
|
||||||
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
||||||
|
|
||||||
if (my_init_dynamic_array(&options_array, sizeof(char *), 0, 32))
|
if (my_init_dynamic_array(&options_array, sizeof(char*), 0, 32))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!(instance_name= strmake_root(&alloc, (char *) instance_name_arg,
|
if (!(instance_name= strmake_root(&alloc, (char*) instance_name_arg,
|
||||||
instance_name_len)))
|
instance_name_len)))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <my_global.h>
|
#include <my_global.h>
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma interface
|
#pragma interface
|
||||||
@ -76,9 +77,13 @@ public:
|
|||||||
const char *nonguarded;
|
const char *nonguarded;
|
||||||
const char *shutdown_delay;
|
const char *shutdown_delay;
|
||||||
uint shutdown_delay_val;
|
uint shutdown_delay_val;
|
||||||
|
/* log enums are defined in parse.h */
|
||||||
|
char *logs[3];
|
||||||
|
|
||||||
/* this value is computed and cashed here */
|
/* this value is computed and cashed here */
|
||||||
DYNAMIC_ARRAY options_array;
|
DYNAMIC_ARRAY options_array;
|
||||||
private:
|
private:
|
||||||
|
int fill_log_options();
|
||||||
int add_to_argv(const char *option);
|
int add_to_argv(const char *option);
|
||||||
int get_default_option(char *result, size_t result_len,
|
int get_default_option(char *result, size_t result_len,
|
||||||
const char *option_name);
|
const char *option_name);
|
||||||
|
@ -241,23 +241,20 @@ void Listener_thread::run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (FD_ISSET(ip_socket, &read_fds_arg))
|
||||||
if (FD_ISSET(ip_socket, &read_fds_arg))
|
{
|
||||||
|
int client_fd= accept(ip_socket, 0, 0);
|
||||||
|
/* accept may return -1 (failure or spurious wakeup) */
|
||||||
|
if (client_fd >= 0) // connection established
|
||||||
{
|
{
|
||||||
int client_fd= accept(ip_socket, 0, 0);
|
if (Vio *vio= vio_new(client_fd, VIO_TYPE_TCPIP, 0))
|
||||||
/* accept may return -1 (failure or spurious wakeup) */
|
handle_new_mysql_connection(vio);
|
||||||
if (client_fd >= 0) // connection established
|
else
|
||||||
{
|
{
|
||||||
if (Vio *vio= vio_new(client_fd, VIO_TYPE_TCPIP, 0))
|
shutdown(client_fd, SHUT_RDWR);
|
||||||
{
|
close(client_fd);
|
||||||
handle_new_mysql_connection(vio);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shutdown(client_fd, SHUT_RDWR);
|
|
||||||
close(client_fd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ static inline void log(FILE *file, const char *format, va_list args)
|
|||||||
if (n < 0 || n == sizeof(buff_stack))
|
if (n < 0 || n == sizeof(buff_stack))
|
||||||
{
|
{
|
||||||
int size= sizeof(buff_stack) * 2;
|
int size= sizeof(buff_stack) * 2;
|
||||||
buff_msg= (char *) my_malloc(size, 0);
|
buff_msg= (char*) my_malloc(size, MYF(0));
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (buff_msg == 0)
|
if (buff_msg == 0)
|
||||||
@ -86,16 +86,16 @@ static inline void log(FILE *file, const char *format, va_list args)
|
|||||||
size*= 2;
|
size*= 2;
|
||||||
/* realloc() does unnecessary memcpy */
|
/* realloc() does unnecessary memcpy */
|
||||||
my_free(buff_msg, 0);
|
my_free(buff_msg, 0);
|
||||||
buff_msg= (char *) my_malloc(size, 0);
|
buff_msg= (char*) my_malloc(size, MYF(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((size_t) n > sizeof(buff_stack))
|
else if ((size_t) n > sizeof(buff_stack))
|
||||||
{
|
{
|
||||||
buff_msg= (char *) my_malloc(n + 1, 0);
|
buff_msg= (char*) my_malloc(n + 1, MYF(0));
|
||||||
#ifdef DBUG
|
#ifdef DBUG
|
||||||
DBUG_ASSERT(n == vsnprintf(buff_msg, n + 1, format, args));
|
DBUG_ASSERT(n == vsnprintf(buff_msg, n + 1, format, args));
|
||||||
#else
|
#else
|
||||||
vsnprintf(buff_msg, n + 1, format, args);
|
vsnprintf(buff_msg, n + 1, format, args);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
fprintf(file, "%s%s\n", buff_date, buff_msg);
|
fprintf(file, "%s%s\n", buff_date, buff_msg);
|
||||||
|
@ -197,8 +197,7 @@ void manager(const Options &options)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (signo)
|
switch (signo) {
|
||||||
{
|
|
||||||
case THR_SERVER_ALARM:
|
case THR_SERVER_ALARM:
|
||||||
process_alarm(signo);
|
process_alarm(signo);
|
||||||
break;
|
break;
|
||||||
|
@ -55,8 +55,21 @@ static const char *mysqld_error_message(unsigned sql_errno)
|
|||||||
case ER_CANNOT_START_INSTANCE:
|
case ER_CANNOT_START_INSTANCE:
|
||||||
return "Cannot start instance. Possible reasons are wrong instance options"
|
return "Cannot start instance. Possible reasons are wrong instance options"
|
||||||
" or resources shortage";
|
" or resources shortage";
|
||||||
|
case ER_OFFSET_ERROR:
|
||||||
|
return "Cannot read negative number of bytes";
|
||||||
case ER_STOP_INSTANCE:
|
case ER_STOP_INSTANCE:
|
||||||
return "Cannot stop instance";
|
return "Cannot stop instance";
|
||||||
|
case ER_READ_FILE:
|
||||||
|
return "Cannot read requested part of the logfile";
|
||||||
|
case ER_NO_SUCH_LOG:
|
||||||
|
return "The instance has no such log enabled";
|
||||||
|
case ER_OPEN_LOGFILE:
|
||||||
|
return "Cannot open log file";
|
||||||
|
case ER_GUESS_LOGFILE:
|
||||||
|
return "Cannot guess the log filename. Try specifying full log name"
|
||||||
|
"in the instance options";
|
||||||
|
case ER_ACCESS_OPTION_FILE:
|
||||||
|
return "Cannot open the option file to edit. Check permissions";
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -261,10 +261,10 @@ int Mysql_connection_thread::check_connection()
|
|||||||
}
|
}
|
||||||
client_capabilities|= ((ulong) uint2korr(net.read_pos + 2)) << 16;
|
client_capabilities|= ((ulong) uint2korr(net.read_pos + 2)) << 16;
|
||||||
|
|
||||||
pos= (char *) net.read_pos + 32;
|
pos= (char*) net.read_pos + 32;
|
||||||
|
|
||||||
/* At least one byte for username and one byte for password */
|
/* At least one byte for username and one byte for password */
|
||||||
if (pos >= (char *) net.read_pos + pkt_len + 2)
|
if (pos >= (char*) net.read_pos + pkt_len + 2)
|
||||||
{
|
{
|
||||||
/*TODO add user and password handling in error messages*/
|
/*TODO add user and password handling in error messages*/
|
||||||
net_send_error(&net, ER_HANDSHAKE_ERROR);
|
net_send_error(&net, ER_HANDSHAKE_ERROR);
|
||||||
@ -284,7 +284,7 @@ int Mysql_connection_thread::check_connection()
|
|||||||
net_send_error(&net, ER_ACCESS_DENIED_ERROR);
|
net_send_error(&net, ER_ACCESS_DENIED_ERROR);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
net_send_ok(&net, connection_id);
|
net_send_ok(&net, connection_id, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,9 +301,7 @@ int Mysql_connection_thread::do_command()
|
|||||||
{
|
{
|
||||||
/* Check if we can continue without closing the connection */
|
/* Check if we can continue without closing the connection */
|
||||||
if (net.error != 3) // what is 3 - find out
|
if (net.error != 3) // what is 3 - find out
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
if (thread_registry.is_shutdown())
|
if (thread_registry.is_shutdown())
|
||||||
return 1;
|
return 1;
|
||||||
net_send_error(&net, net.last_errno);
|
net_send_error(&net, net.last_errno);
|
||||||
@ -332,7 +330,7 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command,
|
|||||||
return 1;
|
return 1;
|
||||||
case COM_PING:
|
case COM_PING:
|
||||||
log_info("query for connection %d received ping command", connection_id);
|
log_info("query for connection %d received ping command", connection_id);
|
||||||
net_send_ok(&net, connection_id);
|
net_send_ok(&net, connection_id, NULL);
|
||||||
break;
|
break;
|
||||||
case COM_QUERY:
|
case COM_QUERY:
|
||||||
{
|
{
|
||||||
@ -346,14 +344,12 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command,
|
|||||||
res= command->execute(&net, connection_id);
|
res= command->execute(&net, connection_id);
|
||||||
delete command;
|
delete command;
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
log_info("query for connection %d executed ok",connection_id);
|
||||||
log_info("query for connection %d executed ok",connection_id);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_info("query for connection %d executed err=%d",connection_id,res);
|
log_info("query for connection %d executed err=%d",connection_id,res);
|
||||||
net_send_error(&net, res);
|
net_send_error(&net, res);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -23,5 +23,11 @@
|
|||||||
#define ER_INSTANCE_ALREADY_STARTED 3002
|
#define ER_INSTANCE_ALREADY_STARTED 3002
|
||||||
#define ER_CANNOT_START_INSTANCE 3003
|
#define ER_CANNOT_START_INSTANCE 3003
|
||||||
#define ER_STOP_INSTANCE 3004
|
#define ER_STOP_INSTANCE 3004
|
||||||
|
#define ER_NO_SUCH_LOG 3005
|
||||||
|
#define ER_OPEN_LOGFILE 3006
|
||||||
|
#define ER_GUESS_LOGFILE 3007
|
||||||
|
#define ER_ACCESS_OPTION_FILE 3008
|
||||||
|
#define ER_OFFSET_ERROR 3009
|
||||||
|
#define ER_READ_FILE 3010
|
||||||
|
|
||||||
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H */
|
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H */
|
||||||
|
@ -136,7 +136,8 @@ static struct passwd *check_user(const char *user)
|
|||||||
{
|
{
|
||||||
/* Allow a numeric uid to be used */
|
/* Allow a numeric uid to be used */
|
||||||
const char *pos;
|
const char *pos;
|
||||||
for (pos= user; my_isdigit(default_charset_info, *pos); pos++) ;
|
for (pos= user; my_isdigit(default_charset_info, *pos); pos++)
|
||||||
|
{}
|
||||||
if (*pos) /* Not numeric id */
|
if (*pos) /* Not numeric id */
|
||||||
goto err;
|
goto err;
|
||||||
if (!(user_info= getpwuid(atoi(user))))
|
if (!(user_info= getpwuid(atoi(user))))
|
||||||
|
@ -158,7 +158,7 @@ static void passwd()
|
|||||||
|
|
||||||
fprintf(stderr, "Creating record for new user.\n");
|
fprintf(stderr, "Creating record for new user.\n");
|
||||||
fprintf(stderr, "Enter user name: ");
|
fprintf(stderr, "Enter user name: ");
|
||||||
if (! fgets(user, sizeof(user), stdin))
|
if (!fgets(user, sizeof(user), stdin))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Unable to read user.\n");
|
fprintf(stderr, "Unable to read user.\n");
|
||||||
return;
|
return;
|
||||||
|
@ -15,38 +15,56 @@
|
|||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#include "factory.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
enum Token
|
enum Token
|
||||||
{
|
{
|
||||||
TOK_FLUSH = 0,
|
TOK_ERROR= 0, /* Encodes the "ERROR" word, it doesn't indicate error. */
|
||||||
|
TOK_FILES,
|
||||||
|
TOK_FLUSH,
|
||||||
|
TOK_GENERAL,
|
||||||
TOK_INSTANCE,
|
TOK_INSTANCE,
|
||||||
TOK_INSTANCES,
|
TOK_INSTANCES,
|
||||||
|
TOK_LOG,
|
||||||
TOK_OPTIONS,
|
TOK_OPTIONS,
|
||||||
|
TOK_SET,
|
||||||
|
TOK_SLOW,
|
||||||
TOK_START,
|
TOK_START,
|
||||||
TOK_STATUS,
|
TOK_STATUS,
|
||||||
TOK_STOP,
|
TOK_STOP,
|
||||||
TOK_SHOW,
|
TOK_SHOW,
|
||||||
|
TOK_UNSET,
|
||||||
TOK_NOT_FOUND, // must be after all tokens
|
TOK_NOT_FOUND, // must be after all tokens
|
||||||
TOK_END
|
TOK_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct tokens_st
|
struct tokens_st
|
||||||
{
|
{
|
||||||
uint length;
|
uint length;
|
||||||
const char *tok_name;
|
const char *tok_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static struct tokens_st tokens[]= {
|
static struct tokens_st tokens[]= {
|
||||||
|
{5, "ERROR"},
|
||||||
|
{5, "FILES"},
|
||||||
{5, "FLUSH"},
|
{5, "FLUSH"},
|
||||||
|
{7, "GENERAL"},
|
||||||
{8, "INSTANCE"},
|
{8, "INSTANCE"},
|
||||||
{9, "INSTANCES"},
|
{9, "INSTANCES"},
|
||||||
|
{3, "LOG"},
|
||||||
{7, "OPTIONS"},
|
{7, "OPTIONS"},
|
||||||
|
{3, "SET"},
|
||||||
|
{4, "SLOW"},
|
||||||
{5, "START"},
|
{5, "START"},
|
||||||
{6, "STATUS"},
|
{6, "STATUS"},
|
||||||
{4, "STOP"},
|
{4, "STOP"},
|
||||||
{4, "SHOW"}
|
{4, "SHOW"},
|
||||||
|
{5, "UNSET"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -86,13 +104,6 @@ Token shift_token(const char **text, uint *word_len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void print_token(const char *token, uint tok_len)
|
|
||||||
{
|
|
||||||
for (uint i= 0; i < tok_len; ++i)
|
|
||||||
printf("%c", token[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int get_text_id(const char **text, uint *word_len, const char **id)
|
int get_text_id(const char **text, uint *word_len, const char **id)
|
||||||
{
|
{
|
||||||
get_word(text, word_len);
|
get_word(text, word_len);
|
||||||
@ -108,7 +119,15 @@ Command *parse_command(Command_factory *factory, const char *text)
|
|||||||
uint word_len;
|
uint word_len;
|
||||||
const char *instance_name;
|
const char *instance_name;
|
||||||
uint instance_name_len;
|
uint instance_name_len;
|
||||||
|
const char *option;
|
||||||
|
uint option_len;
|
||||||
|
const char *option_value;
|
||||||
|
uint option_value_len;
|
||||||
|
const char *log_size;
|
||||||
Command *command;
|
Command *command;
|
||||||
|
const char *saved_text= text;
|
||||||
|
bool skip= false;
|
||||||
|
const char *tmp;
|
||||||
|
|
||||||
Token tok1= shift_token(&text, &word_len);
|
Token tok1= shift_token(&text, &word_len);
|
||||||
|
|
||||||
@ -143,6 +162,53 @@ Command *parse_command(Command_factory *factory, const char *text)
|
|||||||
|
|
||||||
command= factory->new_Flush_instances();
|
command= factory->new_Flush_instances();
|
||||||
break;
|
break;
|
||||||
|
case TOK_UNSET:
|
||||||
|
skip= true;
|
||||||
|
case TOK_SET:
|
||||||
|
|
||||||
|
get_text_id(&text, &instance_name_len, &instance_name);
|
||||||
|
text+= instance_name_len;
|
||||||
|
|
||||||
|
/* the next token should be a dot */
|
||||||
|
get_word(&text, &word_len);
|
||||||
|
if (*text != '.')
|
||||||
|
goto syntax_error;
|
||||||
|
text++;
|
||||||
|
|
||||||
|
get_word(&text, &option_len, NONSPACE);
|
||||||
|
option= text;
|
||||||
|
if ((tmp= strchr(text, '=')) != NULL)
|
||||||
|
option_len= tmp - text;
|
||||||
|
text+= option_len;
|
||||||
|
|
||||||
|
get_word(&text, &word_len);
|
||||||
|
if (*text == '=')
|
||||||
|
{
|
||||||
|
text++; /* skip '=' */
|
||||||
|
get_word(&text, &option_value_len, NONSPACE);
|
||||||
|
option_value= text;
|
||||||
|
text+= option_value_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
option_value= "";
|
||||||
|
option_value_len= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* should be empty */
|
||||||
|
get_word(&text, &word_len);
|
||||||
|
if (word_len)
|
||||||
|
goto syntax_error;
|
||||||
|
|
||||||
|
if (skip)
|
||||||
|
command= factory->new_Unset_option(instance_name, instance_name_len,
|
||||||
|
option, option_len, option_value,
|
||||||
|
option_value_len);
|
||||||
|
else
|
||||||
|
command= factory->new_Set_option(instance_name, instance_name_len,
|
||||||
|
option, option_len, option_value,
|
||||||
|
option_value_len);
|
||||||
|
break;
|
||||||
case TOK_SHOW:
|
case TOK_SHOW:
|
||||||
switch (shift_token(&text, &word_len)) {
|
switch (shift_token(&text, &word_len)) {
|
||||||
case TOK_INSTANCES:
|
case TOK_INSTANCES:
|
||||||
@ -157,6 +223,7 @@ Command *parse_command(Command_factory *factory, const char *text)
|
|||||||
case TOK_STATUS:
|
case TOK_STATUS:
|
||||||
get_text_id(&text, &instance_name_len, &instance_name);
|
get_text_id(&text, &instance_name_len, &instance_name);
|
||||||
text+= instance_name_len;
|
text+= instance_name_len;
|
||||||
|
/* check that this is the end of the command */
|
||||||
get_word(&text, &word_len);
|
get_word(&text, &word_len);
|
||||||
if (word_len)
|
if (word_len)
|
||||||
goto syntax_error;
|
goto syntax_error;
|
||||||
@ -172,7 +239,87 @@ Command *parse_command(Command_factory *factory, const char *text)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto syntax_error;
|
instance_name= text - word_len;
|
||||||
|
instance_name_len= word_len;
|
||||||
|
if (instance_name_len)
|
||||||
|
{
|
||||||
|
Log_type log_type;
|
||||||
|
switch (shift_token(&text, &word_len)) {
|
||||||
|
case TOK_LOG:
|
||||||
|
switch (Token tok3= shift_token(&text, &word_len)) {
|
||||||
|
case TOK_FILES:
|
||||||
|
get_word(&text, &word_len);
|
||||||
|
/* check that this is the end of the command */
|
||||||
|
if (word_len)
|
||||||
|
goto syntax_error;
|
||||||
|
command= (Command *)
|
||||||
|
factory->new_Show_instance_log_files(instance_name,
|
||||||
|
instance_name_len);
|
||||||
|
break;
|
||||||
|
case TOK_ERROR:
|
||||||
|
case TOK_GENERAL:
|
||||||
|
case TOK_SLOW:
|
||||||
|
/* define a log type */
|
||||||
|
switch (tok3) {
|
||||||
|
case TOK_ERROR:
|
||||||
|
log_type= LOG_ERROR;
|
||||||
|
break;
|
||||||
|
case TOK_GENERAL:
|
||||||
|
log_type= LOG_GENERAL;
|
||||||
|
break;
|
||||||
|
case TOK_SLOW:
|
||||||
|
log_type= LOG_SLOW;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto syntax_error;
|
||||||
|
}
|
||||||
|
/* get the size of the log we want to retrieve */
|
||||||
|
get_text_id(&text, &word_len, &log_size);
|
||||||
|
text+= word_len;
|
||||||
|
/* this parameter is required */
|
||||||
|
if (!word_len)
|
||||||
|
goto syntax_error;
|
||||||
|
/* the next token should be comma, or nothing */
|
||||||
|
get_word(&text, &word_len);
|
||||||
|
switch (*text) {
|
||||||
|
case ',':
|
||||||
|
text++; /* swallow the comma */
|
||||||
|
/* read the next word */
|
||||||
|
get_word(&text, &word_len);
|
||||||
|
if (!word_len)
|
||||||
|
goto syntax_error;
|
||||||
|
command= (Command *)
|
||||||
|
factory->new_Show_instance_log(instance_name,
|
||||||
|
instance_name_len,
|
||||||
|
log_type,
|
||||||
|
log_size,
|
||||||
|
text);
|
||||||
|
|
||||||
|
//get_text_id(&text, &log_size_len, &log_size);
|
||||||
|
break;
|
||||||
|
case '\0':
|
||||||
|
command= (Command *)
|
||||||
|
factory->new_Show_instance_log(instance_name,
|
||||||
|
instance_name_len,
|
||||||
|
log_type,
|
||||||
|
log_size,
|
||||||
|
NULL);
|
||||||
|
break; /* this is ok */
|
||||||
|
default:
|
||||||
|
goto syntax_error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto syntax_error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto syntax_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto syntax_error;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -181,4 +328,3 @@ syntax_error:
|
|||||||
}
|
}
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,18 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
#include "factory.h"
|
#include <my_global.h>
|
||||||
|
#include <my_sys.h>
|
||||||
|
|
||||||
|
class Command;
|
||||||
|
class Command_factory;
|
||||||
|
|
||||||
|
enum Log_type
|
||||||
|
{
|
||||||
|
LOG_ERROR= 0,
|
||||||
|
LOG_GENERAL,
|
||||||
|
LOG_SLOW
|
||||||
|
};
|
||||||
|
|
||||||
Command *parse_command(Command_factory *factory, const char *text);
|
Command *parse_command(Command_factory *factory, const char *text);
|
||||||
|
|
||||||
@ -44,10 +55,12 @@ inline void get_word(const char **text, uint *word_len,
|
|||||||
while (my_isalnum(default_charset_info, *word_end))
|
while (my_isalnum(default_charset_info, *word_end))
|
||||||
++word_end;
|
++word_end;
|
||||||
else
|
else
|
||||||
while (!my_isspace(default_charset_info, *word_end))
|
while (!my_isspace(default_charset_info, *word_end) &&
|
||||||
|
(*word_end != '\0'))
|
||||||
++word_end;
|
++word_end;
|
||||||
|
|
||||||
*word_len= word_end - *text;
|
*word_len= word_end - *text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H */
|
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H */
|
||||||
|
@ -47,7 +47,7 @@ int parse_output_and_get_value(const char *command, const char *word,
|
|||||||
{
|
{
|
||||||
FILE *output;
|
FILE *output;
|
||||||
uint wordlen;
|
uint wordlen;
|
||||||
/* should be enought to store the string from the output */
|
/* should be enough to store the string from the output */
|
||||||
enum { MAX_LINE_LEN= 512 };
|
enum { MAX_LINE_LEN= 512 };
|
||||||
char linebuf[MAX_LINE_LEN];
|
char linebuf[MAX_LINE_LEN];
|
||||||
|
|
||||||
@ -99,3 +99,4 @@ pclose:
|
|||||||
err:
|
err:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H
|
||||||
|
#define INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H
|
||||||
/* Copyright (C) 2004 MySQL AB
|
/* Copyright (C) 2004 MySQL AB
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
@ -17,3 +19,4 @@
|
|||||||
int parse_output_and_get_value(const char *command, const char *word,
|
int parse_output_and_get_value(const char *command, const char *word,
|
||||||
char *result, size_t result_len);
|
char *result, size_t result_len);
|
||||||
|
|
||||||
|
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H */
|
||||||
|
@ -24,15 +24,25 @@
|
|||||||
|
|
||||||
static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
|
static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
|
||||||
|
|
||||||
int net_send_ok(struct st_net *net, unsigned long connection_id)
|
|
||||||
{
|
|
||||||
char buff[1 + // packet type code
|
|
||||||
9 + // affected rows count
|
|
||||||
9 + // connection id
|
|
||||||
2 + // thread return status
|
|
||||||
2]; // warning count
|
|
||||||
|
|
||||||
char *pos= buff;
|
int net_send_ok(struct st_net *net, unsigned long connection_id,
|
||||||
|
const char *message)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The format of a packet
|
||||||
|
1 packet type code
|
||||||
|
1-9 affected rows count
|
||||||
|
1-9 connection id
|
||||||
|
2 thread return status
|
||||||
|
2 warning count
|
||||||
|
1-9 + message length message to send (isn't stored if no message)
|
||||||
|
*/
|
||||||
|
Buffer buff;
|
||||||
|
char *pos= buff.buffer;
|
||||||
|
|
||||||
|
/* check that we have space to hold mandatory fields */
|
||||||
|
buff.reserve(0, 23);
|
||||||
|
|
||||||
enum { OK_PACKET_CODE= 0 };
|
enum { OK_PACKET_CODE= 0 };
|
||||||
*pos++= OK_PACKET_CODE;
|
*pos++= OK_PACKET_CODE;
|
||||||
pos= net_store_length(pos, (ulonglong) 0);
|
pos= net_store_length(pos, (ulonglong) 0);
|
||||||
@ -43,7 +53,15 @@ int net_send_ok(struct st_net *net, unsigned long connection_id)
|
|||||||
int2store(pos, 0);
|
int2store(pos, 0);
|
||||||
pos+= 2;
|
pos+= 2;
|
||||||
|
|
||||||
return my_net_write(net, buff, pos - buff) || net_flush(net);
|
uint position= pos - buff.buffer; /* we might need it for message */
|
||||||
|
|
||||||
|
if (message != NULL)
|
||||||
|
{
|
||||||
|
buff.reserve(position, 9 + strlen(message));
|
||||||
|
store_to_string(&buff, message, &position);
|
||||||
|
}
|
||||||
|
|
||||||
|
return my_net_write(net, buff.buffer, position) || net_flush(net);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -99,15 +117,16 @@ char *net_store_length(char *pkg, uint length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int store_to_string(Buffer *buf, const char *string, uint *position)
|
int store_to_string(Buffer *buf, const char *string, uint *position,
|
||||||
|
uint string_len)
|
||||||
{
|
{
|
||||||
uint currpos;
|
uint currpos;
|
||||||
uint string_len;
|
|
||||||
|
|
||||||
string_len= strlen(string);
|
/* reserve max amount of bytes needed to store length */
|
||||||
if (buf->reserve(*position, 2))
|
if (buf->reserve(*position, 9))
|
||||||
goto err;
|
goto err;
|
||||||
currpos= (net_store_length(buf->buffer + *position, string_len) - buf->buffer);
|
currpos= (net_store_length(buf->buffer + *position,
|
||||||
|
(ulonglong) string_len) - buf->buffer);
|
||||||
if (buf->append(currpos, string, string_len))
|
if (buf->append(currpos, string, string_len))
|
||||||
goto err;
|
goto err;
|
||||||
*position= *position + string_len + (currpos - *position);
|
*position= *position + string_len + (currpos - *position);
|
||||||
@ -118,6 +137,15 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int store_to_string(Buffer *buf, const char *string, uint *position)
|
||||||
|
{
|
||||||
|
uint string_len;
|
||||||
|
|
||||||
|
string_len= strlen(string);
|
||||||
|
return store_to_string(buf, string, position, string_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int send_eof(struct st_net *net)
|
int send_eof(struct st_net *net)
|
||||||
{
|
{
|
||||||
char buff[1 + /* eof packet code */
|
char buff[1 + /* eof packet code */
|
||||||
@ -148,10 +176,10 @@ int send_fields(struct st_net *net, LIST *fields)
|
|||||||
position= 0;
|
position= 0;
|
||||||
field= (NAME_WITH_LENGTH *) tmp->data;
|
field= (NAME_WITH_LENGTH *) tmp->data;
|
||||||
|
|
||||||
store_to_string(&send_buff, (char *) "", &position); /* catalog name */
|
store_to_string(&send_buff, (char*) "", &position); /* catalog name */
|
||||||
store_to_string(&send_buff, (char *) "", &position); /* db name */
|
store_to_string(&send_buff, (char*) "", &position); /* db name */
|
||||||
store_to_string(&send_buff, (char *) "", &position); /* table name */
|
store_to_string(&send_buff, (char*) "", &position); /* table name */
|
||||||
store_to_string(&send_buff, (char *) "", &position); /* table name alias */
|
store_to_string(&send_buff, (char*) "", &position); /* table name alias */
|
||||||
store_to_string(&send_buff, field->name, &position); /* column name */
|
store_to_string(&send_buff, field->name, &position); /* column name */
|
||||||
store_to_string(&send_buff, field->name, &position); /* column name alias */
|
store_to_string(&send_buff, field->name, &position); /* column name alias */
|
||||||
send_buff.reserve(position, 12);
|
send_buff.reserve(position, 12);
|
||||||
|
@ -25,9 +25,13 @@ typedef struct field {
|
|||||||
uint length;
|
uint length;
|
||||||
} NAME_WITH_LENGTH;
|
} NAME_WITH_LENGTH;
|
||||||
|
|
||||||
|
/* default field length to be used in various field-realted functions */
|
||||||
|
enum { DEFAULT_FIELD_LENGTH= 20 };
|
||||||
|
|
||||||
struct st_net;
|
struct st_net;
|
||||||
|
|
||||||
int net_send_ok(struct st_net *net, unsigned long connection_id);
|
int net_send_ok(struct st_net *net, unsigned long connection_id,
|
||||||
|
const char *message);
|
||||||
|
|
||||||
int net_send_error(struct st_net *net, unsigned sql_errno);
|
int net_send_error(struct st_net *net, unsigned sql_errno);
|
||||||
|
|
||||||
@ -39,6 +43,9 @@ char *net_store_length(char *pkg, uint length);
|
|||||||
|
|
||||||
int store_to_string(Buffer *buf, const char *string, uint *position);
|
int store_to_string(Buffer *buf, const char *string, uint *position);
|
||||||
|
|
||||||
|
int store_to_string(Buffer *buf, const char *string, uint *position,
|
||||||
|
uint string_len);
|
||||||
|
|
||||||
int send_eof(struct st_net *net);
|
int send_eof(struct st_net *net);
|
||||||
|
|
||||||
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PROTOCOL_H */
|
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PROTOCOL_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user