diff options
Diffstat (limited to 'server-tools')
-rw-r--r-- | server-tools/instance-manager/instance.cc | 36 | ||||
-rw-r--r-- | server-tools/instance-manager/instance_options.cc | 13 | ||||
-rw-r--r-- | server-tools/instance-manager/parse_output.cc | 401 | ||||
-rw-r--r-- | server-tools/instance-manager/parse_output.h | 16 | ||||
-rw-r--r-- | server-tools/instance-manager/portability.h | 5 |
5 files changed, 377 insertions, 94 deletions
diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index edc9c88fe9f..80e7e99214b 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -524,24 +524,17 @@ bool Instance::init(const LEX_STRING *name_arg) /** - Complete instance options initialization. + @brief Complete instance options initialization. - SYNOPSIS - complete_initialization() - - RETURN - FALSE - ok - TRUE - error + @return Error status. + @retval FALSE ok + @retval TRUE error */ bool Instance::complete_initialization() { configured= ! options.complete_initialization(); - return FALSE; - /* - TODO: return actual status (from - Instance_options::complete_initialization()) here. - */ + return !configured; } /************************************************************************** @@ -644,25 +637,24 @@ bool Instance::is_mysqld_running() /** - Start mysqld. + @brief Start mysqld. - SYNOPSIS - start_mysqld() - - DESCRIPTION - Reset flags and start Instance Monitor thread, which will start mysqld. + Reset flags and start Instance Monitor thread, which will start mysqld. - MT-NOTE: instance must be locked before calling the operation. + @note Instance must be locked before calling the operation. - RETURN - FALSE - ok - TRUE - could not start instance + @return Error status code + @retval FALSE Ok + @retval TRUE Could not start instance */ bool Instance::start_mysqld() { Instance_monitor *instance_monitor; + if (!configured) + return TRUE; + /* Prepare instance to start Instance Monitor thread. diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index 5665c6f8670..8b96d6f0f96 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -156,7 +156,8 @@ int Instance_options::get_default_option(char *result, size_t result_len, goto err; /* +2 eats first "--" from the option string (E.g. "--datadir") */ - rc= parse_output_and_get_value((char*) cmd.buffer, option_name + 2, + rc= parse_output_and_get_value((char*) cmd.buffer, + option_name + 2, strlen(option_name + 2), result, result_len, GET_VALUE); err: return rc; @@ -194,8 +195,8 @@ bool Instance_options::fill_instance_version() bzero(result, MAX_VERSION_LENGTH); - if (parse_output_and_get_value((char*) cmd.buffer, "Ver", result, - MAX_VERSION_LENGTH, GET_LINE)) + if (parse_output_and_get_value((char*) cmd.buffer, STRING_WITH_LEN("Ver"), + result, MAX_VERSION_LENGTH, GET_LINE)) { log_error("Failed to get version of '%s': unexpected output.", (const char *) mysqld_path.str); @@ -206,8 +207,7 @@ bool Instance_options::fill_instance_version() { char *start; - /* chop the newline from the end of the version string */ - result[strlen(result) - NEWLINE_LEN]= '\0'; + /* trim leading whitespaces */ start= result; while (my_isspace(default_charset_info, *start)) @@ -255,7 +255,8 @@ bool Instance_options::fill_mysqld_real_path() bzero(result, FN_REFLEN); - if (parse_output_and_get_value((char*) cmd.buffer, "Usage: ", + if (parse_output_and_get_value((char*) cmd.buffer, + STRING_WITH_LEN("Usage: "), result, FN_REFLEN, GET_LINE)) { diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index 36eb5185f6b..4dc67657512 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -24,6 +24,13 @@ #include "parse.h" #include "portability.h" +/************************************************************************** + Private module implementation. +**************************************************************************/ + +namespace { /* no-indent */ + +/*************************************************************************/ void trim_space(const char **text, uint *word_len) { @@ -39,90 +46,362 @@ void trim_space(const char **text, uint *word_len) *word_len= (end - start)+1; } -/* - Parse output of the given command +/*************************************************************************/ - SYNOPSIS - parse_output_and_get_value() +/** + @brief A facade to the internal workings of optaining the output from an + executed system process. +*/ - command the command to execue with popen. - word the word to look for (usually an option name) - result the buffer to store the next word (option value) - input_buffer_len self-explanatory - flag this equals to GET_LINE if we want to get all the line after - the matched word and GET_VALUE otherwise. +class Mysqld_output_parser +{ +public: + Mysqld_output_parser() + { } - DESCRIPTION + virtual ~Mysqld_output_parser() + { } - Parse output of the "command". Find the "word" and return the next one - if flag is GET_VALUE. Return the rest of the parsed string otherwise. +public: + bool parse(const char *command, + const char *option_name_str, + uint option_name_length, + char *option_value_buf, + size_t option_value_buf_size, + enum_option_type option_type); - RETURN - 0 - ok, the word has been found - 1 - error occured or the word is not found -*/ +protected: + /** + @brief Run a process and attach stdout- and stdin-pipes to it. -int parse_output_and_get_value(const char *command, const char *word, - char *result, size_t input_buffer_len, - uint flag) -{ - FILE *output; - uint wordlen; - /* should be enough to store the string from the output */ - enum { MAX_LINE_LEN= 512 }; - char linebuf[MAX_LINE_LEN]; - int rc= 1; + @param command The path to the process to be executed - wordlen= strlen(word); + @return Error status. + @retval TRUE An error occurred + @retval FALSE Operation was a success + */ - /* - Successful return of popen does not tell us whether the command has been - executed successfully: if the command was not found, we'll get EOF - when reading the output buffer below. + virtual bool run_command(const char *command)= 0; + + + /** + @brief Read a sequence of bytes from the executed process' stdout pipe. + + The sequence is terminated by either '\0', LF or CRLF tokens. The + terminating token is excluded from the result. + + @param line_buffer A pointer to a character buffer + @param line_buffer_size The size of the buffer in bytes + + @return Error status. + @retval TRUE An error occured + @retval FALSE Operation was a success */ - if (!(output= popen(command, "r"))) - goto err; - /* - We want fully buffered stream. We also want system to - allocate appropriate buffer. + virtual bool read_line(char *line_buffer, + uint line_buffer_size)= 0; + + + /** + @brief Release any resources needed after a execution and parsing. */ - setvbuf(output, NULL, _IOFBF, 0); - while (fgets(linebuf, sizeof(linebuf) - 1, output)) + virtual bool cleanup()= 0; +}; + +/*************************************************************************/ + +bool Mysqld_output_parser::parse(const char *command, + const char *option_name_str, + uint option_name_length, + char *option_value_buf, + size_t option_value_buf_size, + enum_option_type option_type) +{ + /* should be enough to store the string from the output */ + const int LINE_BUFFER_SIZE= 512; + char line_buffer[LINE_BUFFER_SIZE]; + + if (run_command(command)) + return TRUE; + + while (true) { + if (read_line(line_buffer, LINE_BUFFER_SIZE)) + { + cleanup(); + return TRUE; + } + uint found_word_len= 0; - char *linep= linebuf; + char *linep= line_buffer; + + line_buffer[sizeof(line_buffer) - 1]= '\0'; /* safety */ + + /* Find the word(s) we are looking for in the line. */ - linebuf[sizeof(linebuf) - 1]= '\0'; /* safety */ + linep= strstr(linep, option_name_str); - /* - Find the word(s) we are looking for in the line - */ - if ((linep= strstr(linep, word))) + if (!linep) + continue; + + linep+= option_name_length; + + switch (option_type) { - /* - If we have found our word(s), then move linep past the word(s) - */ - linep+= wordlen; - if (flag & GET_VALUE) + case GET_VALUE: + trim_space((const char**) &linep, &found_word_len); + + if (option_value_buf_size <= found_word_len) { - trim_space((const char**) &linep, &found_word_len); - if (input_buffer_len <= found_word_len) - goto err; - strmake(result, linep, found_word_len); + cleanup(); + return TRUE; } - else /* currently there are only two options */ - strmake(result, linep, input_buffer_len - 1); - rc= 0; + + strmake(option_value_buf, linep, found_word_len); + + break; + + case GET_LINE: + strmake(option_value_buf, linep, option_value_buf_size - 1); + break; } + + cleanup(); + + return FALSE; } +} + +/************************************************************************** + Platform-specific implementation: UNIX. +**************************************************************************/ + +#ifndef __WIN__ + +class Mysqld_output_parser_unix : public Mysqld_output_parser +{ +public: + Mysqld_output_parser_unix() : + m_stdout(NULL) + { } + +protected: + virtual bool run_command(const char *command); + + virtual bool read_line(char *line_buffer, + uint line_buffer_size); + + virtual bool cleanup(); + +private: + FILE *m_stdout; +}; + +bool Mysqld_output_parser_unix::run_command(const char *command) +{ + if (!(m_stdout= popen(command, "r"))) + return TRUE; - /* we are not interested in the termination status */ - pclose(output); + /* + We want fully buffered stream. We also want system to allocate + appropriate buffer. + */ -err: - return rc; + setvbuf(m_stdout, NULL, _IOFBF, 0); + + return FALSE; } +bool Mysqld_output_parser_unix::read_line(char *line_buffer, + uint line_buffer_size) +{ + char *retbuff = fgets(line_buffer, line_buffer_size, m_stdout); + /* Remove any tailing new line charaters */ + if (line_buffer[line_buffer_size-1] == LF) + line_buffer[line_buffer_size-1]= '\0'; + return (retbuff == NULL); +} + +bool Mysqld_output_parser_unix::cleanup() +{ + if (m_stdout) + pclose(m_stdout); + + return FALSE; +} + +#else /* Windows */ + +/************************************************************************** + Platform-specific implementation: Windows. +**************************************************************************/ + +class Mysqld_output_parser_win : public Mysqld_output_parser +{ +public: + Mysqld_output_parser_win() : + m_internal_buffer(NULL), + m_internal_buffer_offset(0), + m_internal_buffer_size(0) + { } + +protected: + virtual bool run_command(const char *command); + virtual bool read_line(char *line_buffer, + uint line_buffer_size); + virtual bool cleanup(); + +private: + HANDLE m_h_child_stdout_wr; + HANDLE m_h_child_stdout_rd; + uint m_internal_buffer_offset; + uint m_internal_buffer_size; + char *m_internal_buffer; +}; + +bool Mysqld_output_parser_win::run_command(const char *command) +{ + BOOL op_status; + + SECURITY_ATTRIBUTES sa_attr; + sa_attr.nLength= sizeof(SECURITY_ATTRIBUTES); + sa_attr.bInheritHandle= TRUE; + sa_attr.lpSecurityDescriptor= NULL; + + op_status= CreatePipe(&m_h_child_stdout_rd, + &m_h_child_stdout_wr, + &sa_attr, + 0 /* Use system-default buffer size. */); + + if (!op_status) + return TRUE; + + SetHandleInformation(m_h_child_stdout_rd, HANDLE_FLAG_INHERIT, 0); + + STARTUPINFO si_start_info; + ZeroMemory(&si_start_info, sizeof(STARTUPINFO)); + si_start_info.cb= sizeof(STARTUPINFO); + si_start_info.hStdError= m_h_child_stdout_wr; + si_start_info.hStdOutput= m_h_child_stdout_wr; + si_start_info.dwFlags|= STARTF_USESTDHANDLES; + + PROCESS_INFORMATION pi_proc_info; + + op_status= CreateProcess(NULL, /* Application name. */ + (char*)command, /* Command line. */ + NULL, /* Process security attributes. */ + NULL, /* Primary thread security attr.*/ + TRUE, /* Handles are inherited. */ + 0, /* Creation flags. */ + NULL, /* Use parent's environment. */ + NULL, /* Use parent's curr. directory. */ + &si_start_info, /* STARTUPINFO pointer. */ + &pi_proc_info); /* Rec. PROCESS_INFORMATION. */ + + if (!retval) + { + CloseHandle(m_h_child_stdout_rd); + CloseHandle(m_h_child_stdout_wr); + + return TRUE; + } + + /* Close unnessary handles. */ + + CloseHandle(pi_proc_info.hProcess); + CloseHandle(pi_proc_info.hThread); + + return FALSE; +} + +bool Mysqld_output_parser_win::read_line(char *line_buffer, + uint line_buffer_size) +{ + DWORD dw_read_count= m_internal_buffer_size; + bzero(line_buffer,line_buffer_size); + char *buff_ptr= line_buffer; + char ch; + + while (buff_ptr - line_buffer < line_buffer_size) + { + do + { + ReadFile(m_h_child_stdout_rd, &ch, + 1, &dw_read_count, NULL); + } while ((ch == CR || ch == LF) && buff_ptr == line_buffer); + + if (dw_read_count == 0) + return TRUE; + + if (ch == CR || ch == LF) + break; + + *buff_ptr++ = ch; + } + + return FALSE; +} + +bool Mysqld_output_parser_win::cleanup() +{ + /* Close all handles. */ + + CloseHandle(m_h_child_stdout_wr); + CloseHandle(m_h_child_stdout_rd); + + return FALSE; +} +#endif + +/*************************************************************************/ + +} /* End of private module implementation. */ + +/*************************************************************************/ + +/** + @brief Parse output of the given command + + @param command The command to execute. + @param option_name_str Option name. + @param option_name_length Length of the option name. + @param[out] option_value_buf The buffer to store option value. + @param option_value_buf_size Size of the option value buffer. + @param option_type Type of the option: + - GET_LINE if we want to get all the + line after the option name; + - GET_VALUE otherwise. + + Execute the process by running "command". Find the "option name" and + return the next word if "option_type" is GET_VALUE. Return the rest of + the parsed string otherwise. + + @note This function has a separate windows implementation. + + @return The error status. + @retval FALSE Ok, the option name has been found. + @retval TRUE Error occured or the option name is not found. +*/ + +bool parse_output_and_get_value(const char *command, + const char *option_name_str, + uint option_name_length, + char *option_value_buf, + size_t option_value_buf_size, + enum_option_type option_type) +{ +#ifndef __WIN__ + Mysqld_output_parser_unix parser; +#else /* __WIN__ */ + Mysqld_output_parser_win parser; +#endif + + return parser.parse(command, + option_name_str, + option_name_length, + option_value_buf, + option_value_buf_size, + option_type); +} diff --git a/server-tools/instance-manager/parse_output.h b/server-tools/instance-manager/parse_output.h index 8851934f230..41618f643a3 100644 --- a/server-tools/instance-manager/parse_output.h +++ b/server-tools/instance-manager/parse_output.h @@ -17,11 +17,17 @@ #include <my_global.h> -#define GET_VALUE 1 -#define GET_LINE 2 +enum enum_option_type +{ + GET_VALUE = 1, + GET_LINE +}; -int parse_output_and_get_value(const char *command, const char *word, - char *result, size_t input_buffer_len, - uint flag); +bool parse_output_and_get_value(const char *command, + const char *option_name_str, + uint option_name_length, + char *option_value_buf, + size_t option_value_buf_size, + enum_option_type option_type); #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H */ diff --git a/server-tools/instance-manager/portability.h b/server-tools/instance-manager/portability.h index eb677a0135c..990e6140a9e 100644 --- a/server-tools/instance-manager/portability.h +++ b/server-tools/instance-manager/portability.h @@ -48,11 +48,16 @@ typedef int pid_t; #define NEWLINE "\r\n" #define NEWLINE_LEN 2 +const char CR = '\r'; +const char LF = '\n'; + #else /* ! __WIN__ */ #define NEWLINE "\n" #define NEWLINE_LEN 1 +const char LF = '\n'; + #endif /* __WIN__ */ #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PORTABILITY_H */ |