mariadb/server-tools/instance-manager/commands.cc

793 lines
20 KiB
C++
Raw Normal View History

/* Copyright (C) 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "commands.h"
#include "instance_map.h"
#include "messages.h"
#include "mysqld_error.h"
#include "mysql_manager_error.h"
2004-10-26 23:22:12 +04:00
#include "protocol.h"
#include "buffer.h"
2004-10-26 23:22:12 +04:00
#include <m_string.h>
#include <mysql.h>
2005-05-16 01:54:02 +04:00
#include <my_dir.h>
2005-05-16 01:54:02 +04:00
/*
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
*/
2005-05-16 01:54:02 +04:00
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: */
2004-10-26 23:22:12 +04:00
/*
The method sends a list of instances in the instance map to the client.
SYNOPSYS
2005-05-16 01:54:02 +04:00
Show_instances::execute()
net The network connection to the client.
connection_id Client connection ID
2004-10-26 23:22:12 +04:00
RETURN
0 - ok
1 - error occured
*/
2005-05-16 01:54:02 +04:00
int Show_instances::execute(struct st_net *net, ulong connection_id)
2004-10-26 23:22:12 +04:00
{
Buffer send_buff; /* buffer for packets */
LIST name, status;
NAME_WITH_LENGTH name_field, status_field;
LIST *field_list;
uint position=0;
2005-05-16 01:54:02 +04:00
name_field.name= (char*) "instance_name";
name_field.length= DEFAULT_FIELD_LENGTH;
2004-10-26 23:22:12 +04:00
name.data= &name_field;
2005-05-16 01:54:02 +04:00
status_field.name= (char*) "status";
status_field.length= DEFAULT_FIELD_LENGTH;
2004-10-26 23:22:12 +04:00
status.data= &status_field;
field_list= list_add(NULL, &status);
field_list= list_add(field_list, &name);
send_fields(net, field_list);
{
Instance *instance;
2004-10-27 10:21:48 +04:00
Instance_map::Iterator iterator(instance_map);
2004-10-26 23:22:12 +04:00
instance_map->lock();
2004-12-12 20:59:15 +03:00
while ((instance= iterator.next()))
2004-10-26 23:22:12 +04:00
{
position= 0;
store_to_string(&send_buff, instance->options.instance_name, &position);
if (instance->is_running())
2005-05-16 01:54:02 +04:00
store_to_string(&send_buff, (char*) "online", &position);
2004-10-26 23:22:12 +04:00
else
2005-05-16 01:54:02 +04:00
store_to_string(&send_buff, (char*) "offline", &position);
2004-10-26 23:22:12 +04:00
if (my_net_write(net, send_buff.buffer, (uint) position))
goto err;
}
instance_map->unlock();
}
if (send_eof(net))
goto err;
if (net_flush(net))
goto err;
return 0;
err:
2005-05-16 01:54:02 +04:00
return ER_OUT_OF_RESOURCES;
}
/* implementation for Flush_instances: */
int Flush_instances::execute(struct st_net *net, ulong connection_id)
{
2005-05-16 01:54:02 +04:00
if (instance_map->flush_instances() ||
net_send_ok(net, connection_id, NULL))
return ER_OUT_OF_RESOURCES;
return 0;
}
/* implementation for Show_instance_status: */
2004-10-27 10:21:48 +04:00
Show_instance_status::Show_instance_status(Instance_map *instance_map_arg,
const char *name, uint len)
2004-10-27 10:21:48 +04:00
:Command(instance_map_arg)
{
Instance *instance;
/* we make a search here, since we don't want to store the name */
2004-12-12 20:59:15 +03:00
if ((instance= instance_map->find(name, len)))
instance_name= instance->options.instance_name;
2004-10-25 14:23:31 +04:00
else
instance_name= NULL;
}
2004-10-26 23:22:12 +04:00
/*
The method sends a table with a status of requested instance to the client.
SYNOPSYS
Show_instance_status::do_command()
net The network connection to the client.
instance_name The name of the instance.
RETURN
0 - ok
1 - error occured
*/
2005-05-16 01:54:02 +04:00
int Show_instance_status::execute(struct st_net *net,
ulong connection_id)
2004-10-26 23:22:12 +04:00
{
enum { MAX_VERSION_LENGTH= 40 };
Buffer send_buff; /* buffer for packets */
LIST name, status, version;
LIST *field_list;
NAME_WITH_LENGTH name_field, status_field, version_field;
uint position=0;
2005-05-16 01:54:02 +04:00
if (!instance_name)
return ER_BAD_INSTANCE_NAME;
2004-10-26 23:22:12 +04:00
/* create list of the fileds to be passed to send_fields */
2005-05-16 01:54:02 +04:00
name_field.name= (char*) "instance_name";
name_field.length= DEFAULT_FIELD_LENGTH;
2004-10-26 23:22:12 +04:00
name.data= &name_field;
2005-05-16 01:54:02 +04:00
status_field.name= (char*) "status";
status_field.length= DEFAULT_FIELD_LENGTH;
2004-10-26 23:22:12 +04:00
status.data= &status_field;
2005-05-16 01:54:02 +04:00
version_field.name= (char*) "version";
2004-10-26 23:22:12 +04:00
version_field.length= MAX_VERSION_LENGTH;
version.data= &version_field;
field_list= list_add(NULL, &version);
field_list= list_add(field_list, &status);
field_list= list_add(field_list, &name);
send_fields(net, field_list);
{
Instance *instance;
2005-05-16 01:54:02 +04:00
store_to_string(&send_buff, (char*) instance_name, &position);
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
2004-10-26 23:22:12 +04:00
goto err;
if (instance->is_running())
{
2005-05-16 01:54:02 +04:00
store_to_string(&send_buff, (char*) "online", &position);
store_to_string(&send_buff, "unknown", &position);
2004-10-26 23:22:12 +04:00
}
else
{
2005-05-16 01:54:02 +04:00
store_to_string(&send_buff, (char*) "offline", &position);
store_to_string(&send_buff, (char*) "unknown", &position);
2004-10-26 23:22:12 +04:00
}
2005-02-13 15:13:33 +03:00
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
2004-11-02 10:11:03 +03:00
goto err;
2004-10-26 23:22:12 +04:00
}
2005-05-16 01:54:02 +04:00
if (send_eof(net) || net_flush(net))
goto err;
2004-10-26 23:22:12 +04:00
return 0;
2004-11-02 10:11:03 +03:00
err:
2005-05-16 01:54:02 +04:00
return ER_OUT_OF_RESOURCES;
}
/* Implementation for Show_instance_options */
2004-10-27 10:21:48 +04:00
Show_instance_options::Show_instance_options(Instance_map *instance_map_arg,
const char *name, uint len):
2004-10-27 10:21:48 +04:00
Command(instance_map_arg)
{
Instance *instance;
/* we make a search here, since we don't want to store the name */
2004-12-12 20:59:15 +03:00
if ((instance= instance_map->find(name, len)))
instance_name= instance->options.instance_name;
2004-10-25 14:23:31 +04:00
else
instance_name= NULL;
}
2005-05-16 01:54:02 +04:00
int Show_instance_options::execute(struct st_net *net, ulong connection_id)
2004-10-26 23:22:12 +04:00
{
Buffer send_buff; /* buffer for packets */
LIST name, option;
LIST *field_list;
NAME_WITH_LENGTH name_field, option_field;
uint position=0;
2005-05-16 01:54:02 +04:00
if (!instance_name)
return ER_BAD_INSTANCE_NAME;
2004-10-26 23:22:12 +04:00
/* create list of the fileds to be passed to send_fields */
2005-05-16 01:54:02 +04:00
name_field.name= (char*) "option_name";
name_field.length= DEFAULT_FIELD_LENGTH;
2004-10-26 23:22:12 +04:00
name.data= &name_field;
2005-05-16 01:54:02 +04:00
option_field.name= (char*) "value";
option_field.length= DEFAULT_FIELD_LENGTH;
2004-10-26 23:22:12 +04:00
option.data= &option_field;
field_list= list_add(NULL, &option);
field_list= list_add(field_list, &name);
send_fields(net, field_list);
{
Instance *instance;
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
2004-10-26 23:22:12 +04:00
goto err;
2005-05-16 01:54:02 +04:00
store_to_string(&send_buff, (char*) "instance_name", &position);
store_to_string(&send_buff, (char*) instance_name, &position);
2004-11-02 10:11:03 +03:00
if (my_net_write(net, send_buff.buffer, (uint) position))
goto err;
if ((instance->options.mysqld_path))
2004-10-26 23:22:12 +04:00
{
position= 0;
2005-05-16 01:54:02 +04:00
store_to_string(&send_buff, (char*) "mysqld-path", &position);
2004-10-26 23:22:12 +04:00
store_to_string(&send_buff,
2005-05-16 01:54:02 +04:00
(char*) instance->options.mysqld_path,
2004-10-26 23:22:12 +04:00
&position);
2005-02-13 15:13:33 +03:00
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
2004-11-02 10:11:03 +03:00
goto err;
}
if ((instance->options.nonguarded))
2004-11-02 10:11:03 +03:00
{
position= 0;
2005-05-16 01:54:02 +04:00
store_to_string(&send_buff, (char*) "nonguarded", &position);
2004-11-02 10:11:03 +03:00
store_to_string(&send_buff, "", &position);
2005-02-13 15:13:33 +03:00
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
2004-11-02 10:11:03 +03:00
goto err;
2004-10-26 23:22:12 +04:00
}
/* loop through the options stored in DYNAMIC_ARRAY */
2004-12-12 20:59:15 +03:00
for (uint i= 0; i < instance->options.options_array.elements; i++)
2004-10-26 23:22:12 +04:00
{
char *tmp_option, *option_value;
get_dynamic(&(instance->options.options_array), (gptr) &tmp_option, i);
option_value= strchr(tmp_option, '=');
2005-04-11 17:14:40 +04:00
/* split the option string into two parts if it has a value */
2004-10-26 23:22:12 +04:00
position= 0;
2005-04-11 17:14:40 +04:00
if (option_value != NULL)
{
*option_value= 0;
store_to_string(&send_buff, tmp_option + 2, &position);
store_to_string(&send_buff, option_value + 1, &position);
/* join name and the value into the same option again */
*option_value= '=';
}
2005-05-16 01:54:02 +04:00
else
store_to_string(&send_buff, tmp_option + 2, &position);
2005-04-11 17:14:40 +04:00
2005-02-13 15:13:33 +03:00
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
2004-11-02 10:11:03 +03:00
goto err;
2004-10-26 23:22:12 +04:00
}
}
2005-05-16 01:54:02 +04:00
if (send_eof(net) || net_flush(net))
goto err;
2004-10-26 23:22:12 +04:00
return 0;
err:
2005-05-16 01:54:02 +04:00
return ER_OUT_OF_RESOURCES;
}
/* Implementation for Start_instance */
2004-10-27 10:21:48 +04:00
Start_instance::Start_instance(Instance_map *instance_map_arg,
const char *name, uint len)
2004-10-27 10:21:48 +04:00
:Command(instance_map_arg)
{
/* we make a search here, since we don't want to store the name */
2004-12-12 20:59:15 +03:00
if ((instance= instance_map->find(name, len)))
instance_name= instance->options.instance_name;
}
int Start_instance::execute(struct st_net *net, ulong connection_id)
{
uint err_code;
if (instance == 0)
return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
else
{
if ((err_code= instance->start()))
return err_code;
if (!(instance->options.nonguarded))
2004-10-26 23:22:12 +04:00
instance_map->guardian->guard(instance);
net_send_ok(net, connection_id, "Instance started");
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;
}
2005-05-16 01:54:02 +04:00
/*
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;
2005-05-16 01:54:02 +04:00
uint position= 0;
/* create list of the fileds to be passed to send_fields */
2005-05-16 01:54:02 +04:00
name_field.name= (char*) "Log";
name_field.length= DEFAULT_FIELD_LENGTH;
name.data= &name_field;
field_list= list_add(NULL, &name);
2005-05-16 01:54:02 +04:00
if (!instance_name)
return ER_BAD_INSTANCE_NAME;
/* cannot read negative number of bytes */
if (offset > size)
2005-05-16 01:54:02 +04:00
return ER_OFFSET_ERROR;
send_fields(net, field_list);
{
Instance *instance;
const char *logpath;
File fd;
2005-05-16 01:54:02 +04:00
if ((instance= instance_map->find(instance_name,
strlen(instance_name))) == NULL)
goto err;
2005-05-16 01:54:02 +04:00
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;
2005-05-16 01:54:02 +04:00
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;
2005-05-16 01:54:02 +04:00
/* 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));
2005-05-16 01:54:02 +04:00
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;
}
2005-05-16 01:54:02 +04:00
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;
}
/*
2005-05-16 01:54:02 +04:00
The method sends a table with a list of log files
used by the instance.
SYNOPSYS
2005-05-16 01:54:02 +04:00
Show_instance_log_files::execute()
net The network connection to the client.
2005-05-16 01:54:02 +04:00
connection_id The ID of the client connection
RETURN
2005-05-16 01:54:02 +04:00
ER_BAD_INSTANCE_NAME The instance name specified is not valid
ER_OUT_OF_RESOURCES some error occured
0 - ok
*/
2005-05-16 01:54:02 +04:00
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;
2005-05-16 01:54:02 +04:00
uint position= 0;
if (!instance_name)
return ER_BAD_INSTANCE_NAME;
/* create list of the fileds to be passed to send_fields */
2005-05-16 01:54:02 +04:00
name_field.name= (char*) "Logfile";
name_field.length= DEFAULT_FIELD_LENGTH;
name.data= &name_field;
2005-05-16 01:54:02 +04:00
path_field.name= (char*) "Path";
path_field.length= DEFAULT_FIELD_LENGTH;
path.data= &path_field;
2005-05-16 01:54:02 +04:00
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
2005-05-16 01:54:02 +04:00
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[]=
{
2005-05-16 01:54:02 +04:00
{"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;
2005-05-16 01:54:02 +04:00
/*
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);
2005-05-16 01:54:02 +04:00
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,
2005-05-16 01:54:02 +04:00
(char*) log_files->value,
&position);
2005-05-16 01:54:02 +04:00
int10_to_str(file_stat.st_size, buff, 10);
store_to_string(&send_buff, (char*) buff, &position);
}
2005-05-16 01:54:02 +04:00
if (my_net_write(net, send_buff.buffer, (uint) position))
goto err;
}
}
}
2005-05-16 01:54:02 +04:00
if (send_eof(net) || net_flush(net))
goto err;
return 0;
err:
2005-05-16 01:54:02 +04:00
return ER_OUT_OF_RESOURCES;
}
2005-05-16 01:54:02 +04:00
/* 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))
{
2005-05-16 01:54:02 +04:00
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);
2005-05-16 01:54:02 +04:00
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;
}
}
/*
2005-05-16 01:54:02 +04:00
The method sends a table with a list of log files
used by the instance.
2005-05-16 01:54:02 +04:00
SYNOPSYS
Set_option::correct_file()
skip Skip the option, being searched while writing the result file.
That is, to delete it.
2005-05-16 01:54:02 +04:00
DESCRIPTION
2005-05-16 01:54:02 +04:00
Correct the option file. The "skip" option is used to remove the found
option.
2005-05-16 01:54:02 +04:00
RETURN
ER_BAD_INSTANCE_NAME The instance name specified is not valid
ER_ACCESS_OPTION_FILE Cannot access the option file
0 - ok
*/
2005-05-16 01:54:02 +04:00
int Set_option::correct_file(int skip)
{
int error;
2005-05-16 01:54:02 +04:00
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;
2005-05-16 01:54:02 +04:00
/* 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)
{
2005-05-16 01:54:02 +04:00
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)
{
2005-05-16 01:54:02 +04:00
return correct_file(TRUE);
}
/* Implementation for Stop_instance: */
2004-10-27 10:21:48 +04:00
Stop_instance::Stop_instance(Instance_map *instance_map_arg,
const char *name, uint len)
2004-10-27 10:21:48 +04:00
:Command(instance_map_arg)
{
/* we make a search here, since we don't want to store the name */
2004-12-12 20:59:15 +03:00
if ((instance= instance_map->find(name, len)))
instance_name= instance->options.instance_name;
}
int Stop_instance::execute(struct st_net *net, ulong connection_id)
{
uint err_code;
if (instance == 0)
return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
else
{
if (!(instance->options.nonguarded))
2004-10-26 23:22:12 +04:00
instance_map->guardian->
stop_guard(instance);
2004-12-12 20:59:15 +03:00
if ((err_code= instance->stop()))
return err_code;
net_send_ok(net, connection_id, NULL);
return 0;
}
}
int Syntax_error::execute(struct st_net *net, ulong connection_id)
{
return ER_SYNTAX_ERROR;
}