summaryrefslogtreecommitdiff
path: root/server-tools/instance-manager/parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'server-tools/instance-manager/parse.cc')
-rw-r--r--server-tools/instance-manager/parse.cc351
1 files changed, 265 insertions, 86 deletions
diff --git a/server-tools/instance-manager/parse.cc b/server-tools/instance-manager/parse.cc
index 14b3db16b45..4e931488fce 100644
--- a/server-tools/instance-manager/parse.cc
+++ b/server-tools/instance-manager/parse.cc
@@ -17,12 +17,12 @@
#include "parse.h"
#include "commands.h"
-#include <string.h>
-
enum Token
{
- TOK_ERROR= 0, /* Encodes the "ERROR" word, it doesn't indicate error. */
+ TOK_CREATE= 0,
+ TOK_DROP,
+ TOK_ERROR, /* Encodes the "ERROR" word, it doesn't indicate error. */
TOK_FILES,
TOK_FLUSH,
TOK_GENERAL,
@@ -50,6 +50,8 @@ struct tokens_st
static struct tokens_st tokens[]= {
+ {6, "CREATE"},
+ {4, "DROP"},
{5, "ERROR"},
{5, "FILES"},
{5, "FLUSH"},
@@ -67,6 +69,37 @@ static struct tokens_st tokens[]= {
{5, "UNSET"}
};
+/************************************************************************/
+
+Named_value_arr::Named_value_arr() :
+ initialized(FALSE)
+{
+}
+
+
+bool Named_value_arr::init()
+{
+ if (my_init_dynamic_array(&arr, sizeof(Named_value), 0, 32))
+ return TRUE;
+
+ initialized= TRUE;
+
+ return FALSE;
+}
+
+
+Named_value_arr::~Named_value_arr()
+{
+ if (!initialized)
+ return;
+
+ for (int i= 0; i < get_size(); ++i)
+ get_element(i).free();
+
+ delete_dynamic(&arr);
+}
+
+/************************************************************************/
/*
Returns token no if word corresponds to some token, otherwise returns
@@ -104,53 +137,200 @@ Token shift_token(const char **text, uint *word_len)
}
-int get_text_id(const char **text, uint *word_len, const char **id)
+int get_text_id(const char **text, LEX_STRING *token)
{
- get_word(text, word_len);
- if (*word_len == 0)
+ get_word(text, &token->length);
+ if (token->length == 0)
return 1;
- *id= *text;
+ token->str= (char *) *text;
return 0;
}
+static bool parse_long(const LEX_STRING *token, long *value)
+{
+ int err_code;
+ char *end_ptr= token->str + token->length;
+
+ *value= my_strtoll10(token->str, &end_ptr, &err_code);
+
+ return err_code != 0;
+}
+
+
+bool parse_option_value(const char *text, uint *text_len, char **value)
+{
+ char beginning_quote;
+ const char *text_start_ptr;
+ char *v;
+ bool escape_mode= FALSE;
+
+ if (!*text || (*text != '\'' && *text != '"'))
+ return TRUE; /* syntax error: string expected. */
+
+ beginning_quote= *text;
+
+ ++text; /* skip the beginning quote. */
+
+ text_start_ptr= text;
+
+ if (!(v= Named_value::alloc_str(text)))
+ return TRUE;
+
+ *value= v;
+
+ while (TRUE)
+ {
+ if (!*text)
+ {
+ Named_value::free_str(value);
+ return TRUE; /* syntax error: missing terminating ' character. */
+ }
+
+ if (*text == '\n' || *text == '\r')
+ {
+ Named_value::free_str(value);
+ return TRUE; /* syntax error: option value should be a single line. */
+ }
+
+ if (!escape_mode && *text == beginning_quote)
+ break;
+
+ if (escape_mode)
+ {
+ switch (*text)
+ {
+ case 'b': /* \b -- backspace */
+ if (v > *value)
+ --v;
+ break;
+
+ case 't': /* \t -- tab */
+ *v= '\t';
+ ++v;
+ break;
+
+ case 'n': /* \n -- newline */
+ *v= '\n';
+ ++v;
+ break;
+
+ case 'r': /* \r -- carriage return */
+ *v= '\r';
+ ++v;
+ break;
+
+ case '\\': /* \\ -- back slash */
+ *v= '\\';
+ ++v;
+ break;
+
+ case 's': /* \s -- space */
+ *v= ' ';
+ ++v;
+ break;
+
+ default: /* Unknown escape sequence. Treat as error. */
+ Named_value::free_str(value);
+ return TRUE;
+ }
+
+ escape_mode= FALSE;
+ }
+ else
+ {
+ if (*text == '\\')
+ {
+ escape_mode= TRUE;
+ }
+ else
+ {
+ *v= *text;
+ ++v;
+ }
+ }
+
+ ++text;
+ }
+
+ *v= 0;
+
+ /* "2" below stands for beginning and ending quotes. */
+ *text_len= text - text_start_ptr + 2;
+
+ return FALSE;
+}
+
+
+void skip_spaces(const char **text)
+{
+ while (**text && my_isspace(default_charset_info, **text))
+ ++(*text);
+}
+
+
Command *parse_command(Instance_map *map, 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;
+ LEX_STRING instance_name;
Command *command;
const char *saved_text= text;
- bool skip= false;
- const char *tmp;
Token tok1= shift_token(&text, &word_len);
switch (tok1) {
case TOK_START: // fallthrough
case TOK_STOP:
+ case TOK_CREATE:
+ case TOK_DROP:
if (shift_token(&text, &word_len) != TOK_INSTANCE)
goto syntax_error;
get_word(&text, &word_len);
if (word_len == 0)
goto syntax_error;
- instance_name= text;
- instance_name_len= word_len;
+ instance_name.str= (char *) text;
+ instance_name.length= word_len;
text+= word_len;
- /* it should be the end of command */
- get_word(&text, &word_len, NONSPACE);
- if (word_len)
- goto syntax_error;
- if (tok1 == TOK_START)
- command= new Start_instance(map, instance_name, instance_name_len);
+ if (tok1 == TOK_CREATE)
+ {
+ Create_instance *cmd= new Create_instance(map, &instance_name);
+
+ if (!cmd)
+ return NULL; /* Report ER_OUT_OF_RESOURCES. */
+
+ if (cmd->init(&text))
+ {
+ delete cmd;
+ goto syntax_error;
+ }
+
+ command= cmd;
+ }
else
- command= new Stop_instance(map, instance_name, instance_name_len);
+ {
+ /* it should be the end of command */
+ get_word(&text, &word_len, NONSPACE);
+ if (word_len)
+ goto syntax_error;
+ }
+
+ switch (tok1) {
+ case TOK_START:
+ command= new Start_instance(map, &instance_name);
+ break;
+ case TOK_STOP:
+ command= new Stop_instance(map, &instance_name);
+ break;
+ case TOK_CREATE:
+ ; /* command already initialized. */
+ break;
+ case TOK_DROP:
+ command= new Drop_instance(map, &instance_name);
+ break;
+ default: /* this is impossible, but nevertheless... */
+ DBUG_ASSERT(0);
+ }
break;
case TOK_FLUSH:
if (shift_token(&text, &word_len) != TOK_INSTANCES)
@@ -163,53 +343,28 @@ Command *parse_command(Instance_map *map, const char *text)
command= new Flush_instances(map);
break;
case TOK_UNSET:
- skip= true;
case TOK_SET:
+ {
+ Abstract_option_cmd *cmd;
- if (get_text_id(&text, &instance_name_len, &instance_name))
- goto syntax_error;
- text+= instance_name_len;
-
- /* the next token should be a dot */
- get_word(&text, &word_len);
- if (*text != '.')
- goto syntax_error;
- text++;
+ if (tok1 == TOK_SET)
+ cmd= new Set_option(map);
+ else
+ cmd= new Unset_option(map);
- get_word(&text, &option_len, NONSPACE);
- option= text;
- if ((tmp= strchr(text, '=')) != NULL)
- option_len= tmp - text;
- text+= option_len;
+ if (!cmd)
+ return NULL; /* Report ER_OUT_OF_RESOURCES. */
- 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;
- }
+ if (cmd->init(&text))
+ {
+ delete cmd;
+ goto syntax_error;
+ }
- /* should be empty */
- get_word(&text, &word_len, NONSPACE);
- if (word_len)
- goto syntax_error;
+ command= cmd;
- if (skip)
- command= new Unset_option(map, instance_name, instance_name_len,
- option, option_len, option_value,
- option_value_len);
- else
- command= new Set_option(map, instance_name, instance_name_len,
- option, option_len, option_value,
- option_value_len);
- break;
+ break;
+ }
case TOK_SHOW:
switch (shift_token(&text, &word_len)) {
case TOK_INSTANCES:
@@ -222,30 +377,35 @@ Command *parse_command(Instance_map *map, const char *text)
switch (Token tok2= shift_token(&text, &word_len)) {
case TOK_OPTIONS:
case TOK_STATUS:
- if (get_text_id(&text, &instance_name_len, &instance_name))
+ if (get_text_id(&text, &instance_name))
goto syntax_error;
- text+= instance_name_len;
+ text+= instance_name.length;
/* check that this is the end of the command */
get_word(&text, &word_len, NONSPACE);
if (word_len)
goto syntax_error;
if (tok2 == TOK_STATUS)
- command= new Show_instance_status(map, instance_name,
- instance_name_len);
+ command= new Show_instance_status(map, &instance_name);
else
- command= new Show_instance_options(map, instance_name,
- instance_name_len);
+ command= new Show_instance_options(map, &instance_name);
break;
default:
goto syntax_error;
}
break;
default:
- instance_name= text - word_len;
- instance_name_len= word_len;
- if (instance_name_len)
+ instance_name.str= (char *) text - word_len;
+ instance_name.length= word_len;
+ if (instance_name.length)
{
Log_type log_type;
+
+ long log_size;
+ LEX_STRING log_size_str;
+
+ long log_offset= 0;
+ LEX_STRING log_offset_str= { NULL, 0 };
+
switch (shift_token(&text, &word_len)) {
case TOK_LOG:
switch (Token tok3= shift_token(&text, &word_len)) {
@@ -254,8 +414,7 @@ Command *parse_command(Instance_map *map, const char *text)
/* check that this is the end of the command */
if (word_len)
goto syntax_error;
- command= new Show_instance_log_files(map, instance_name,
- instance_name_len);
+ command= new Show_instance_log_files(map, &instance_name);
break;
case TOK_ERROR:
case TOK_GENERAL:
@@ -275,12 +434,14 @@ Command *parse_command(Instance_map *map, const char *text)
goto syntax_error;
}
/* get the size of the log we want to retrieve */
- if (get_text_id(&text, &word_len, &log_size))
+ if (get_text_id(&text, &log_size_str))
goto syntax_error;
- text+= word_len;
+ text+= log_size_str.length;
+
/* this parameter is required */
- if (!word_len)
+ if (!log_size_str.length)
goto syntax_error;
+
/* the next token should be comma, or nothing */
get_word(&text, &word_len);
switch (*text) {
@@ -290,23 +451,41 @@ Command *parse_command(Instance_map *map, const char *text)
get_word(&text, &word_len);
if (!word_len)
goto syntax_error;
+ log_offset_str.str= (char *) text;
+ log_offset_str.length= word_len;
text+= word_len;
- command= new Show_instance_log(map, instance_name,
- instance_name_len, log_type,
- log_size, text);
get_word(&text, &word_len, NONSPACE);
/* check that this is the end of the command */
if (word_len)
goto syntax_error;
break;
case '\0':
- command= new Show_instance_log(map, instance_name,
- instance_name_len, log_type,
- log_size, NULL);
break; /* this is ok */
default:
+ goto syntax_error;
+ }
+
+ /* Parse size parameter. */
+
+ if (parse_long(&log_size_str, &log_size))
+ goto syntax_error;
+
+ if (log_size <= 0)
goto syntax_error;
+
+ /* Parse offset parameter (if specified). */
+
+ if (log_offset_str.length)
+ {
+ if (parse_long(&log_offset_str, &log_offset))
+ goto syntax_error;
+
+ if (log_offset <= 0)
+ goto syntax_error;
}
+
+ command= new Show_instance_log(map, &instance_name,
+ log_type, log_size, log_offset);
break;
default:
goto syntax_error;