Below is the list of changes that have just been committed into a local
5.1 repository of alik. When alik does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2192 06/03/18 20:53:21 anozdrin@stripped +32 -0
Draft patch for WL#3158 / WL#3159.
server-tools/instance-manager/exit_codes.h
1.1 06/03/18 20:53:16 anozdrin@stripped +16 -0
q
server-tools/instance-manager/user_map.h
1.6 06/03/18 20:53:16 anozdrin@stripped +22 -1
q
server-tools/instance-manager/user_map.cc
1.16 06/03/18 20:53:16 anozdrin@stripped +63 -27
qq
server-tools/instance-manager/priv.h
1.11 06/03/18 20:53:16 anozdrin@stripped +3 -0
q
server-tools/instance-manager/priv.cc
1.11 06/03/18 20:53:16 anozdrin@stripped +1 -1
q
server-tools/instance-manager/portability.h
1.9 06/03/18 20:53:16 anozdrin@stripped +9 -0
q
server-tools/instance-manager/parse.h
1.7 06/03/18 20:53:16 anozdrin@stripped +49 -4
q
server-tools/instance-manager/parse.cc
1.14 06/03/18 20:53:16 anozdrin@stripped +256 -14
q
server-tools/instance-manager/options.h
1.15 06/03/18 20:53:16 anozdrin@stripped +18 -0
q
server-tools/instance-manager/options.cc
1.31 06/03/18 20:53:16 anozdrin@stripped +302 -29
q
server-tools/instance-manager/mysql_manager_error.h
1.4 06/03/18 20:53:16 anozdrin@stripped +6 -0
q
server-tools/instance-manager/mysql_connection.cc
1.15 06/03/18 20:53:16 anozdrin@stripped +1 -1
q
server-tools/instance-manager/messages.cc
1.6 06/03/18 20:53:16 anozdrin@stripped +13 -0
q
server-tools/instance-manager/manager.cc
1.32 06/03/18 20:53:16 anozdrin@stripped +16 -1
q
server-tools/instance-manager/instance_options.h
1.19 06/03/18 20:53:16 anozdrin@stripped +48 -6
q
server-tools/instance-manager/exit_codes.h
1.0 06/03/18 20:53:16 anozdrin@stripped +0 -0
BitKeeper file /mnt/hda4/home/alik/MySQL/devel/5.1-wl3158/server-tools/instance-manager/exit_codes.h
server-tools/instance-manager/instance_options.cc
1.31 06/03/18 20:53:15 anozdrin@stripped +153 -79
q
server-tools/instance-manager/instance_map.h
1.19 06/03/18 20:53:15 anozdrin@stripped +12 -0
q
server-tools/instance-manager/instance_map.cc
1.27 06/03/18 20:53:15 anozdrin@stripped +45 -30
q
server-tools/instance-manager/instance.h
1.16 06/03/18 20:53:15 anozdrin@stripped +5 -0
q
server-tools/instance-manager/instance.cc
1.33 06/03/18 20:53:15 anozdrin@stripped +27 -6
q
server-tools/instance-manager/guardian.h
1.13 06/03/18 20:53:15 anozdrin@stripped +6 -0
q
server-tools/instance-manager/guardian.cc
1.21 06/03/18 20:53:15 anozdrin@stripped +49 -24
q
server-tools/instance-manager/commands.h
1.10 06/03/18 20:53:15 anozdrin@stripped +52 -3
q
server-tools/instance-manager/commands.cc
1.34 06/03/18 20:53:15 anozdrin@stripped +382 -74
q
mysys/default_modify.c
1.12 06/03/18 20:53:15 anozdrin@stripped +40 -15
q
mysys/default.c
1.79 06/03/18 20:53:15 anozdrin@stripped +9 -1
q
mysql-test/t/im_life_cycle.imtest
1.6 06/03/18 20:53:15 anozdrin@stripped +46 -13
q
mysql-test/r/im_utils.result
1.4 06/03/18 20:53:15 anozdrin@stripped +4 -6
q
mysql-test/r/im_life_cycle.result
1.6 06/03/18 20:53:15 anozdrin@stripped +69 -37
q
mysql-test/r/im_daemon_life_cycle.result
1.2 06/03/18 20:53:15 anozdrin@stripped +3 -3
q
mysql-test/mysql-test-run.pl
1.89 06/03/18 20:53:15 anozdrin@stripped +1 -1
q
include/my_sys.h
1.189 06/03/18 20:53:15 anozdrin@stripped +4 -0
q
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: anozdrin
# Host: booka.home
# Root: /mnt/hda4/home/alik/MySQL/devel/5.1-wl3158
--- 1.188/include/my_sys.h 2006-02-25 00:20:42 +03:00
+++ 1.189/include/my_sys.h 2006-03-18 20:53:15 +03:00
@@ -76,6 +76,10 @@
#define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */
#define MY_GIVE_INFO 2 /* Give time info about process*/
+#define MY_REMOVE_NONE 0 /* Params for modify_defaults_file */
+#define MY_REMOVE_OPTION 1
+#define MY_REMOVE_SECTION 2
+
#define ME_HIGHBYTE 8 /* Shift for colours */
#define ME_NOCUR 1 /* Don't use curses message */
#define ME_OLDWIN 2 /* Use old window */
--- 1.78/mysys/default.c 2005-10-06 12:25:57 +04:00
+++ 1.79/mysys/default.c 2006-03-18 20:53:15 +03:00
@@ -244,7 +244,8 @@
handle_option_ctx structure.
group_name The name of the group the option belongs to.
option The very option to be processed. It is already
- prepared to be used in argv (has -- prefix)
+ prepared to be used in argv (has -- prefix). If it
+ is NULL, we are handling a new group (section).
DESCRIPTION
This handler checks whether a group is one of the listed and adds an option
@@ -263,6 +264,9 @@
char *tmp;
struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
+ if (!option)
+ return 0;
+
if (find_type((char *)group_name, ctx->group, 3))
{
if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1)))
@@ -719,6 +723,10 @@
end[0]=0;
strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096));
+
+ /* signal that a new group is found */
+ opt_handler(handler_ctx, curr_gr, NULL);
+
continue;
}
if (!found_group)
--- 1.1/mysql-test/r/im_daemon_life_cycle.result 2005-10-01 01:14:36 +04:00
+++ 1.2/mysql-test/r/im_daemon_life_cycle.result 2006-03-18 20:53:15 +03:00
@@ -1,7 +1,7 @@
SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 offline
+instance_name status managed
+mysqld1 online 1
+mysqld2 offline 0
Killing the process...
Sleeping...
Success: the process was restarted.
--- 1.5/mysql-test/r/im_life_cycle.result 2006-02-18 18:00:18 +03:00
+++ 1.6/mysql-test/r/im_life_cycle.result 2006-03-18 20:53:15 +03:00
@@ -1,67 +1,99 @@
-SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 offline
+
+--------------------------------------------------------------------
+-- 1.1.1.
+--------------------------------------------------------------------
+SHOW INSTANCES;
+instance_name status managed
+mysqld1 online 1
+mysqld2 offline 0
SHOW INSTANCE STATUS mysqld1;
-instance_name status version_number version
-mysqld1 online VERSION_NUMBER VERSION
+instance_name status version_number version managed
+mysqld1 online VERSION_NUMBER VERSION 1
SHOW INSTANCE STATUS mysqld2;
-instance_name status version_number version
-mysqld2 offline VERSION_NUMBER VERSION
+instance_name status version_number version managed
+mysqld2 offline VERSION_NUMBER VERSION 0
+
+--------------------------------------------------------------------
+-- 1.1.2.
+--------------------------------------------------------------------
START INSTANCE mysqld2;
SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 online
+instance_name status managed
+mysqld1 online 1
+mysqld2 online 0
SHOW INSTANCE STATUS mysqld1;
-instance_name status version_number version
-mysqld1 online VERSION_NUMBER VERSION
+instance_name status version_number version managed
+mysqld1 online VERSION_NUMBER VERSION 1
SHOW INSTANCE STATUS mysqld2;
-instance_name status version_number version
-mysqld2 online VERSION_NUMBER VERSION
+instance_name status version_number version managed
+mysqld2 online VERSION_NUMBER VERSION 0
SHOW VARIABLES LIKE 'port';
Variable_name Value
-port IM_MYSQLD1_PORT
+port IM_MYSQLD2_PORT
+
+--------------------------------------------------------------------
+-- 1.1.3.
+--------------------------------------------------------------------
STOP INSTANCE mysqld2;
SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 offline
+instance_name status managed
+mysqld1 online 1
+mysqld2 offline 0
SHOW INSTANCE STATUS mysqld1;
-instance_name status version_number version
-mysqld1 online VERSION_NUMBER VERSION
+instance_name status version_number version managed
+mysqld1 online VERSION_NUMBER VERSION 1
SHOW INSTANCE STATUS mysqld2;
-instance_name status version_number version
-mysqld2 offline VERSION_NUMBER VERSION
+instance_name status version_number version managed
+mysqld2 offline VERSION_NUMBER VERSION 0
+
+--------------------------------------------------------------------
+-- 1.1.4.
+--------------------------------------------------------------------
START INSTANCE mysqld3;
ERROR HY000: Bad instance name. Check that the instance with such a name exists
START INSTANCE mysqld1;
ERROR HY000: The instance is already started
+
+--------------------------------------------------------------------
+-- 1.1.5.
+--------------------------------------------------------------------
STOP INSTANCE mysqld3;
ERROR HY000: Bad instance name. Check that the instance with such a name exists
-SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 offline
+
+--------------------------------------------------------------------
+-- 1.1.6.
+--------------------------------------------------------------------
+SHOW INSTANCES;
+instance_name status managed
+mysqld1 online 1
+mysqld2 offline 0
Killing the process...
Sleeping...
Success: the process was restarted.
-SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 offline
+
+--------------------------------------------------------------------
+-- 1.1.7.
+--------------------------------------------------------------------
+SHOW INSTANCES;
+instance_name status managed
+mysqld1 online 1
+mysqld2 offline 0
START INSTANCE mysqld2;
SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 online
+instance_name status managed
+mysqld1 online 1
+mysqld2 online 0
Killing the process...
Sleeping...
Success: the process was killed.
SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 offline
+instance_name status managed
+mysqld1 online 1
+mysqld2 offline 0
+
+--------------------------------------------------------------------
+-- 1.1.8.
+--------------------------------------------------------------------
SHOW INSTANCE STATUS;
ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
START INSTANCE mysqld1,mysqld2,mysqld3;
--- 1.3/mysql-test/r/im_utils.result 2006-01-27 13:41:11 +03:00
+++ 1.4/mysql-test/r/im_utils.result 2006-03-18 20:53:15 +03:00
@@ -1,11 +1,10 @@
SHOW INSTANCES;
-instance_name status
-mysqld1 online
-mysqld2 offline
+instance_name status managed
+mysqld1 online 1
+mysqld2 offline 0
SHOW INSTANCE OPTIONS mysqld1;
option_name value
instance_name VALUE
-mysqld-path VALUE
socket VALUE
pid-file VALUE
port VALUE
@@ -25,8 +24,6 @@
SHOW INSTANCE OPTIONS mysqld2;
option_name value
instance_name VALUE
-mysqld-path VALUE
-nonguarded VALUE
socket VALUE
pid-file VALUE
port VALUE
@@ -42,6 +39,7 @@
skip-innodb VALUE
skip-bdb VALUE
skip-ndbcluster VALUE
+nonguarded VALUE
log-output VALUE
START INSTANCE mysqld2;
STOP INSTANCE mysqld2;
--- 1.5/mysql-test/t/im_life_cycle.imtest 2006-02-18 18:00:18 +03:00
+++ 1.6/mysql-test/t/im_life_cycle.imtest 2006-03-18 20:53:15 +03:00
@@ -17,6 +17,11 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.1.
+--echo --------------------------------------------------------------------
+
SHOW INSTANCES;
--replace_column 3 VERSION_NUMBER 4 VERSION
SHOW INSTANCE STATUS mysqld1;
@@ -33,6 +38,11 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.2.
+--echo --------------------------------------------------------------------
+
START INSTANCE mysqld2;
# FIXME
--sleep 3
@@ -43,10 +53,10 @@
--replace_column 3 VERSION_NUMBER 4 VERSION
SHOW INSTANCE STATUS mysqld2;
---connect (mysql_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
+--connect (mysql_con,localhost,root,,mysql,$IM_MYSQLD2_PORT,$IM_MYSQLD2_SOCK)
--connection mysql_con
---replace_result $IM_MYSQLD1_PORT IM_MYSQLD1_PORT
+--replace_result $IM_MYSQLD2_PORT IM_MYSQLD2_PORT
SHOW VARIABLES LIKE 'port';
--connection default
@@ -61,6 +71,11 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.3.
+--echo --------------------------------------------------------------------
+
STOP INSTANCE mysqld2;
# FIXME
--sleep 3
@@ -81,16 +96,17 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.4.
+--echo --------------------------------------------------------------------
+
--error 3000
START INSTANCE mysqld3;
--error 3002
START INSTANCE mysqld1;
-# FIXME TODO
-# BUG#12813: START/STOP INSTANCE commands accept a list as argument
-# START INSTANCE mysqld1, mysqld2;
-
###########################################################################
#
# 1.1.5. Check that Instance Manager reports correct errors for 'STOP INSTANCE'
@@ -101,6 +117,11 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.5.
+--echo --------------------------------------------------------------------
+
--error 3000
STOP INSTANCE mysqld3;
@@ -109,16 +130,17 @@
# --error 3002
# STOP INSTANCE mysqld2;
-# FIXME TODO
-# BUG#12813: START/STOP INSTANCE commands accept a list as argument
-# STOP INSTANCE mysqld1, mysqld2;
-
###########################################################################
#
# 1.1.6. Check that Instance Manager is able to restart guarded instances.
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.6.
+--echo --------------------------------------------------------------------
+
SHOW INSTANCES;
--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted
@@ -129,6 +151,11 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.7.
+--echo --------------------------------------------------------------------
+
SHOW INSTANCES;
START INSTANCE mysqld2;
@@ -147,7 +174,13 @@
# incomplete SHOW INSTANCE STATUS command.
#
###########################################################################
---error 1149
+
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.8.
+--echo --------------------------------------------------------------------
+
+--error ER_SYNTAX_ERROR
SHOW INSTANCE STATUS;
#
@@ -159,8 +192,8 @@
# a list as argument.
#
---error 1149
+--error ER_SYNTAX_ERROR
START INSTANCE mysqld1,mysqld2,mysqld3;
---error 1149
+--error ER_SYNTAX_ERROR
STOP INSTANCE mysqld1,mysqld2,mysqld3;
--- New file ---
+++ server-tools/instance-manager/exit_codes.h 06/03/18 20:53:16
#ifndef __EXIT_CODES_H__
#define __EXIT_CODES_H__
const int ERR_OK = 0;
const int ERR_OUT_OF_MEMORY = 1;
const int ERR_INVALID_USAGE = 2;
const int ERR_INTERNAL_ERROR = 3;
const int ERR_IO_ERROR = 4;
const int ERR_PASSWORD_FILE_CORRUPTED = 5;
const int ERR_CAN_NOT_READ_USER_NAME = 10;
const int ERR_CAN_NOT_READ_PASSWORD = 11;
const int ERR_USER_ALREADY_EXISTS = 12;
#endif // __EXIT_CODES_H__
--- 1.11/mysys/default_modify.c 2006-01-03 19:54:34 +03:00
+++ 1.12/mysys/default_modify.c 2006-03-18 20:53:15 +03:00
@@ -40,11 +40,13 @@
SYNOPSYS
modify_defaults_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.
+ option The name of the option to look for (can be NULL)
+ option value The value of the option we would like to set (can be NULL)
+ section_name The name of the section (must be NOT NULL)
+ remove_option This defines what we want to remove:
+ - MY_REMOVE_NONE -- nothing to remove;
+ - MY_REMOVE_OPTION -- remove the specified option;
+ - MY_REMOVE_SECTION -- remove the specified section;
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
@@ -67,7 +69,9 @@
FILE *cnf_file;
MY_STAT file_stat;
char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer;
- uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size;
+ uint opt_len= 0;
+ uint optval_len= 0;
+ uint sect_len, nr_newlines= 0, buffer_size;
my_bool in_section= FALSE, opt_applied= 0;
uint reserve_extended;
uint new_opt_len;
@@ -81,8 +85,11 @@
if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
goto malloc_err;
- opt_len= (uint) strlen(option);
- optval_len= (uint) strlen(option_value);
+ if (option && option_value)
+ {
+ opt_len= (uint) strlen(option);
+ optval_len= (uint) strlen(option_value);
+ }
new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN;
@@ -119,8 +126,8 @@
continue;
}
- /* correct the option */
- if (in_section && !strncmp(src_ptr, option, opt_len) &&
+ /* correct the option (if requested) */
+ if (option && in_section && !strncmp(src_ptr, option, opt_len) &&
(*(src_ptr + opt_len) == '=' ||
my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) ||
*(src_ptr + opt_len) == '\0'))
@@ -143,7 +150,12 @@
}
else
{
- /* If going to new group and we have option to apply, do it now */
+ /*
+ If we are going to the new group and have an option to apply, do
+ it now. If we are removing a single option or the whole section
+ this will only trigger opt_applied flag.
+ */
+
if (in_section && !opt_applied && *src_ptr == '[')
{
dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
@@ -153,7 +165,10 @@
for (; nr_newlines; nr_newlines--)
dst_ptr= strmov(dst_ptr, NEWLINE);
- dst_ptr= strmov(dst_ptr, linebuff);
+
+ /* Skip the section if MY_REMOVE_SECTION was given */
+ if (!in_section || remove_option != MY_REMOVE_SECTION)
+ dst_ptr= strmov(dst_ptr, linebuff);
}
/* Look for a section */
if (*src_ptr == '[')
@@ -168,17 +183,27 @@
if (*src_ptr != ']')
continue; /* Missing closing parenthesis. Assume this was no group */
+
+ if (remove_option == MY_REMOVE_SECTION)
+ dst_ptr= dst_ptr - strlen(linebuff);
+
in_section= TRUE;
}
else
in_section= FALSE; /* mark that this section is of no interest to us */
}
}
- /* File ended. */
- if (!opt_applied && !remove_option && in_section)
+
+ /*
+ File ended. Apply an option or set opt_applied flag (in case of
+ MY_REMOVE_SECTION) so that the changes are saved. Do not do anything
+ if we are removing non-existent option.
+ */
+
+ if (!opt_applied && in_section && (remove_option != MY_REMOVE_OPTION))
{
/* New option still remains to apply at the end */
- if (*(dst_ptr - 1) != '\n')
+ if (!remove_option && *(dst_ptr - 1) != '\n')
dst_ptr= strmov(dst_ptr, NEWLINE);
dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
opt_applied= 1;
--- 1.88/mysql-test/mysql-test-run.pl 2006-03-14 13:24:57 +03:00
+++ 1.89/mysql-test/mysql-test-run.pl 2006-03-18 20:53:15 +03:00
@@ -1947,7 +1947,7 @@
language = $path_language
character-sets-dir = $path_charsetsdir
basedir = $path_my_basedir
-server_id =$server_id
+server_id = $server_id
skip-stack-trace
skip-innodb
skip-bdb
--- 1.31/server-tools/instance-manager/manager.cc 2006-02-21 15:57:54 +03:00
+++ 1.32/server-tools/instance-manager/manager.cc 2006-03-18 20:53:16 +03:00
@@ -17,6 +17,7 @@
#include <my_global.h>
#include "manager.h"
+#include "exit_codes.h"
#include "priv.h"
#include "thread_registry.h"
#include "listener.h"
@@ -135,8 +136,22 @@
if (instance_map.init() || user_map.init())
return;
- if (user_map.load(options.password_file_name))
+ int err_code= user_map.load(options.password_file_name);
+
+ if (err_code == ERR_IO_ERROR)
+ {
+ log_info("[WARNING] can't open password file %s: errno=%d, %s",
+ (const char *) options.password_file_name,
+ (int) errno,
+ (const char *) strerror(errno));
+
+ /* Probably the password file wasn't specified. Try to leave without it. */
+ }
+ else
+ {
return;
+ }
+
/* write pid file */
if (create_pid_file(options.pid_file_name))
--- 1.30/server-tools/instance-manager/options.cc 2006-02-21 15:32:49 +03:00
+++ 1.31/server-tools/instance-manager/options.cc 2006-03-18 20:53:16 +03:00
@@ -20,8 +20,10 @@
#include "options.h"
+#include "exit_codes.h"
#include "priv.h"
#include "portability.h"
+#include "user_map.h"
#include <my_sys.h>
#include <my_getopt.h>
#include <m_string.h>
@@ -58,29 +60,42 @@
/* Remember if the config file was forced */
bool Options::is_forced_default_file= 0;
+const char *Options::pf_user_name= 0;
+const char *Options::pf_password= 0;
+
+PasswordMgmtCmd Options::pm_cmd= PMC_NOP;
+
/*
List of options, accepted by the instance manager.
List must be closed with empty option.
*/
enum options {
+ OPT_PASSWD= 'P',
+ OPT_USERNAME= 'u',
+ OPT_PASSWORD= 'p',
OPT_LOG= 256,
OPT_PID_FILE,
OPT_SOCKET,
OPT_PASSWORD_FILE,
OPT_MYSQLD_PATH,
-#ifndef __WIN__
- OPT_RUN_AS_SERVICE,
- OPT_USER,
-#else
+#ifdef __WIN__
OPT_INSTALL_SERVICE,
OPT_REMOVE_SERVICE,
OPT_STAND_ALONE,
+#else
+ OPT_RUN_AS_SERVICE,
+ OPT_USER,
#endif
OPT_MONITORING_INTERVAL,
OPT_PORT,
OPT_WAIT_TIMEOUT,
- OPT_BIND_ADDRESS
+ OPT_BIND_ADDRESS,
+ OPT_ADD_USER,
+ OPT_DROP_USER,
+ OPT_EDIT_USER,
+ OPT_CLEAN_PASSWORD_FILE,
+ OPT_CHECK_PASSWORD_FILE,
};
static struct my_option my_long_options[] =
@@ -100,7 +115,7 @@
(gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
- { "passwd", 'P', "Prepare entry for passwd file and exit.", 0, 0, 0,
+ { "passwd", OPT_PASSWD, "Prepare entry for passwd file and exit.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ "bind-address", OPT_BIND_ADDRESS, "Bind address to use for connection.",
@@ -129,13 +144,16 @@
(gptr *) &Options::monitoring_interval,
0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL,
0, 0, 0, 0, 0 },
+
#ifdef __WIN__
{ "install", OPT_INSTALL_SERVICE, "Install as system service.",
(gptr *) &Options::install_as_service, (gptr*) &Options::install_as_service,
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
+
{ "remove", OPT_REMOVE_SERVICE, "Remove system service.",
(gptr *)&Options::remove_service, (gptr*) &Options::remove_service,
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0},
+
{ "standalone", OPT_STAND_ALONE, "Run the application in stand alone mode.",
(gptr *)&Options::stand_alone, (gptr*) &Options::stand_alone,
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0},
@@ -149,6 +167,7 @@
(gptr *) &Options::user,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
#endif
+
{ "version", 'V', "Output version information and exit.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
@@ -157,6 +176,47 @@
(gptr *) &net_read_timeout, (gptr *) &net_read_timeout, 0, GET_ULONG,
REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0 },
+ { "bind-address", OPT_BIND_ADDRESS, "Bind address to use for connection.",
+ (gptr *) &Options::bind_address, (gptr *) &Options::bind_address,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "port", OPT_PORT, "Port number to use for connections",
+ (gptr *) &Options::port_number, (gptr *) &Options::port_number,
+ 0, GET_UINT, REQUIRED_ARG, DEFAULT_PORT, 0, 0, 0, 0, 0 },
+
+ { "password-file", OPT_PASSWORD_FILE, "Look for Instance Manager users"
+ " and passwords here.",
+ (gptr *) &Options::password_file_name,
+ (gptr *) &Options::password_file_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "add-user", OPT_ADD_USER, "Add a user to the password file", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "drop-user", OPT_DROP_USER, "Add a user to the password file", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "edit-user", OPT_EDIT_USER, "Add a user to the password file", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "clean-password-file", OPT_CLEAN_PASSWORD_FILE,
+ "Add a user to the password file",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "check-password-file", OPT_CHECK_PASSWORD_FILE,
+ "Add a user to the password file",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "username", OPT_USERNAME, "Username to update the password file",
+ (gptr *) &Options::pf_user_name,
+ (gptr *) &Options::pf_user_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+ { "password", OPT_PASSWORD, "Password to update the password file",
+ (gptr *) &Options::pf_password,
+ (gptr *) &Options::pf_password,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }
};
@@ -190,37 +250,209 @@
}
-static void passwd()
+/**************************************************************************
+
+ Password management functions.
+
+**************************************************************************/
+
+
+static char user_name_buf[1024];
+
+
+static const char *get_user_name()
{
- char user[1024], *p;
- const char *pw1, *pw2;
- char pw1msg[]= "Enter password: ";
- char pw2msg[]= "Re-type password: ";
- char crypted_pw[SCRAMBLED_PASSWORD_CHAR_LENGTH + 1];
-
- fprintf(stderr, "Creating record for new user.\n");
- fprintf(stderr, "Enter user name: ");
- if (!fgets(user, sizeof(user), stdin))
+ char *ptr;
+
+ if (Options::pf_user_name)
+ return Options::pf_user_name;
+
+ printf("Enter user name: ");
+ fflush(stdout);
+
+ if (!fgets(user_name_buf, sizeof (user_name_buf), stdin))
{
- fprintf(stderr, "Unable to read user.\n");
- return;
+ fprintf(stderr, "Error: unable to read user name from stdin.\n");
+ return 0;
}
- if ((p= strchr(user, '\n'))) *p= 0;
- pw1= get_tty_password(pw1msg);
- pw2= get_tty_password(pw2msg);
+ if ((ptr= strchr(user_name_buf, '\n')))
+ *ptr= 0;
+
+ return user_name_buf;
+}
+
- if (strcmp(pw1, pw2))
+static const char *get_password()
+{
+ if (Options::pf_password)
+ return Options::pf_password;
+
+ const char *passwd1= get_tty_password((char *) "Enter password: ");
+ const char *passwd2= get_tty_password((char *) "Re-type password: ");
+
+ if (strcmp(passwd1, passwd2))
{
- fprintf(stderr, "Sorry, passwords do not match.\n");
- return;
+ fprintf(stderr, "Error: passwords do not match.\n");
+ return 0;
}
- make_scrambled_password(crypted_pw, pw1);
- printf("%s:%s\n", user, crypted_pw);
+ return passwd1;
+}
+
+
+static int passwd()
+{
+ const char *user_name;
+ const char *password;
+ char scrambled_password_buf[SCRAMBLED_PASSWORD_CHAR_LENGTH + 1];
+
+ printf("Creating record for new user.\n");
+
+ if (!(user_name= get_user_name()))
+ return ERR_CAN_NOT_READ_USER_NAME;
+
+ if (!(password= get_password()))
+ return ERR_CAN_NOT_READ_PASSWORD;
+
+ make_scrambled_password(scrambled_password_buf, password);
+
+ printf("%s:%s\n", (const char *) user_name,
+ (const char *) scrambled_password_buf);
+
+ return ERR_OK;
}
+static int add_user()
+{
+ printf("--> password_file_name: '%s'\n", Options::password_file_name);
+
+ const char *user_name;
+ const char *password;
+ char scrambled_password_buf[SCRAMBLED_PASSWORD_CHAR_LENGTH + 1];
+
+ if (!(user_name= get_user_name()))
+ return ERR_CAN_NOT_READ_USER_NAME;
+
+ if (!(password= get_password()))
+ return ERR_CAN_NOT_READ_PASSWORD;
+
+ // Loading the password file.
+
+ User_map user_map;
+
+ if (user_map.init())
+ {
+ fprintf(stderr, "Error: can not initialize user map.\n");
+ return ERR_OUT_OF_MEMORY;
+ }
+
+ int err_code= user_map.load(Options::password_file_name);
+
+ if (err_code != ERR_OK)
+ {
+ if (err_code == ERR_IO_ERROR)
+ {
+ fprintf(stderr,
+ "Error: I/O error while processing password file (%s): %s.",
+ (const char *) Options::password_file_name,
+ (const char *) strerror(errno));
+ }
+ else
+ {
+ fprintf(stderr, "Error: can not process password file.\n");
+ }
+
+ return err_code;
+ }
+
+ // Adding the user.
+
+ if (user_map.find_user(user_name, strlen(user_name)))
+ {
+ fprintf(stderr, "Error: user '%s' already exists.\n",
+ (const char *) user_name);
+ return ERR_USER_ALREADY_EXISTS;
+ }
+
+ // TODO
+
+ make_scrambled_password(scrambled_password_buf, password);
+
+ User *new_user = new User();
+ strcpy(new_user->user, user_name);
+ strcpy(new_user->m_password, scrambled_password_buf);
+
+ user_map.add_user(new_user);
+
+ user_map.save(Options::password_file_name);
+
+ return 0;
+}
+
+
+static int drop_user()
+{
+ printf("---> drop_user()\n");
+ fflush(stdout);
+
+ return 0;
+}
+
+
+static int edit_user()
+{
+ printf("---> edit_user()\n");
+ fflush(stdout);
+
+ return 0;
+}
+
+
+static int clean_password_file()
+{
+ printf("---> clean_password_file()\n");
+ fflush(stdout);
+
+ return 0;
+}
+
+
+static int check_password_file()
+{
+ printf("---> check_password_file()\n");
+ fflush(stdout);
+
+ return 0;
+}
+
+
+static int handle_pm_cmd()
+{
+ switch (Options::pm_cmd) {
+ case PMC_ADD_USER:
+ return add_user();
+
+ case PMC_DROP_USER:
+ return drop_user();
+
+ case PMC_EDIT_USER:
+ return edit_user();
+
+ case PMC_CLEAN_PASSWORD_FILE:
+ return clean_password_file();
+
+ case PMC_CHECK_PASSWORD_FILE:
+ return check_password_file();
+ }
+
+ return ERR_INTERNAL_ERROR;
+}
+
+/*************************************************************************/
+
+
C_MODE_START
static my_bool
@@ -232,9 +464,39 @@
case 'V':
version();
exit(0);
- case 'P':
- passwd();
- exit(0);
+ case OPT_PASSWD:
+ exit(passwd());
+ case OPT_ADD_USER:
+ case OPT_DROP_USER:
+ case OPT_EDIT_USER:
+ case OPT_CLEAN_PASSWORD_FILE:
+ case OPT_CHECK_PASSWORD_FILE:
+ if (Options::pm_cmd != PMC_NOP)
+ {
+ fprintf(stderr, "Error: only one password-management command "
+ "can be specified at a time.\n");
+ exit(ERR_INVALID_USAGE);
+ }
+
+ switch (optid) {
+ case OPT_ADD_USER:
+ Options::pm_cmd= PMC_ADD_USER;
+ break;
+ case OPT_DROP_USER:
+ Options::pm_cmd= PMC_DROP_USER;
+ break;
+ case OPT_EDIT_USER:
+ Options::pm_cmd= PMC_EDIT_USER;
+ break;
+ case OPT_CLEAN_PASSWORD_FILE:
+ Options::pm_cmd= PMC_CLEAN_PASSWORD_FILE;
+ break;
+ case OPT_CHECK_PASSWORD_FILE:
+ Options::pm_cmd= PMC_CHECK_PASSWORD_FILE;
+ break;
+ }
+
+ break;
case '?':
usage();
exit(0);
@@ -289,6 +551,17 @@
if ((handle_options(&argc, &saved_argv, my_long_options,
get_one_option)) != 0)
goto err;
+
+ if (Options::pm_cmd != PMC_NOP)
+ exit(handle_pm_cmd());
+
+ if (Options::pf_user_name || Options::pf_password)
+ {
+ fprintf(stderr,
+ "--username and/or --password options have been specified, "
+ "but no password-management command has been given.\n");
+ return 1;
+ }
return 0;
--- 1.14/server-tools/instance-manager/options.h 2006-02-10 02:15:52 +03:00
+++ 1.15/server-tools/instance-manager/options.h 2006-03-18 20:53:16 +03:00
@@ -26,6 +26,16 @@
#pragma interface
#endif
+enum PasswordMgmtCmd
+{
+ PMC_NOP,
+ PMC_ADD_USER,
+ PMC_DROP_USER,
+ PMC_EDIT_USER,
+ PMC_CLEAN_PASSWORD_FILE,
+ PMC_CHECK_PASSWORD_FILE
+};
+
struct Options
{
#ifdef __WIN__
@@ -47,6 +57,14 @@
static uint port_number;
static const char *bind_address;
static const char *config_file;
+
+ /*
+ Variables for storing user name and password for updating the password file.
+ */
+ static const char *pf_user_name;
+ static const char *pf_password;
+
+ static PasswordMgmtCmd pm_cmd;
/* argv pointer returned by load_defaults() to be used by free_defaults() */
static char **saved_argv;
--- 1.33/server-tools/instance-manager/commands.cc 2006-02-10 21:03:44 +03:00
+++ 1.34/server-tools/instance-manager/commands.cc 2006-03-18 20:53:15 +03:00
@@ -17,6 +17,7 @@
#include "commands.h"
#include "instance_map.h"
+#include "log.h"
#include "messages.h"
#include "mysqld_error.h"
#include "mysql_manager_error.h"
@@ -29,6 +30,13 @@
#include <mysql.h>
#include <my_dir.h>
+/*
+ modify_defaults_to_im_error -- a map of error codes of
+ mysys::modify_defaults_file() into Instance Manager error codes.
+*/
+
+static const int modify_defaults_to_im_error[]= { 0, ER_OUT_OF_RESOURCES,
+ ER_ACCESS_OPTION_FILE };
/*
Add a string to a buffer
@@ -107,8 +115,8 @@
int Show_instances::execute(struct st_net *net, ulong connection_id)
{
Buffer send_buff; /* buffer for packets */
- LIST name, status;
- NAME_WITH_LENGTH name_field, status_field;
+ LIST name, status, managed;
+ NAME_WITH_LENGTH name_field, status_field, managed_field;
LIST *field_list;
uint position=0;
@@ -118,7 +126,11 @@
status_field.name= (char*) "status";
status_field.length= DEFAULT_FIELD_LENGTH;
status.data= &status_field;
- field_list= list_add(NULL, &status);
+ managed_field.name= (char*) "managed";
+ managed_field.length= DEFAULT_FIELD_LENGTH;
+ managed.data= &managed_field;
+ field_list= list_add(NULL, &managed);
+ field_list= list_add(field_list, &status);
field_list= list_add(field_list, &name);
send_fields(net, field_list);
@@ -137,6 +149,11 @@
store_to_protocol_packet(&send_buff, (char*) "online", &position);
else
store_to_protocol_packet(&send_buff, (char*) "offline", &position);
+
+ store_to_protocol_packet(&send_buff,
+ instance_map->guardian->is_managed(instance) ? "1" : "0",
+ &position);
+
if (my_net_write(net, send_buff.buffer, (uint) position))
goto err;
}
@@ -157,6 +174,24 @@
int Flush_instances::execute(struct st_net *net, ulong connection_id)
{
+ /* Check that there is no running instance. */
+
+ Instance *instance;
+ Instance_map::Iterator iterator(instance_map);
+
+ instance_map->lock();
+ while ((instance= iterator.next()))
+ {
+ if (instance_map->guardian->is_managed(instance) || instance->is_running())
+ {
+ instance_map->unlock();
+ return ER_THERE_IS_RUNNING_INSTACE;
+ }
+ }
+ instance_map->unlock();
+
+ /* Perform flush. */
+
if (instance_map->flush_instances() ||
net_send_ok(net, connection_id, NULL))
return ER_OUT_OF_RESOURCES;
@@ -200,10 +235,10 @@
{
enum { MAX_VERSION_LENGTH= 40 };
Buffer send_buff; /* buffer for packets */
- LIST name, status, version, version_number;
+ LIST name, status, version, version_number, managed;
LIST *field_list;
NAME_WITH_LENGTH name_field, status_field, version_field,
- version_number_field;
+ version_number_field, managed_field;
uint position=0;
if (!instance_name)
@@ -222,7 +257,11 @@
version_number_field.name= (char*) "version_number";
version_number_field.length= MAX_VERSION_LENGTH;
version_number.data= &version_number_field;
- field_list= list_add(NULL, &version);
+ managed_field.name= (char*) "managed";
+ managed_field.length= DEFAULT_FIELD_LENGTH;
+ managed.data= &managed_field;
+ field_list= list_add(NULL, &managed);
+ field_list= list_add(field_list, &version);
field_list= list_add(field_list, &version_number);
field_list= list_add(field_list, &status);
field_list= list_add(field_list, &name);
@@ -257,6 +296,9 @@
store_to_protocol_packet(&send_buff, (char*) "unknown", &position);
}
+ store_to_protocol_packet(&send_buff,
+ instance_map->guardian->is_managed(instance) ? "1" : "0",
+ &position);
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
@@ -321,50 +363,18 @@
store_to_protocol_packet(&send_buff, (char*) instance_name, &position);
if (my_net_write(net, send_buff.buffer, (uint) position))
goto err;
- if ((instance->options.mysqld_path))
- {
- position= 0;
- store_to_protocol_packet(&send_buff, (char*) "mysqld-path", &position);
- store_to_protocol_packet(&send_buff,
- (char*) instance->options.mysqld_path,
- &position);
- if (send_buff.is_error() ||
- my_net_write(net, send_buff.buffer, (uint) position))
- goto err;
- }
-
- if ((instance->options.nonguarded))
- {
- position= 0;
- store_to_protocol_packet(&send_buff, (char*) "nonguarded", &position);
- store_to_protocol_packet(&send_buff, "", &position);
- if (send_buff.is_error() ||
- my_net_write(net, send_buff.buffer, (uint) position))
- goto err;
- }
/* loop through the options stored in DYNAMIC_ARRAY */
- for (uint i= 0; i < instance->options.options_array.elements; i++)
+ for (int i= 0; i < instance->options.get_num_options(); i++)
{
- char *tmp_option, *option_value;
- get_dynamic(&(instance->options.options_array), (gptr) &tmp_option, i);
- option_value= strchr(tmp_option, '=');
- /* split the option string into two parts if it has a value */
+ Option option= instance->options.get_option(i);
position= 0;
- if (option_value != NULL)
- {
- *option_value= 0;
- store_to_protocol_packet(&send_buff, tmp_option + 2, &position);
- store_to_protocol_packet(&send_buff, option_value + 1, &position);
- /* join name and the value into the same option again */
- *option_value= '=';
- }
- else
- {
- store_to_protocol_packet(&send_buff, tmp_option + 2, &position);
- store_to_protocol_packet(&send_buff, "", &position);
- }
+
+ store_to_protocol_packet(&send_buff, option.get_name(), &position);
+ store_to_protocol_packet(&send_buff,
+ option.get_value()[0] ? option.get_value() : "",
+ &position);
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
@@ -399,21 +409,271 @@
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))
+ instance_map->guardian->guard(instance);
+
+ net_send_ok(net, connection_id, "Instance started");
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation for Create_instance.
+**************************************************************************/
+
+Create_instance::Create_instance(Instance_map *instance_map_arg,
+ const char *name, uint len)
+ :Command(instance_map_arg)
+{
+ strmake(instance_name, name, len);
+ instance_name_len= len;
+}
+
+
+Create_instance *Create_instance::create(Instance_map *instance_map_arg,
+ const char *name, uint len)
+{
+ Create_instance *cmd= new Create_instance(instance_map_arg, name, len);
+
+ if (my_init_dynamic_array(&cmd->options, sizeof(Option), 0, 32))
{
- if ((err_code= instance->start()))
- return err_code;
+ delete cmd;
+ return NULL;
+ }
+
+ return cmd;
+}
+
+
+Create_instance::~Create_instance()
+{
+ delete_dynamic(&options);
+}
+
+
+int Create_instance::execute(struct st_net *net, ulong connection_id)
+{
+ File cnf_file;
+ Instance *instance;
+
+ /* Check that the name is valid and there is no instance with such name. */
+
+ if (!Instance::is_name_valid(instance_name))
+ return ER_MALFORMED_INSTANCE_NAME;
+
+ /*
+ NOTE: In order to prevent race condition, we should perform all operations
+ on under acquired lock.
+ */
+
+ instance_map->lock();
+
+ if (instance_map->find_impl(instance_name, instance_name_len))
+ {
+ instance_map->unlock();
+ return ER_CREATE_EXISTING_INSTANCE;
+ }
+
+ /* Update the configuration file. */
+
+ if (!(cnf_file= my_open(Options::config_file, O_WRONLY | O_APPEND, MYF(0))))
+ {
+ instance_map->unlock();
+ return ER_ACCESS_OPTION_FILE;
+ }
+
+ if (my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)) ||
+ my_write(cnf_file, (byte*)"[", 1, MYF(MY_NABP)) ||
+ my_write(cnf_file, (byte*)instance_name, instance_name_len,
+ MYF(MY_NABP)) ||
+ my_write(cnf_file, (byte*)"]", 1, MYF(MY_NABP)) ||
+ my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)))
+ {
+ my_close(cnf_file, MYF(0));
+ instance_map->unlock();
+ return ER_ACCESS_OPTION_FILE;
+ }
+
+ for (uint i= 0; i < options.elements; ++i)
+ {
+ Option option;
+ char option_str[MAX_OPTION_STR_LEN];
+ char *ptr;
+ int option_str_len;
+
+ get_dynamic(&options, (gptr) &option, i);
+
+ ptr= strxnmov(option_str, MAX_OPTION_LEN + 1, option.get_name(), NullS);
+
+ if (option.get_value()[0])
+ ptr= strxnmov(ptr, MAX_OPTION_LEN + 2, "=", option.get_value(), NullS);
+
+ option_str_len= ptr - option_str;
+
+ if (my_write(cnf_file, (byte*)option_str, option_str_len, MYF(MY_NABP)) ||
+ my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)))
+ {
+ my_close(cnf_file, MYF(0));
+ instance_map->unlock();
+ return ER_ACCESS_OPTION_FILE;
+ }
+ }
+
+ my_close(cnf_file, MYF(0));
+
+ /* Register new instance in configuration cache. */
- if (!(instance->options.nonguarded))
- instance_map->guardian->guard(instance);
+ instance= new Instance();
+
+ if (instance->init(instance_name) || instance_map->add_instance(instance))
+ {
+ log_error("Can not initialize or register instance (name: '%s').",
+ (const char *) instance_name);
+ delete instance;
+ instance_map->unlock();
+ return ER_OUT_OF_RESOURCES;
+ }
+
+ /* Add options into the created instance. */
+
+ for (uint i= 0; i < options.elements; ++i)
+ {
+ Option option;
+ get_dynamic(&options, (gptr) &option, i);
- net_send_ok(net, connection_id, "Instance started");
- return 0;
+ instance->options.set_option(option.get_name(), option.get_value());
}
+
+ if (instance->complete_initialization(instance_map,
+ instance_map->mysqld_path,
+ USUAL_INSTANCE))
+ {
+ log_error("Can not complete initialization of instance (name: '%s').",
+ (const char *) instance_name);
+ instance_map->unlock();
+ return ER_OUT_OF_RESOURCES; // XXX: is it correct error status in this case?
+ }
+
+#if 0
+ /*
+ If the created instance is guarded, start it and add to the Guardian's
+ list.
+ */
+
+ if (!instance->options.nonguarded)
+ {
+ int err_code= instance->start();
+
+ if (err_code)
+ {
+ log_error("Can not start instance (name: '%s'). Error: %d.",
+ (const char *) instance_name,
+ (int) err_code);
+ instance_map->unlock();
+ return err_code;
+ }
+
+ if (instance_map->guardian->guard(instance))
+ {
+ log_error("Can not add instance (name: '%s') to Guardian list.",
+ (const char *) instance_name);
+ instance_map->unlock();
+ return ER_OUT_OF_RESOURCES; // XXX: is it correct error status in this case?
+ }
+ }
+#endif
+
+ /* That's all. */
+
+ instance_map->unlock();
+
+ /* Send the result. */
+
+ net_send_ok(net, connection_id, NULL);
+
+ return 0;
}
+
+/**************************************************************************
+ Implementation for Drop_instance.
+**************************************************************************/
+
+Drop_instance::Drop_instance(Instance_map *instance_map_arg,
+ const char *name, uint len)
+ :Command(instance_map_arg)
+{
+ /*
+ NOTE: we can not get and remember (Instance *) here, because all these
+ operations must be called under acquired lock.
+ */
+
+ strmake(instance_name, name, len);
+ instance_name_len= len;
+}
+
+
+int Drop_instance::execute(struct st_net *net, ulong connection_id)
+{
+ int err_code;
+ Instance *instance;
+
+ /*
+ NOTE: In order to prevent race condition, we should perform all operations
+ under acquired lock.
+ */
+
+ instance_map->lock();
+
+ instance= instance_map->find_impl(instance_name, instance_name_len);
+
+ if (instance == 0)
+ {
+ instance_map->unlock();
+ return ER_BAD_INSTANCE_NAME; /* no instance with this name */
+ }
+
+ if (instance_map->guardian->is_managed(instance) || instance->is_running())
+ {
+ instance_map->unlock();
+ return ER_DROP_RUNNING_INSTANCE;
+ }
-/* implementation for Show_instance_log: */
+ err_code= modify_defaults_file(Options::config_file, NULL, NULL,
+ instance_name, MY_REMOVE_SECTION);
+ DBUG_ASSERT(err_code >= 0 && err_code <= 2);
+
+ if (err_code)
+ {
+ instance_map->unlock();
+ return modify_defaults_to_im_error[err_code];
+ }
+
+ /* Remove instance from the instance map hash and Guardian's list. */
+
+ if (!instance->options.nonguarded)
+ instance_map->guardian->stop_guard(instance);
+
+ if ((err_code= instance->stop()))
+ return err_code;
+
+ instance_map->remove_instance(instance);
+
+ instance_map->unlock();
+
+ net_send_ok(net, connection_id, "Instance dropped");
+
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation for Show_instance_log.
+**************************************************************************/
Show_instance_log::Show_instance_log(Instance_map *instance_map_arg,
const char *name, uint len,
@@ -688,7 +948,11 @@
{
Instance *instance;
- /* we make a search here, since we don't want to store the name */
+ /*
+ We make a search here, since we don't want to store the name.
+ XXX: This seems to be MT-INSAFE! Another user in another thread can
+ destroy the instance we use.
+ */
if ((instance= instance_map->find(name, len)))
{
instance_name= instance->options.instance_name;
@@ -737,15 +1001,13 @@
int Set_option::correct_file(int skip)
{
- static const int mysys_to_im_error[]= { 0, ER_OUT_OF_RESOURCES,
- ER_ACCESS_OPTION_FILE };
int error;
error= modify_defaults_file(Options::config_file, option,
option_value, instance_name, skip);
DBUG_ASSERT(error >= 0 && error <= 2);
- return mysys_to_im_error[error];
+ return modify_defaults_to_im_error[error];
}
@@ -755,48 +1017,94 @@
SYNOPSYS
Set_option::do_command()
net The network connection to the client.
+ instance Instance to be modified.
RETURN
0 - ok
1 - error occured
*/
-int Set_option::do_command(struct st_net *net)
+int Set_option::do_command(struct st_net *net, Instance *instance)
{
- int error;
+ /* Update the configuration file. */
- /* we must hold the instance_map mutex while changing config file */
- instance_map->lock();
- error= correct_file(FALSE);
- instance_map->unlock();
+ int error= correct_file(FALSE);
+
+ if (error)
+ return error;
- return error;
+ /* Update the internal cache. */
+
+ if (instance->options.set_option(option, option_value))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
}
int Set_option::execute(struct st_net *net, ulong connection_id)
{
- if (instance_name != NULL)
- {
- int val;
+ int val;
- val= do_command(net);
+ if (instance_name == NULL)
+ return ER_BAD_INSTANCE_NAME;
- if (val == 0)
- net_send_ok(net, connection_id, NULL);
+ /*
+ NOTE: In order to prevent race condition, we should perform all operations
+ under acquired lock.
+ */
- return val;
+ instance_map->lock();
+
+ /* Check that the instance is not running. */
+
+ Instance *instance= instance_map->find_impl(instance_name, instance_name_len);
+
+ if (!instance)
+ {
+ instance_map->unlock();
+ return ER_BAD_INSTANCE_NAME;
+ }
+
+ if (instance_map->guardian->is_managed(instance) || instance->is_running())
+ {
+ instance_map->unlock();
+ return ER_INSTANCE_IS_RUNNING;
}
- return ER_BAD_INSTANCE_NAME;
+ /* Perform command-specific (SET/UNSET) actions. */
+
+ val= do_command(net, instance);
+
+ /* Unlock instance_map. */
+
+ instance_map->unlock();
+
+ /* That's all. */
+
+ if (val == 0)
+ net_send_ok(net, connection_id, NULL);
+
+ return val;
}
/* the only function from Unset_option we need to Implement */
-int Unset_option::do_command(struct st_net *net)
+int Unset_option::do_command(struct st_net *net, Instance *instance)
{
- return correct_file(TRUE);
+ /* Update the configuration file. */
+
+ int error= correct_file(TRUE);
+
+ if (error)
+ return error;
+
+ /* Update the internal cache. */
+
+ instance->options.unset_option(option);
+
+ return 0;
}
--- 1.9/server-tools/instance-manager/commands.h 2005-07-21 22:40:43 +04:00
+++ 1.10/server-tools/instance-manager/commands.h 2006-03-18 20:53:15 +03:00
@@ -19,6 +19,7 @@
#include "command.h"
#include "instance.h"
#include "parse.h"
+#include "priv.h"
/*
Print all instances of this instance manager.
@@ -116,6 +117,54 @@
/*
+ Create an instance section in config file.
+ Grammar: CREATE INSTANCE <instance_name>
+*/
+
+class Create_instance : public Command
+{
+public:
+ static Create_instance *create(Instance_map *instance_map_arg,
+ const char *name, uint len);
+
+public:
+ virtual ~Create_instance();
+
+ virtual int execute(struct st_net *net, ulong connection_id);
+
+public:
+ DYNAMIC_ARRAY options;
+
+private:
+ Create_instance(Instance_map *instance_map_arg, const char *name, uint len);
+
+private:
+ uint instance_name_len;
+ char instance_name[FN_REFLEN];
+};
+
+
+/*
+ Drop an instance. Operation is permitted only if the instance is stopped.
+ On successful completion the insatnce section is removed from config-file
+ and the instance is removed from the instance map.
+ Grammar: Drop INSTANCE <instance_name>
+*/
+
+class Drop_instance : public Command
+{
+public:
+ Drop_instance(Instance_map *instance_map_arg, const char *name, uint len);
+
+ virtual int execute(struct st_net *net, ulong connection_id);
+
+private:
+ uint instance_name_len;
+ char instance_name[FN_REFLEN];
+};
+
+
+/*
Print requested part of the log
Grammar:
SHOW <instance_name> log {ERROR | SLOW | GENERAL} size[, offset_from_end]
@@ -166,6 +215,7 @@
int execute(struct st_net *net, ulong connection_id);
};
+
/*
Set an option for the instance.
Grammar: SET instance_name.option=option_value
@@ -180,7 +230,7 @@
/*
the following function is virtual to let Unset_option to use
*/
- virtual int do_command(struct st_net *net);
+ virtual int do_command(struct st_net *net, Instance *instance);
int execute(struct st_net *net, ulong connection_id);
protected:
int correct_file(int skip);
@@ -188,7 +238,6 @@
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];
};
@@ -208,7 +257,7 @@
Set_option(instance_map_arg, name, len, option_arg, option_len,
option_value_arg, option_value_len)
{}
- int do_command(struct st_net *net);
+ virtual int do_command(struct st_net *net, Instance *instance);
};
--- 1.20/server-tools/instance-manager/guardian.cc 2006-02-21 15:57:54 +03:00
+++ 1.21/server-tools/instance-manager/guardian.cc 2006-03-18 20:53:15 +03:00
@@ -159,7 +159,11 @@
instance->options.instance_name);
}
else
+ {
+ log_info("guardian: cannot start instance %s. Abandoning attempts "
+ "to (re)start it", instance->options.instance_name);
current_node->state= CRASHED_AND_ABANDONED;
+ }
}
break;
case CRASHED_AND_ABANDONED:
@@ -201,8 +205,6 @@
while (node != NULL)
{
- struct timespec timeout;
-
GUARD_NODE *current_node= (GUARD_NODE *) node->data;
instance= ((GUARD_NODE *) node->data)->instance;
process_instance(instance, current_node, &guarded_instances, node);
@@ -263,12 +265,11 @@
while ((instance= iterator.next()))
{
- if (!(instance->options.nonguarded))
- if (guard(instance, TRUE)) /* do not lock guardian */
- {
- instance_map->unlock();
- return 1;
- }
+ if (instance->options.nonguarded)
+ continue;
+
+ if (guard(instance, TRUE)) /* do not lock guardian */
+ return 1;
}
return 0;
@@ -336,24 +337,14 @@
LIST *node;
pthread_mutex_lock(&LOCK_guardian);
- node= guarded_instances;
- while (node != NULL)
- {
- /*
- We compare only pointers, as we always use pointers from the
- instance_map's MEM_ROOT.
- */
- if (((GUARD_NODE *) node->data)->instance == instance)
- {
- guarded_instances= list_delete(guarded_instances, node);
- pthread_mutex_unlock(&LOCK_guardian);
- return 0;
- }
- else
- node= node->next;
- }
+ node= find_instance_node(instance);
+
+ if (node != NULL)
+ guarded_instances= list_delete(guarded_instances, node);
+
pthread_mutex_unlock(&LOCK_guardian);
+
/* if there is nothing to delete it is also fine */
return 0;
}
@@ -429,4 +420,38 @@
void Guardian_thread::unlock()
{
pthread_mutex_unlock(&LOCK_guardian);
+}
+
+
+LIST *Guardian_thread::find_instance_node(Instance *instance)
+{
+ LIST *node= guarded_instances;
+
+ while (node != NULL)
+ {
+ /*
+ We compare only pointers, as we always use pointers from the
+ instance_map's MEM_ROOT.
+ */
+ if (((GUARD_NODE *) node->data)->instance == instance)
+ return node;
+
+ node= node->next;
+ }
+
+ return NULL;
+}
+
+
+bool Guardian_thread::is_managed(Instance *instance)
+{
+ bool guarded;
+
+ pthread_mutex_lock(&LOCK_guardian);
+
+ guarded= find_instance_node(instance) != NULL;
+
+ pthread_mutex_unlock(&LOCK_guardian);
+
+ return guarded;
}
--- 1.12/server-tools/instance-manager/guardian.h 2005-10-08 18:39:39 +04:00
+++ 1.13/server-tools/instance-manager/guardian.h 2006-03-18 20:53:15 +03:00
@@ -99,6 +99,9 @@
void lock();
void unlock();
+ /* Return true if the instance is managed by Guardian. */
+ bool is_managed(Instance *instance);
+
public:
pthread_cond_t COND_guardian;
@@ -108,6 +111,9 @@
/* check instance state and act accordingly */
void process_instance(Instance *instance, GUARD_NODE *current_node,
LIST **guarded_instances, LIST *elem);
+
+ LIST *find_instance_node(Instance *instance);
+
int stopped;
private:
--- 1.32/server-tools/instance-manager/instance.cc 2006-02-10 02:15:52 +03:00
+++ 1.33/server-tools/instance-manager/instance.cc 2006-03-18 20:53:15 +03:00
@@ -275,6 +275,26 @@
}
+bool Instance::is_name_valid(const char *name)
+{
+ static const char * const INSTANCE_NAME_PREFIX= "mysqld";
+ static const int INSTANCE_NAME_PREFIX_LEN= 6;
+
+ const char *name_suffix= name + INSTANCE_NAME_PREFIX_LEN;
+
+ if (strncmp(name, INSTANCE_NAME_PREFIX, INSTANCE_NAME_PREFIX_LEN))
+ return false;
+
+ for (; *name_suffix; ++name_suffix)
+ {
+ if (!my_isdigit(default_charset_info, *name_suffix))
+ return false;
+ }
+
+ return true;
+}
+
+
Instance_map *Instance::get_map()
{
return instance_map;
@@ -313,7 +333,7 @@
pthread_mutex_unlock(&LOCK_instance);
- if (!is_running())
+ if (configured && !is_running())
{
remove_pid();
@@ -339,8 +359,8 @@
return 0;
}
- /* the instance is started already */
- return ER_INSTANCE_ALREADY_STARTED;
+ /* The instance is started already or misconfigured. */
+ return configured ? ER_INSTANCE_ALREADY_STARTED : ER_INSTANCE_MISCONFIGURED;
}
/*
@@ -378,7 +398,7 @@
-Instance::Instance(): crashed(0)
+Instance::Instance(): crashed(0), configured(FALSE)
{
pthread_mutex_init(&LOCK_instance, 0);
pthread_cond_init(&COND_instance_stopped, 0);
@@ -416,7 +436,7 @@
port= options.mysqld_port_val;
if (options.mysqld_socket)
- socket= strchr(options.mysqld_socket, '=') + 1;
+ socket= options.mysqld_socket;
/* no port was specified => instance falled back to default value */
if (!options.mysqld_port && !options.mysqld_socket)
@@ -603,5 +623,6 @@
uint instance_type)
{
instance_map= instance_map_arg;
- return options.complete_initialization(mysqld_path, instance_type);
+ configured= !options.complete_initialization(mysqld_path, instance_type);
+ return 0; // XXX: why don't return actual status here?
}
--- 1.15/server-tools/instance-manager/instance.h 2005-09-23 22:28:46 +04:00
+++ 1.16/server-tools/instance-manager/instance.h 2006-03-18 20:53:15 +03:00
@@ -28,6 +28,9 @@
class Instance
{
public:
+ static bool is_name_valid(const char *name);
+
+public:
Instance();
~Instance();
@@ -50,6 +53,8 @@
private:
int crashed;
+ bool configured;
+
/*
Mutex protecting the instance. Currently we use it to avoid the
double start of the instance. This happens when the instance is starting
--- 1.26/server-tools/instance-manager/instance_map.cc 2006-02-21 15:59:35 +03:00
+++ 1.27/server-tools/instance-manager/instance_map.cc 2006-03-18 20:53:15 +03:00
@@ -106,31 +106,31 @@
int Instance_map::process_one_option(const char *group, const char *option)
{
Instance *instance= NULL;
- static const char prefix[]= { 'm', 'y', 's', 'q', 'l', 'd' };
- if (strncmp(group, prefix, sizeof prefix) == 0 &&
- ((my_isdigit(default_charset_info, group[sizeof prefix]))
- || group[sizeof(prefix)] == '\0'))
- {
- if (!(instance= (Instance *) hash_search(&hash, (byte *) group,
- strlen(group))))
- {
- if (!(instance= new Instance))
- goto err;
- if (instance->init(group) || my_hash_insert(&hash, (byte *) instance))
- goto err_instance;
- }
+ if (!Instance::is_name_valid(group))
+ return 0;
+
+
+ if (!(instance= (Instance *) hash_search(&hash, (byte *) group,
+ strlen(group))))
+ {
+ if (!(instance= new Instance))
+ return 1;
- if (instance->options.add_option(option))
- goto err; /* the instance'll be deleted when we destroy the map */
+ if (instance->init(group) || add_instance(instance))
+ {
+ delete instance;
+ return 1;
}
- return 0;
+ log_info("mysqld instance '%s' has been added successfully.",
+ (const char *) group);
+ }
-err_instance:
- delete instance;
-err:
- return 1;
+ if (option && instance->options.add_option(option))
+ return 1; /* the instance'll be deleted when we destroy the map */
+
+ return 0;
}
@@ -214,6 +214,7 @@
hash_free(&hash);
hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
get_instance_key, delete_instance, 0);
+
rc= load();
guardian->init();
pthread_mutex_unlock(&LOCK_instance_map);
@@ -222,29 +223,45 @@
}
+int Instance_map::add_instance(Instance *instance)
+{
+ return my_hash_insert(&hash, (byte *) instance);
+}
+
+
+int Instance_map::remove_instance(Instance *instance)
+{
+ return hash_delete(&hash, (byte *) instance);
+}
+
+
Instance *
Instance_map::find(const char *name, uint name_len)
{
Instance *instance;
pthread_mutex_lock(&LOCK_instance_map);
- instance= (Instance *) hash_search(&hash, (byte *) name, name_len);
+ instance= find_impl(name, name_len);
pthread_mutex_unlock(&LOCK_instance_map);
return instance;
}
+Instance *
+Instance_map::find_impl(const char *name, uint name_len)
+{
+ return (Instance *) hash_search(&hash, (byte *) name, name_len);
+}
+
int Instance_map::complete_initialization()
{
Instance *instance;
- uint i= 0;
-
if (hash.records == 0) /* no instances found */
{
if ((instance= new Instance) == 0)
goto err;
- if (instance->init("mysqld") || my_hash_insert(&hash, (byte *) instance))
+ if (instance->init("mysqld") || add_instance(instance))
goto err_instance;
/*
@@ -257,13 +274,14 @@
goto err;
}
else
- while (i < hash.records)
+ {
+ for (uint i= 0; i < hash.records; ++i)
{
instance= (Instance *) hash_element(&hash, i);
if (instance->complete_initialization(this, mysqld_path, USUAL_INSTANCE))
goto err;
- i++;
}
+ }
return 0;
err_instance:
@@ -319,10 +337,7 @@
process_option, (void*) this))
log_info("Falling back to compiled-in defaults");
- if (complete_initialization())
- return 1;
-
- return 0;
+ return complete_initialization();
}
--- 1.18/server-tools/instance-manager/instance_map.h 2006-02-21 15:57:54 +03:00
+++ 1.19/server-tools/instance-manager/instance_map.h 2006-03-18 20:53:15 +03:00
@@ -59,15 +59,27 @@
/* returns a pointer to the instance or NULL, if there is no such instance */
Instance *find(const char *name, uint name_len);
+ /* The same as find(), but does not care about locks. */
+ Instance *find_impl(const char *name, uint name_len);
+
int flush_instances();
+
void lock();
void unlock();
+
int init();
+
/*
Process a given option and assign it to appropricate instance. This is
required for the option handler, passed to my_search_option_files().
*/
int process_one_option(const char *group, const char *option);
+
+ /* add instance into internal hash. */
+ int add_instance(Instance *instance);
+
+ /* remove instance from internal hash */
+ int remove_instance(Instance *instance);
Instance_map(const char *default_mysqld_path_arg);
~Instance_map();
--- 1.30/server-tools/instance-manager/instance_options.cc 2006-02-10 03:35:04 +03:00
+++ 1.31/server-tools/instance-manager/instance_options.cc 2006-03-18 20:53:15 +03:00
@@ -22,18 +22,12 @@
#include "parse_output.h"
#include "buffer.h"
+#include "priv.h"
#include <my_sys.h>
#include <signal.h>
#include <m_string.h>
-#ifdef __WIN__
-#define NEWLINE_LEN 2
-#else
-#define NEWLINE_LEN 1
-#endif
-
-
/* Create "mysqld ..." command in the buffer */
static inline int create_mysqld_command(Buffer *buf,
@@ -63,6 +57,26 @@
}
+static bool is_option_im_specific(const char *option_name)
+{
+ static const char *IM_SPECIFIC_OPTIONS[] =
+ {
+ "nonguarded",
+ "mysqld-path",
+ "shutdown-delay",
+ NULL
+ };
+
+ for (int i = 0; IM_SPECIFIC_OPTIONS[i]; ++i)
+ {
+ if (!strcmp(option_name, IM_SPECIFIC_OPTIONS[i]))
+ return true;
+ }
+
+ return false;
+}
+
+
/*
Get compiled-in value of default_option
@@ -88,7 +102,7 @@
int rc= 1;
char verbose_option[]= " --no-defaults --verbose --help";
- /* reserve space fot the path + option + final '\0' */
+ /* reserve space for the path + option + final '\0' */
Buffer cmd(mysqld_path_len + sizeof(verbose_option));
if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len,
@@ -200,8 +214,7 @@
else
{
/* below is safe, as --datadir always has a value */
- strmake(datadir,
- strchr(mysqld_datadir, '=') + 1, MAX_LOG_OPTION_LENGTH - 1);
+ strmake(datadir, mysqld_datadir, MAX_LOG_OPTION_LENGTH - 1);
}
if (gethostname(hostname,sizeof(hostname)-1) < 0)
@@ -287,7 +300,6 @@
int Instance_options::get_pid_filename(char *result)
{
- const char *pid_file= mysqld_pid_file;
char datadir[MAX_PATH_LEN];
if (mysqld_datadir == NULL)
@@ -297,14 +309,10 @@
return 1;
}
else
- strxnmov(datadir, MAX_PATH_LEN - 1, strchr(mysqld_datadir, '=') + 1,
- "/", NullS);
-
- DBUG_ASSERT(mysqld_pid_file);
- pid_file= strchr(pid_file, '=') + 1;
+ strxnmov(datadir, MAX_PATH_LEN - 1, mysqld_datadir, "/", NullS);
/* get the full path to the pidfile */
- my_load_path(result, pid_file, datadir);
+ my_load_path(result, mysqld_pid_file, datadir);
return 0;
}
@@ -349,7 +357,7 @@
mysqld_path_len= strlen(mysqld_path);
if (mysqld_port)
- mysqld_port_val= atoi(strchr(mysqld_port, '=') + 1);
+ mysqld_port_val= atoi(mysqld_port);
if (shutdown_delay)
shutdown_delay_val= atoi(shutdown_delay);
@@ -357,7 +365,7 @@
if (!(tmp= strdup_root(&alloc, "--no-defaults")))
goto err;
- if (!(mysqld_pid_file))
+ if (!mysqld_pid_file)
{
char pidfilename[MAX_PATH_LEN];
char hostname[MAX_PATH_LEN];
@@ -393,9 +401,10 @@
/* we need to reserve space for the final zero + possible default options */
if (!(argv= (char**)
- alloc_root(&alloc, (options_array.elements + 1
+ alloc_root(&alloc, (get_num_options() + 1
+ MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
goto err;
+ filled_default_options= 0;
/* the path must be first in the argv */
if (add_to_argv(mysqld_path))
@@ -404,9 +413,25 @@
if (add_to_argv(tmp))
goto err;
- memcpy((gptr) (argv + filled_default_options), options_array.buffer,
- options_array.elements*sizeof(char*));
- argv[filled_default_options + options_array.elements]= 0;
+ int arg_idx= filled_default_options;
+ for (int opt_idx= 0; opt_idx < get_num_options(); ++opt_idx)
+ {
+ char option_str[MAX_OPTION_STR_LEN];
+ Option option= get_option(opt_idx);
+
+ if (is_option_im_specific(option.get_name()))
+ continue;
+
+ char *ptr= strxnmov(option_str, MAX_OPTION_LEN + 3, "--", option.get_name(),
+ NullS);
+
+ if (option.get_value()[0])
+ strxnmov(ptr, MAX_OPTION_LEN + 2, "=", option.get_value(), NullS);
+
+ argv[arg_idx++]= strdup_root(&alloc, option_str);
+ }
+
+ argv[arg_idx]= 0;
if (fill_log_options() || fill_instance_version())
goto err;
@@ -418,75 +443,124 @@
}
-/*
- Assigns given value to the appropriate option from the class.
+my_bool Instance_options::add_option(const char *option_str)
+{
+ char option_name_buf[MAX_OPTION_LEN];
+ char option_value_buf[MAX_OPTION_LEN];
- SYNOPSYS
- add_option()
- option string with the option prefixed by --
+ parse_option(option_str, option_name_buf, option_value_buf);
- DESCRIPTION
+ return set_option(option_name_buf, option_value_buf);
+}
- The method is called from the option handling routine.
- RETURN
- 0 - ok
- 1 - error occured
-*/
+my_bool Instance_options::set_option(const char *option_name,
+ const char *option_value)
+{
+ char *option_name_dup= strdup_root(&alloc, option_name);
+ char *option_value_dup= strdup_root(&alloc, option_value);
+
+ if (!option_name_dup || !option_value_dup)
+ return true;
+
+ return set_option_impl(option_name_dup, option_value_dup);
+}
-int Instance_options::add_option(const char* option)
+
+void Instance_options::unset_option(const char *option_name)
{
- char *tmp;
- enum { SAVE_VALUE= 1, SAVE_WHOLE, SAVE_WHOLE_AND_ADD };
- struct selected_options_st
+ int idx= find_option(option_name);
+
+ if (idx < 0)
+ return; /* the option has not been set. */
+
+ delete_dynamic_element(&options, idx);
+
+ update_var(CMD_UNSET, option_name, NULL);
+}
+
+
+void Instance_options::parse_option(const char *option_str,
+ char *option_name_buf,
+ char *option_value_buf)
+{
+ char *eq_pos;
+ const char *ptr= option_str;
+
+ while (*ptr == '-')
+ ++ptr;
+
+ strcpy(option_name_buf, ptr);
+ option_value_buf[0]= 0;
+
+ eq_pos= strchr(option_name_buf, '=');
+ if (eq_pos)
+ {
+ *eq_pos = 0;
+ strcpy(option_value_buf, eq_pos + 1);
+ }
+}
+
+
+my_bool Instance_options::set_option_impl(const char *option_name,
+ const char *option_value)
+{
+ my_bool err_status;
+ Option option(option_name, option_value);
+ int idx= find_option(option_name);
+
+ if (idx < 0)
+ err_status= insert_dynamic(&options, (gptr) &option);
+ else
+ err_status= set_dynamic(&options, (gptr) &option, idx);
+
+ update_var(CMD_SET, option_name, option_value);
+
+ return err_status;
+}
+
+
+void Instance_options::update_var(VarCmd cmd,
+ const char *option_name,
+ const char *option_value)
+{
+ struct options_st
{
const char *name;
- uint length;
- const char **value;
- uint type;
+ uint name_len;
+ const char **var;
} options[]=
{
- {"--socket=", 9, &mysqld_socket, SAVE_WHOLE_AND_ADD},
- {"--port=", 7, &mysqld_port, SAVE_WHOLE_AND_ADD},
- {"--datadir=", 10, &mysqld_datadir, SAVE_WHOLE_AND_ADD},
- {"--bind-address=", 15, &mysqld_bind_address, SAVE_WHOLE_AND_ADD},
- {"--pid-file=", 11, &mysqld_pid_file, SAVE_WHOLE_AND_ADD},
- {"--mysqld-path=", 14, &mysqld_path, SAVE_VALUE},
- {"--nonguarded", 9, &nonguarded, SAVE_WHOLE},
- {"--shutdown_delay", 9, &shutdown_delay, SAVE_VALUE},
- {NULL, 0, NULL, 0}
+ {"socket", 6, &mysqld_socket},
+ {"port", 4, &mysqld_port},
+ {"datadir", 7, &mysqld_datadir},
+ {"pid-file", 8, &mysqld_pid_file},
+ {"nonguarded", 10, &nonguarded},
+ {"mysqld-path", 11, &mysqld_path},
+ {"shutdown-delay", 14, &shutdown_delay},
+ {NULL, 0, NULL}
};
- struct selected_options_st *selected_options;
- if (!(tmp= strdup_root(&alloc, option)))
- goto err;
-
- for (selected_options= options; selected_options->name; selected_options++)
- {
- if (strncmp(tmp, selected_options->name, selected_options->length) == 0)
- switch (selected_options->type) {
- case SAVE_WHOLE_AND_ADD:
- *(selected_options->value)= tmp;
- insert_dynamic(&options_array,(gptr) &tmp);
- return 0;
- case SAVE_VALUE:
- *(selected_options->value)= strchr(tmp, '=') + 1;
- return 0;
- case SAVE_WHOLE:
- *(selected_options->value)= tmp;
- return 0;
- default:
- break;
- }
- }
+ for (options_st *opt= options; opt->name; ++opt)
+ {
+ if (!strncmp(opt->name, option_name, opt->name_len))
+ {
+ *(opt->var)= option_value;
+ break;
+ }
+ }
+}
- /* if we haven't returned earlier we should just save the option */
- insert_dynamic(&options_array,(gptr) &tmp);
- return 0;
+int Instance_options::find_option(const char *option_name)
+{
+ for (int i= 0; i < get_num_options(); i++)
+ {
+ if (!strcmp(get_option(i).get_name(), option_name))
+ return i;
+ }
-err:
- return 1;
+ return -1;
}
@@ -521,7 +595,7 @@
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, sizeof(Option), 0, 32))
goto err;
if (!(instance_name= strmake_root(&alloc, (char*) instance_name_arg,
@@ -538,6 +612,6 @@
Instance_options::~Instance_options()
{
free_root(&alloc, MYF(0));
- delete_dynamic(&options_array);
+ delete_dynamic(&options);
}
--- 1.18/server-tools/instance-manager/instance_options.h 2005-09-23 22:28:47 +04:00
+++ 1.19/server-tools/instance-manager/instance_options.h 2006-03-18 20:53:16 +03:00
@@ -18,6 +18,7 @@
#include <my_global.h>
#include <my_sys.h>
+#include <string.h>
#include "parse.h"
#include "portability.h"
@@ -43,15 +44,24 @@
public:
Instance_options() :
mysqld_version(0), mysqld_socket(0), mysqld_datadir(0),
- mysqld_bind_address(0), mysqld_pid_file(0), mysqld_port(0),
+ mysqld_pid_file(0), mysqld_port(0),
mysqld_port_val(0), mysqld_path(0), nonguarded(0), shutdown_delay(0),
shutdown_delay_val(0), filled_default_options(0)
- {}
+ {
+ memset(logs, 0, sizeof(logs));
+ }
~Instance_options();
/* fills in argv */
int complete_initialization(const char *default_path, uint instance_type);
- int add_option(const char* option);
+ my_bool add_option(const char *option_str);
+ my_bool set_option(const char *option_name, const char *option_value);
+ void unset_option(const char *option_name);
+
+ inline int get_num_options() const;
+ inline Option get_option(int idx) const;
+
+public:
int init(const char *instance_name_arg);
pid_t get_pid();
int get_pid_filename(char *result);
@@ -76,7 +86,6 @@
/* We need the some options, so we store them as a separate pointers */
const char *mysqld_socket;
const char *mysqld_datadir;
- const char *mysqld_bind_address;
const char *mysqld_pid_file;
const char *mysqld_port;
uint mysqld_port_val;
@@ -90,17 +99,50 @@
/* log enums are defined in parse.h */
char *logs[3];
- /* this value is computed and cashed here */
- DYNAMIC_ARRAY options_array;
+
+private:
+ enum VarCmd
+ {
+ CMD_SET,
+ CMD_UNSET
+ };
+
private:
int fill_log_options();
int fill_instance_version();
int add_to_argv(const char *option);
int get_default_option(char *result, size_t result_len,
const char *option_name);
+
+ static void parse_option(const char *option_str,
+ char *option_name_buf,
+ char *option_value_buf);
+
+ my_bool set_option_impl(const char *option_name, const char *option_value);
+ void update_var(VarCmd cmd, const char *option_name,
+ const char *option_value);
+ int find_option(const char *option_name);
+
private:
uint filled_default_options;
MEM_ROOT alloc;
+
+ DYNAMIC_ARRAY options;
};
+
+inline int Instance_options::get_num_options() const
+{
+ return options.elements;
+}
+
+inline Option Instance_options::get_option(int idx) const
+{
+ DBUG_ASSERT(0 <= idx && (uint) idx < options.elements);
+
+ Option option;
+ get_dynamic((DYNAMIC_ARRAY *) &options, (gptr) &option, idx);
+
+ return option;
+}
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_OPTIONS_H */
--- 1.5/server-tools/instance-manager/messages.cc 2005-05-16 01:53:56 +04:00
+++ 1.6/server-tools/instance-manager/messages.cc 2006-03-18 20:53:16 +03:00
@@ -70,6 +70,19 @@
"in the instance options";
case ER_ACCESS_OPTION_FILE:
return "Cannot open the option file to edit. Check permissions";
+ case ER_DROP_RUNNING_INSTANCE:
+ return "Cannot drop a running/managed instance. You should stop it first";
+ case ER_CREATE_EXISTING_INSTANCE:
+ return "Instance already exists";
+ case ER_INSTANCE_MISCONFIGURED:
+ return "Instance is misconfigured. Cannot start it";
+ case ER_MALFORMED_INSTANCE_NAME:
+ return "Malformed instance name. Check that instance name is formed "
+ "as follows: 'mysqld<number>'";
+ case ER_INSTANCE_IS_RUNNING:
+ return "The instance is running/managed. Stop the instance first";
+ case ER_THERE_IS_RUNNING_INSTACE:
+ return "At least one instance is running/managed. Stop all instances first";
default:
DBUG_ASSERT(0);
return 0;
--- 1.14/server-tools/instance-manager/mysql_connection.cc 2005-10-08 18:59:12 +04:00
+++ 1.15/server-tools/instance-manager/mysql_connection.cc 2006-03-18 20:53:16 +03:00
@@ -336,7 +336,7 @@
if (Command *command= parse_command(&instance_map, packet))
{
int res= 0;
- log_info("query for connection %d successefully parsed",connection_id);
+ log_info("query for connection %d successfully parsed",connection_id);
res= command->execute(&net, connection_id);
delete command;
if (!res)
--- 1.3/server-tools/instance-manager/mysql_manager_error.h 2005-05-16 01:53:56 +04:00
+++ 1.4/server-tools/instance-manager/mysql_manager_error.h 2006-03-18 20:53:16 +03:00
@@ -29,5 +29,11 @@
#define ER_ACCESS_OPTION_FILE 3008
#define ER_OFFSET_ERROR 3009
#define ER_READ_FILE 3010
+#define ER_DROP_RUNNING_INSTANCE 3011
+#define ER_CREATE_EXISTING_INSTANCE 3012
+#define ER_INSTANCE_MISCONFIGURED 3013
+#define ER_MALFORMED_INSTANCE_NAME 3014
+#define ER_INSTANCE_IS_RUNNING 3015
+#define ER_THERE_IS_RUNNING_INSTACE 3016
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H */
--- 1.13/server-tools/instance-manager/parse.cc 2006-02-18 03:22:10 +03:00
+++ 1.14/server-tools/instance-manager/parse.cc 2006-03-18 20:53:16 +03:00
@@ -22,7 +22,9 @@
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 +52,8 @@
static struct tokens_st tokens[]= {
+ {6, "CREATE"},
+ {4, "DROP"},
{5, "ERROR"},
{5, "FILES"},
{5, "FLUSH"},
@@ -67,6 +71,10 @@
{5, "UNSET"}
};
+char *StringSegment::make_str() const
+{
+ return begin_ptr ? strndup(begin_ptr, length) : NULL;
+}
/*
Returns token no if word corresponds to some token, otherwise returns
@@ -114,6 +122,194 @@
}
+static bool parse_opt_value(const char *text, uint *text_len,
+ const char **value)
+{
+ if (!*text || (*text != '\'' && *text != '"'))
+ return true; /* syntax error: string expected. */
+
+ char beginning_quote= *text;
+
+ ++text; /* skip the beginning quote ('). */
+
+ const char *text_start_ptr= text;
+ char *v= strdup(text);
+
+ bool escape_mode = false;
+
+ *value = v;
+
+ while (true)
+ {
+ if (!*text)
+ return true; /* syntax error: missing terminating ' character. */
+
+ if (*text == '\n' || *text == '\r')
+ 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 */
+ --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. */
+ 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;
+}
+
+
+static bool parse_options(const char **text, DYNAMIC_ARRAY *options)
+{
+ uint len;
+
+ /* 0. Check if we have something (and trim leading spaces). */
+
+ get_word(text, &len, NONSPACE);
+
+ if (len == 0)
+ return false; /* OK: no option. */
+
+ /* Main parsing loop. */
+
+ while (true)
+ {
+ StringSegment option_name;
+ const char *option_value_str= "";
+
+ /* 1. Looking for option name. */
+
+ get_word(text, &option_name.length, OPTION_NAME);
+
+ if (option_name.length == 0)
+ return true; /* syntax error: option name expected. */
+
+ option_name.begin_ptr= *text;
+ *text+= option_name.length;
+
+ /* 2. Looking for equal sign. */
+
+ /* Ignore spaces. */
+ while (**text && my_isspace(default_charset_info, **text))
+ ++(*text);
+
+ if (**text == '=')
+ {
+ /* Skip '='. */
+ ++(*text);
+
+ /* 3. Looking for option value. */
+
+ /* Ignore spaces. */
+ while (**text && my_isspace(default_charset_info, **text))
+ ++(*text);
+
+ if (!**text)
+ return true; /* syntax error: EOS when option value expected. */
+
+ if (**text != '\'' && **text != '"')
+ {
+ /* 3.1. Option value is a simple token. */
+
+ StringSegment option_value;
+
+ get_word(text, &option_value.length, ALPHANUM);
+
+ if (option_value.length == 0)
+ return true; /* internal parser error. */
+
+ option_value.begin_ptr= *text;
+ *text+= option_value.length;
+
+ option_value_str= option_value.make_str();
+ }
+ else
+ {
+ /* 3.2. Option value is a string. */
+
+ if (parse_opt_value(*text, &len, &option_value_str))
+ return true; /* syntax error: invalid string specification. */
+
+ printf("---> option value: '%s'\n", option_value_str);
+ fflush(stdout);
+
+ *text+= len;
+ }
+ }
+
+ Option opt(option_name.make_str(), option_value_str);
+ insert_dynamic(options, (gptr) &opt);
+
+ /* Ignore spaces. */
+ while (**text && my_isspace(default_charset_info, **text))
+ ++(*text);
+
+ if (!**text)
+ return false; /* OK: end of options. */
+
+ if (**text != ',')
+ return true; /* syntax error: comma expected. */
+
+ ++(*text);
+ }
+}
+
+
Command *parse_command(Instance_map *map, const char *text)
{
uint word_len;
@@ -134,6 +330,8 @@
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);
@@ -142,15 +340,48 @@
instance_name= text;
instance_name_len= 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= Create_instance::create(map, instance_name,
+ instance_name_len);
+
+ if (!cmd)
+ return NULL; /* Report ER_OUT_OF_RESOURCES. */
+
+ /* Parsing instance options. */
+ if (parse_options(&text, &cmd->options))
+ {
+ delete cmd;
+ goto syntax_error;
+ }
+
+ command= cmd;
+ }
else
+ {
+ /* 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, instance_name_len);
+ break;
+ case TOK_STOP:
command= new Stop_instance(map, instance_name, instance_name_len);
+ break;
+ case TOK_CREATE:
+ ; /* command already initialized. */
+ break;
+ case TOK_DROP:
+ command= new Drop_instance(map, instance_name, instance_name_len);
+ break;
+ default: /* this is impossible, but nevertheless... */
+ DBUG_ASSERT(0);
+ }
break;
case TOK_FLUSH:
if (shift_token(&text, &word_len) != TOK_INSTANCES)
@@ -165,7 +396,6 @@
case TOK_UNSET:
skip= true;
case TOK_SET:
-
if (get_text_id(&text, &instance_name_len, &instance_name))
goto syntax_error;
text+= instance_name_len;
@@ -178,17 +408,29 @@
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);
+ get_word(&text, &word_len, NONSPACE);
+
+ if (skip && word_len)
+ goto syntax_error;
+
if (*text == '=')
{
- text++; /* skip '=' */
- get_word(&text, &option_value_len, NONSPACE);
+ ++text; /* skip '=' */
+
+ /* skip spaces */
+ while (my_isspace(default_charset_info, *text))
+ ++text;
+
option_value= text;
- text+= option_value_len;
+ text+= strlen(text);
+
+ /* remove trailng spaces */
+ while (my_isspace(default_charset_info, *text))
+ --text;
+
+ option_value_len= text - option_value + 1;
}
else
{
--- 1.6/server-tools/instance-manager/parse.h 2005-08-29 23:29:27 +04:00
+++ 1.7/server-tools/instance-manager/parse.h 2006-03-18 20:53:16 +03:00
@@ -32,7 +32,42 @@
Command *parse_command(Instance_map *instance_map, const char *text);
/* define kinds of the word seek method */
-enum { ALPHANUM= 1, NONSPACE };
+enum SeekMethod { ALPHANUM= 1, NONSPACE, OPTION_NAME };
+
+class Option
+{
+public:
+ inline Option(const char *name = NULL, const char *value = NULL)
+ :_name(name), _value(value)
+ { }
+
+ inline const char *get_name() const
+ {
+ return _name;
+ }
+
+ inline const char *get_value() const
+ {
+ return _value;
+ }
+
+private:
+ const char *_name;
+ const char *_value;
+
+};
+
+struct StringSegment
+{
+ const char *begin_ptr;
+ uint length;
+
+ inline StringSegment()
+ :begin_ptr(NULL), length(0)
+ { }
+
+ char *make_str() const;
+};
/*
tries to find next word in the text
@@ -41,7 +76,7 @@
*/
inline void get_word(const char **text, uint *word_len,
- int seek_method= ALPHANUM)
+ SeekMethod seek_method= ALPHANUM)
{
const char *word_end;
@@ -51,13 +86,23 @@
word_end= *text;
- if (seek_method == ALPHANUM)
+ switch (seek_method) {
+ case ALPHANUM:
while (my_isalnum(default_charset_info, *word_end))
++word_end;
- else
+ break;
+ case NONSPACE:
while (!my_isspace(default_charset_info, *word_end) &&
(*word_end != '\0'))
++word_end;
+ break;
+ case OPTION_NAME:
+ while (my_isalnum(default_charset_info, *word_end) ||
+ *word_end == '-' ||
+ *word_end == '_')
+ ++word_end;
+ break;
+ }
*word_len= word_end - *text;
}
--- 1.10/server-tools/instance-manager/priv.cc 2006-02-10 02:15:52 +03:00
+++ 1.11/server-tools/instance-manager/priv.cc 2006-03-18 20:53:16 +03:00
@@ -43,7 +43,7 @@
The following string must be less then 80 characters, as
mysql_connection.cc relies on it
*/
-const char mysqlmanager_version[] = "0.2-alpha";
+const char mysqlmanager_version[] = "1.0-beta";
const int mysqlmanager_version_length= sizeof(mysqlmanager_version) - 1;
--- 1.10/server-tools/instance-manager/priv.h 2006-02-21 15:32:49 +03:00
+++ 1.11/server-tools/instance-manager/priv.h 2006-03-18 20:53:16 +03:00
@@ -31,6 +31,9 @@
/* three-week timeout should be enough */
#define LONG_TIMEOUT ((ulong) 3600L*24L*21L)
+const int MAX_OPTION_LEN= 1024;
+const int MAX_OPTION_STR_LEN= 2 + MAX_OPTION_LEN + 1 + MAX_OPTION_LEN + 1;
+
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
extern pid_t manager_pid;
--- 1.15/server-tools/instance-manager/user_map.cc 2005-10-07 20:25:34 +04:00
+++ 1.16/server-tools/instance-manager/user_map.cc 2006-03-18 20:53:16 +03:00
@@ -20,20 +20,11 @@
#include "user_map.h"
-#include <mysql_com.h>
#include <m_string.h>
+#include "exit_codes.h"
#include "log.h"
-struct User
-{
- char user[USERNAME_LENGTH + 1];
- uint8 user_length;
- uint8 salt[SCRAMBLE_LENGTH];
- int init(const char *line);
-};
-
-
int User::init(const char *line)
{
const char *name_begin, *name_end, *password;
@@ -72,6 +63,7 @@
memcpy(user, name_begin, user_length);
user[user_length]= 0;
+ memcpy(m_password, password, strlen(password) - 1);
get_salt_from_password(salt, password);
log_info("loaded user %s", user);
@@ -111,6 +103,11 @@
}
+User_map::User_map()
+{
+}
+
+
User_map::~User_map()
{
hash_free(&hash);
@@ -135,12 +132,7 @@
int rc= 1;
if ((file= my_fopen(password_file_name, O_RDONLY | O_BINARY, MYF(0))) == 0)
- {
- /* Probably the password file wasn't specified. Try to leave without it */
- log_info("[WARNING] can't open password file %s: errno=%d, %s", password_file_name,
- errno, strerror(errno));
- return 0;
- }
+ return ERR_IO_ERROR;
while (fgets(line, sizeof(line), file))
{
@@ -148,19 +140,51 @@
if (line[0] == '#' || line[0] == '\n' &&
(line[1] == '\0' || line[1] == '\r'))
continue;
+
if ((user= new User) == 0)
- goto done;
+ {
+ my_fclose(file, MYF(0));
+ return ERR_OUT_OF_MEMORY;
+ }
+
if (user->init(line) || my_hash_insert(&hash, (byte *) user))
- goto err_init_user;
+ {
+ delete user;
+ my_fclose(file, MYF(0));
+ return ERR_OUT_OF_MEMORY;
+ }
}
- if (feof(file))
- rc= 0;
- goto done;
-err_init_user:
- delete user;
-done:
+
+ feof(file); // XXX: ????
+ my_fclose(file, MYF(0));
+
+ return ERR_OK;
+}
+
+
+int User_map::save(const char *password_file_name)
+{
+ FILE *file;
+ User *user;
+
+ if ((file= my_fopen(password_file_name, O_WRONLY | O_TRUNC | O_BINARY,
+ MYF(0))) == 0)
+ {
+ return ERR_IO_ERROR;
+ }
+
+ for (uint i= 0; i < hash.records; ++i)
+ {
+ User *user= (User *) hash_element(&hash, i);
+
+ fprintf(file,
+ "%s:%s\n", (const char *) user->user,
+ (const char *) user->m_password);
+ }
+
my_fclose(file, MYF(0));
- return rc;
+
+ return ERR_OK;
}
@@ -176,9 +200,21 @@
const char *scrambled_password,
const char *scramble) const
{
- const User *user= (const User *) hash_search((HASH *) &hash,
- (byte *) user_name, length);
+ const User *user= find_user(user_name, length);
if (user)
return check_scramble(scrambled_password, scramble, user->salt);
return 2;
+}
+
+
+const User *User_map::find_user(const char *user_name, uint user_name_len) const
+{
+ return (const User *) hash_search((HASH *) &hash, (byte *) user_name,
+ user_name_len);
+}
+
+
+void User_map::add_user(User *user)
+{
+ my_hash_insert(&hash, (byte *) user);
}
--- 1.5/server-tools/instance-manager/user_map.h 2005-10-19 00:30:50 +04:00
+++ 1.6/server-tools/instance-manager/user_map.h 2006-03-18 20:53:16 +03:00
@@ -18,14 +18,25 @@
#include <my_global.h>
-
#include <my_sys.h>
+#include <mysql_com.h>
+
#include <hash.h>
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface
#endif
+struct User
+{
+ char user[USERNAME_LENGTH + 1];
+ char m_password[SCRAMBLED_PASSWORD_CHAR_LENGTH + 10]; // XXX
+ uint8 user_length;
+ uint8 salt[SCRAMBLE_LENGTH];
+ int init(const char *line);
+};
+
+
/*
User_map -- all users and passwords
*/
@@ -33,13 +44,23 @@
class User_map
{
public:
+ User_map();
~User_map();
int init();
int load(const char *password_file_name);
+ int save(const char *password_file_name);
int authenticate(const char *user_name, uint length,
const char *scrambled_password,
const char *scramble) const;
+
+ const User *find_user(const char *user_name, uint user_name_len) const;
+ void add_user(User *user);
+
+private:
+ User_map(const User_map &);
+ User_map &operator =(const User_map &);
+
private:
HASH hash;
};
--- 1.8/server-tools/instance-manager/portability.h 2006-02-10 02:15:52 +03:00
+++ 1.9/server-tools/instance-manager/portability.h 2006-03-18 20:53:16 +03:00
@@ -21,7 +21,16 @@
#undef popen
#define popen(A,B) _popen(A,B)
+#define NEWLINE "\r\n"
+#define NEWLINE_LEN 2
+
+#else /* ! __WIN__ */
+
+#define NEWLINE "\n"
+#define NEWLINE_LEN 1
+
#endif /* __WIN__ */
+
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PORTABILITY_H */
| Thread |
|---|
| • bk commit into 5.1 tree (anozdrin:1.2192) | Alexander Nozdrin | 18 Mar |