Commit 834c47f3 authored by petr@mysql.com's avatar petr@mysql.com

Merge

parents 567712b9 180d0ed6
......@@ -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 *strmake_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,
char **defaults, char **extra_defaults);
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 \
my_pread.lo mf_cache.lo md5.lo sha1.lo \
my_getopt.lo my_gethostbyname.lo my_port.lo \
my_rename.lo
my_rename.lo my_chsize.lo
sqlobjects = net.lo
sql_cmn_objects = pack.lo client.lo my_time.lo
......
......@@ -50,9 +50,11 @@ const char *default_directories[MAX_DEFAULT_DIRS + 1];
#ifdef __WIN__
static const char *f_extensions[]= { ".ini", ".cnf", 0 };
#define NEWLINE "\r\n"
static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN];
#else
static const char *f_extensions[]= { ".cnf", 0 };
#define NEWLINE "\n"
#endif
/*
......@@ -79,6 +81,142 @@ static void init_default_directories();
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.
......
......@@ -30,7 +30,9 @@
MyFlags Flags
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
0 Ok
......
......@@ -64,7 +64,7 @@ int Buffer::append(uint position, const char *string, uint len_arg)
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
buffer is too small it reallocs the buffer. The total size of the buffer is
restricted with 16 Mb.
......@@ -81,7 +81,7 @@ int Buffer::reserve(uint position, uint len_arg)
if (position + len_arg >= buffer_size)
{
buffer= (char *) my_realloc(buffer,
buffer= (char*) my_realloc(buffer,
min(MAX_BUFFER_SIZE,
max((uint) (buffer_size*1.5),
position + len_arg)), MYF(0));
......
This diff is collapsed.
......@@ -18,6 +18,7 @@
#include "command.h"
#include "instance.h"
#include "parse.h"
/*
Print all instances of this instance manager.
......@@ -30,7 +31,6 @@ public:
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);
};
......@@ -59,8 +59,8 @@ class Show_instance_status : public Command
{
public:
Show_instance_status(Instance_map *instance_map_arg, const char *name, uint len);
int do_command(struct st_net *net, const char *instance_name);
Show_instance_status(Instance_map *instance_map_arg,
const char *name, uint len);
int execute(struct st_net *net, ulong connection_id);
const char *instance_name;
};
......@@ -75,10 +75,10 @@ class Show_instance_options : public Command
{
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 do_command(struct st_net *net, 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.
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.
Print requested part of the log
Grammar:
SHOW <instance_name> log {ERROR | SLOW | GENERAL} size[, offset_from_end]
*/
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
......@@ -128,4 +166,50 @@ public:
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 */
......@@ -16,40 +16,85 @@
#include "factory.h"
Show_instances *Command_factory::new_Show_instances()
{
return new Show_instances(&instance_map);
}
Flush_instances *Command_factory::new_Flush_instances()
{
return new Flush_instances(&instance_map);
}
Show_instance_status *Command_factory::
new_Show_instance_status(const char *name, uint len)
{
return new Show_instance_status(&instance_map, name, len);
}
Show_instance_options *Command_factory::
new_Show_instance_options(const char *name, uint len)
{
return new Show_instance_options(&instance_map, name, len);
}
Start_instance *Command_factory::
new_Start_instance(const char *name, uint len)
{
return new Start_instance(&instance_map, name, len);
}
Stop_instance *Command_factory::new_Stop_instance(const char *name, uint len)
{
return new Stop_instance(&instance_map, name, len);
}
Syntax_error *Command_factory::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
*/
class Show_instances;
class Command_factory
{
public:
......@@ -33,12 +35,26 @@ public:
{}
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_options *new_Show_instance_options (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);
Flush_instances *new_Flush_instances ();
Syntax_error *new_Syntax_error ();
Show_instance_log *new_Show_instance_log (const char *name, uint len,
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;
};
......
......@@ -315,7 +315,7 @@ int Guardian_thread::guard(Instance *instance, bool nolock)
content->restart_counter= 0;
content->crash_moment= 0;
content->state= NOT_STARTED;
node->data= (void *) content;
node->data= (void*) content;
if (nolock)
guarded_instances= list_add(guarded_instances, node);
......
......@@ -304,12 +304,11 @@ void Instance::kill_instance(int signum)
*/
if (!kill(pid, signum))
options.unlink_pidfile();
else
if (signum == SIGKILL) /* really killed instance with SIGKILL */
log_error("The instance %s is being stopped forsibly. Normally \
it should not happed. Probably the instance has been \
hanging. You should also check your IM setup",
options.instance_name);
else if (signum == SIGKILL) /* really killed instance with SIGKILL */
log_error("The instance %s is being stopped forsibly. Normally \
it should not happed. Probably the instance has been \
hanging. You should also check your IM setup",
options.instance_name);
}
return;
}
......
......@@ -246,7 +246,7 @@ int Instance_map::load()
argv_options[1]= '\0';
if (my_search_option_files("my", &argc, (char ***) &argv, &args_used,
process_option, (void *) this) ||
process_option, (void*) this) ||
complete_initialization())
return 1;
......
......@@ -24,7 +24,6 @@
#include "buffer.h"
#include <my_sys.h>
#include <mysql.h>
#include <signal.h>
#include <m_string.h>
......@@ -36,7 +35,7 @@
get_default_option()
result buffer to put found value
result_len buffer size
oprion_name the name of the option, prefixed with "--"
option_name the name of the option, prefixed with "--"
DESCRIPTION
......@@ -47,6 +46,7 @@
1 - error occured
*/
int Instance_options::get_default_option(char *result, size_t result_len,
const char *option_name)
{
......@@ -54,7 +54,7 @@ int Instance_options::get_default_option(char *result, size_t result_len,
int rc= 1;
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 */
{
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)
{
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*));
argv[filled_default_options + options_array.elements]= 0;
fill_log_options();
return 0;
err:
......@@ -274,7 +416,7 @@ int Instance_options::add_to_argv(const char* option)
DBUG_ASSERT(filled_default_options < MAX_NUMBER_OF_DEFAULT_OPTIONS);
if ((option))
argv[filled_default_options++]= (char *) option;
argv[filled_default_options++]= (char*) option;
return 0;
}
......@@ -302,10 +444,10 @@ int Instance_options::init(const char *instance_name_arg)
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;
if (!(instance_name= strmake_root(&alloc, (char *) instance_name_arg,
if (!(instance_name= strmake_root(&alloc, (char*) instance_name_arg,
instance_name_len)))
goto err;
......
......@@ -18,6 +18,7 @@
#include <my_global.h>
#include <my_sys.h>
#include "parse.h"
#ifdef __GNUC__
#pragma interface
......@@ -76,9 +77,13 @@ public:
const char *nonguarded;
const char *shutdown_delay;
uint shutdown_delay_val;
/* log enums are defined in parse.h */
char *logs[3];
/* this value is computed and cashed here */
DYNAMIC_ARRAY options_array;
private:
int fill_log_options();
int add_to_argv(const char *option);
int get_default_option(char *result, size_t result_len,
const char *option_name);
......
......@@ -241,23 +241,20 @@ void Listener_thread::run()
}
}
}
else
if (FD_ISSET(ip_socket, &read_fds_arg))
else 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);
/* accept may return -1 (failure or spurious wakeup) */
if (client_fd >= 0) // connection established
if (Vio *vio= vio_new(client_fd, VIO_TYPE_TCPIP, 0))
handle_new_mysql_connection(vio);
else
{
if (Vio *vio= vio_new(client_fd, VIO_TYPE_TCPIP, 0))
{
handle_new_mysql_connection(vio);
}
else
{
shutdown(client_fd, SHUT_RDWR);
close(client_fd);
}
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))
{
int size= sizeof(buff_stack) * 2;
buff_msg= (char *) my_malloc(size, 0);
buff_msg= (char*) my_malloc(size, MYF(0));
while (true)
{
if (buff_msg == 0)
......@@ -86,16 +86,16 @@ static inline void log(FILE *file, const char *format, va_list args)
size*= 2;
/* realloc() does unnecessary memcpy */
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))
{
buff_msg= (char *) my_malloc(n + 1, 0);
buff_msg= (char*) my_malloc(n + 1, MYF(0));
#ifdef DBUG
DBUG_ASSERT(n == vsnprintf(buff_msg, n + 1, format, args));
#else
vsnprintf(buff_msg, n + 1, format, args);
vsnprintf(buff_msg, n + 1, format, args);
#endif
}
fprintf(file, "%s%s\n", buff_date, buff_msg);
......
......@@ -197,8 +197,7 @@ void manager(const Options &options)
goto err;
}
switch (signo)
{
switch (signo) {
case THR_SERVER_ALARM:
process_alarm(signo);
break;
......
......@@ -55,8 +55,21 @@ static const char *mysqld_error_message(unsigned sql_errno)
case ER_CANNOT_START_INSTANCE:
return "Cannot start instance. Possible reasons are wrong instance options"
" or resources shortage";
case ER_OFFSET_ERROR:
return "Cannot read negative number of bytes";
case ER_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:
DBUG_ASSERT(0);
return 0;
......
......@@ -261,10 +261,10 @@ int Mysql_connection_thread::check_connection()
}
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 */
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*/
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);
return 1;
}
net_send_ok(&net, connection_id);
net_send_ok(&net, connection_id, NULL);
return 0;
}
......@@ -301,9 +301,7 @@ int Mysql_connection_thread::do_command()
{
/* Check if we can continue without closing the connection */
if (net.error != 3) // what is 3 - find out
{
return 1;
}
if (thread_registry.is_shutdown())
return 1;
net_send_error(&net, net.last_errno);
......@@ -332,7 +330,7 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command,
return 1;
case COM_PING:
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;
case COM_QUERY:
{
......@@ -346,14 +344,12 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command,
res= command->execute(&net, connection_id);
delete command;
if (!res)
{
log_info("query for connection %d executed ok",connection_id);
}
log_info("query for connection %d executed ok",connection_id);
else
{
log_info("query for connection %d executed err=%d",connection_id,res);
net_send_error(&net, res);
return 0;
log_info("query for connection %d executed err=%d",connection_id,res);
net_send_error(&net, res);
return 0;
}
}
else
......
......@@ -23,5 +23,11 @@
#define ER_INSTANCE_ALREADY_STARTED 3002
#define ER_CANNOT_START_INSTANCE 3003
#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 */
......@@ -136,7 +136,8 @@ static struct passwd *check_user(const char *user)
{
/* Allow a numeric uid to be used */
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 */
goto err;
if (!(user_info= getpwuid(atoi(user))))
......
......@@ -158,7 +158,7 @@ static void passwd()
fprintf(stderr, "Creating record for new user.\n");
fprintf(stderr, "Enter user name: ");
if (! fgets(user, sizeof(user), stdin))
if (!fgets(user, sizeof(user), stdin))
{
fprintf(stderr, "Unable to read user.\n");
return;
......
......@@ -15,38 +15,56 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "parse.h"
#include "factory.h"
#include <string.h>
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_INSTANCES,
TOK_LOG,
TOK_OPTIONS,
TOK_SET,
TOK_SLOW,
TOK_START,
TOK_STATUS,
TOK_STOP,
TOK_SHOW,
TOK_UNSET,
TOK_NOT_FOUND, // must be after all tokens
TOK_END
};
struct tokens_st
{
uint length;
const char *tok_name;
};
static struct tokens_st tokens[]= {
{5, "ERROR"},
{5, "FILES"},
{5, "FLUSH"},
{7, "GENERAL"},
{8, "INSTANCE"},
{9, "INSTANCES"},
{3, "LOG"},
{7, "OPTIONS"},
{3, "SET"},
{4, "SLOW"},
{5, "START"},
{6, "STATUS"},
{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)
{
get_word(text, word_len);
......@@ -108,7 +119,15 @@ Command *parse_command(Command_factory *factory, const char *text)
uint word_len;
const char *instance_name;
uint instance_name_len;
const char *option;
uint option_len;
const char *option_value;
uint option_value_len;
const char *log_size;
Command *command;
const char *saved_text= text;
bool skip= false;
const char *tmp;
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();
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:
switch (shift_token(&text, &word_len)) {
case TOK_INSTANCES:
......@@ -157,6 +223,7 @@ Command *parse_command(Command_factory *factory, const char *text)
case TOK_STATUS:
get_text_id(&text, &instance_name_len, &instance_name);
text+= instance_name_len;
/* check that this is the end of the command */
get_word(&text, &word_len);
if (word_len)
goto syntax_error;
......@@ -172,7 +239,87 @@ Command *parse_command(Command_factory *factory, const char *text)
}
break;
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;
default:
......@@ -181,4 +328,3 @@ syntax_error:
}
return command;
}
......@@ -16,7 +16,18 @@
along with this program; if not, write to the Free Software
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);
......@@ -44,10 +55,12 @@ inline void get_word(const char **text, uint *word_len,
while (my_isalnum(default_charset_info, *word_end))
++word_end;
else
while (!my_isspace(default_charset_info, *word_end))
while (!my_isspace(default_charset_info, *word_end) &&
(*word_end != '\0'))
++word_end;
*word_len= word_end - *text;
}
#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;
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 };
char linebuf[MAX_LINE_LEN];
......@@ -99,3 +99,4 @@ pclose:
err:
return 1;
}
#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H
#define INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H
/* Copyright (C) 2004 MySQL AB
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,
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 */
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)
{
char buff[1 + // packet type code
9 + // affected rows count
9 + // connection id
2 + // thread return status
2]; // warning count
/*
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);
char *pos= buff;
enum { OK_PACKET_CODE= 0 };
*pos++= OK_PACKET_CODE;
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);
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 string_len;
string_len= strlen(string);
if (buf->reserve(*position, 2))
/* reserve max amount of bytes needed to store length */
if (buf->reserve(*position, 9))
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))
goto err;
*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)
{
char buff[1 + /* eof packet code */
......@@ -148,10 +176,10 @@ int send_fields(struct st_net *net, LIST *fields)
position= 0;
field= (NAME_WITH_LENGTH *) tmp->data;
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); /* table name */
store_to_string(&send_buff, (char *) "", &position); /* table name alias */
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); /* table name */
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 alias */
send_buff.reserve(position, 12);
......
......@@ -25,9 +25,13 @@ typedef struct field {
uint length;
} NAME_WITH_LENGTH;
/* default field length to be used in various field-realted functions */
enum { DEFAULT_FIELD_LENGTH= 20 };
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);
......@@ -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,
uint string_len);
int send_eof(struct st_net *net);
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PROTOCOL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment