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.2210 06/04/04 16:31:15 anozdrin@stripped +47 -0
This is an implementation of two WL items:
- WL#3158: IM: Instance configuration extensions;
- WL#3159: IM: --bootstrap and --start-default-instance modes
The following new statements have been added:
- CREATE INSTANCE;
- DROP INSTANCE;
The behaviour of the following statements have been changed:
- SET;
- UNSET;
- FLUSH INSTANCES;
- SHOW INSTANCES;
- SHOW INSTANCE OPTIONS;
server-tools/instance-manager/exit_codes.h
1.1 06/04/04 16:31:12 anozdrin@stripped +18 -0
New file for defining exit codes for user-management mode.
server-tools/instance-manager/exit_codes.h
1.0 06/04/04 16:31:12 anozdrin@stripped +0 -0
BitKeeper file
/home/alik/Documents/AllProgs/MySQL/devel/5.1-wl3158/server-tools/instance-manager/exit_codes.h
mysql-test/t/im_utils-im.opt
1.1 06/04/04 16:31:11 anozdrin@stripped +1 -0
Set minimal monitoring interval for Instance Manager to speed up testing.
mysql-test/t/im_options.imtest
1.1 06/04/04 16:31:11 anozdrin@stripped +175 -0
Join im_options_set and im_options_unset and add some new tests.
mysql-test/t/im_life_cycle-im.opt
1.1 06/04/04 16:31:11 anozdrin@stripped +1 -0
Set minimal monitoring interval for Instance Manager to speed up testing.
mysql-test/t/im_instance_conf.imtest
1.1 06/04/04 16:31:11 anozdrin@stripped +296 -0
Added a new test case for checking instance-management.
mysql-test/t/im_utils-im.opt
1.0 06/04/04 16:31:11 anozdrin@stripped +0 -0
BitKeeper file
/home/alik/Documents/AllProgs/MySQL/devel/5.1-wl3158/mysql-test/t/im_utils-im.opt
mysql-test/t/im_options.imtest
1.0 06/04/04 16:31:11 anozdrin@stripped +0 -0
BitKeeper file
/home/alik/Documents/AllProgs/MySQL/devel/5.1-wl3158/mysql-test/t/im_options.imtest
mysql-test/t/im_life_cycle-im.opt
1.0 06/04/04 16:31:11 anozdrin@stripped +0 -0
BitKeeper file
/home/alik/Documents/AllProgs/MySQL/devel/5.1-wl3158/mysql-test/t/im_life_cycle-im.opt
mysql-test/t/im_instance_conf.imtest
1.0 06/04/04 16:31:11 anozdrin@stripped +0 -0
BitKeeper file
/home/alik/Documents/AllProgs/MySQL/devel/5.1-wl3158/mysql-test/t/im_instance_conf.imtest
mysql-test/t/im_instance_conf-im.opt
1.1 06/04/04 16:31:10 anozdrin@stripped +1 -0
Set minimal monitoring interval for Instance Manager to speed up testing.
mysql-test/r/im_options.result
1.1 06/04/04 16:31:10 anozdrin@stripped +88 -0
Added result file.
mysql-test/r/im_instance_conf.result
1.1 06/04/04 16:31:10 anozdrin@stripped +274 -0
Added result file.
server-tools/instance-manager/user_map.h
1.6 06/04/04 16:31:10 anozdrin@stripped +35 -0
Added support for managing password database.
server-tools/instance-manager/user_map.cc
1.16 06/04/04 16:31:10 anozdrin@stripped +80 -30
Added support for managing password database.
server-tools/instance-manager/priv.h
1.11 06/04/04 16:31:10 anozdrin@stripped +7 -0
Added some global constants.
server-tools/instance-manager/priv.cc
1.11 06/04/04 16:31:10 anozdrin@stripped +1 -1
Updated version.
server-tools/instance-manager/portability.h
1.9 06/04/04 16:31:10 anozdrin@stripped +9 -0
Moved system-dependent defines from instance_options.cc
server-tools/instance-manager/parse.h
1.7 06/04/04 16:31:10 anozdrin@stripped +49 -4
1. Added support of new statements:
- CREATE INSTANCE;
- DROP INSTANCE.
2. Added functionality to parse options in CREATE INSTANCE.
server-tools/instance-manager/parse.cc
1.14 06/04/04 16:31:10 anozdrin@stripped +254 -14
1. Added support of new statements:
- CREATE INSTANCE;
- DROP INSTANCE.
2. Added functionality to parse options in CREATE INSTANCE.
server-tools/instance-manager/options.h
1.15 06/04/04 16:31:10 anozdrin@stripped +27 -0
Added support for user-management command-line options.
server-tools/instance-manager/options.cc
1.31 06/04/04 16:31:10 anozdrin@stripped +454 -28
Added support for user-management command-line options.
server-tools/instance-manager/mysql_manager_error.h
1.4 06/04/04 16:31:10 anozdrin@stripped +8 -0
Added new errors.
server-tools/instance-manager/mysql_connection.cc
1.15 06/04/04 16:31:10 anozdrin@stripped +1 -3
1. Move a constant to common place.
2. Polishing.
server-tools/instance-manager/messages.cc
1.6 06/04/04 16:31:10 anozdrin@stripped +18 -1
Added messages for new errors.
server-tools/instance-manager/manager.h
1.5 06/04/04 16:31:10 anozdrin@stripped +8 -0
Added a common for IM operation to work with configuration file.
server-tools/instance-manager/manager.cc
1.32 06/04/04 16:31:10 anozdrin@stripped +145 -5
Added a common for IM operation to work with configuration file.
server-tools/instance-manager/instance_options.h
1.19 06/04/04 16:31:10 anozdrin@stripped +54 -6
Changed Instance_options so that it will be possible to manage
options on the fly.
server-tools/instance-manager/instance_options.cc
1.31 06/04/04 16:31:10 anozdrin@stripped +155 -79
Changed Instance_options so that it will be possible to manage
options on the fly.
server-tools/instance-manager/instance_map.h
1.19 06/04/04 16:31:10 anozdrin@stripped +46 -1
Added operations to manage instances.
server-tools/instance-manager/instance_map.cc
1.27 06/04/04 16:31:10 anozdrin@stripped +206 -63
1. Used the operation to check validity of instance name;
2. Added operations to manage instances.
server-tools/instance-manager/instance.h
1.16 06/04/04 16:31:10 anozdrin@stripped +39 -0
1. Provided an operation to check validity of instance name.
2. Added an attribute to distiguish mysqld-instances,
whose configuration should be kept backward-compatible.
server-tools/instance-manager/instance.cc
1.33 06/04/04 16:31:10 anozdrin@stripped +29 -6
1. Provided an operation to check validity of instance name.
2. Added an attribute to distiguish mysqld-instances,
whose configuration should be kept backward-compatible.
server-tools/instance-manager/guardian.h
1.13 06/04/04 16:31:10 anozdrin@stripped +24 -0
Added operations to retrieve state of managed instances.
server-tools/instance-manager/guardian.cc
1.21 06/04/04 16:31:10 anozdrin@stripped +69 -26
Added operations to retrieve state of managed instances.
server-tools/instance-manager/commands.h
1.10 06/04/04 16:31:10 anozdrin@stripped +190 -64
1. Added support for CREATE INSTANCE, DROP INSTANCE statements;
2. Added "managed" column in output of SHOW INSTANCES and SHOW INSTANCE OPTIONS;
3. Modified the behaviour of SET/UNSET, FLUSH INSTANCES statements;
server-tools/instance-manager/commands.cc
1.34 06/04/04 16:31:10 anozdrin@stripped +673 -427
1. Added support for CREATE INSTANCE, DROP INSTANCE statements;
2. Added "managed" column in output of SHOW INSTANCES and SHOW INSTANCE OPTIONS;
3. Modified the behaviour of SET/UNSET, FLUSH INSTANCES statements;
mysql-test/t/im_instance_conf-im.opt
1.0 06/04/04 16:31:10 anozdrin@stripped +0 -0
BitKeeper file
/home/alik/Documents/AllProgs/MySQL/devel/5.1-wl3158/mysql-test/t/im_instance_conf-im.opt
mysql-test/r/im_options.result
1.0 06/04/04 16:31:10 anozdrin@stripped +0 -0
BitKeeper file
/home/alik/Documents/AllProgs/MySQL/devel/5.1-wl3158/mysql-test/r/im_options.result
mysql-test/r/im_instance_conf.result
1.0 06/04/04 16:31:10 anozdrin@stripped +0 -0
BitKeeper file
/home/alik/Documents/AllProgs/MySQL/devel/5.1-wl3158/mysql-test/r/im_instance_conf.result
mysys/default_modify.c
1.12 06/04/04 16:31:09 anozdrin@stripped +40 -15
Added REMOVE_SECTION functionality.
mysys/default.c
1.79 06/04/04 16:31:09 anozdrin@stripped +9 -1
Pass the name of the section to the handler function as well.
mysql-test/t/im_utils.imtest
1.2 06/04/04 16:31:09 anozdrin@stripped +6 -2
Get Instance Manager and managed mysqld-instances enough time to start.
mysql-test/t/im_life_cycle.imtest
1.6 06/04/04 16:31:09 anozdrin@stripped +63 -24
1. Polishing;
2. Fixed a test error in 1.1.2.
mysql-test/t/im_daemon_life_cycle.imtest
1.2 06/04/04 16:31:09 anozdrin@stripped +3 -0
Get Instance Manager and managed mysqld-instances enough time to start.
mysql-test/t/im_daemon_life_cycle-im.opt
1.3 06/04/04 16:31:09 anozdrin@stripped +1 -0
Set minimal monitoring interval for Instance Manager to speed up testing.
mysql-test/r/im_utils.result
1.4 06/04/04 16:31:09 anozdrin@stripped +2 -4
Updated the result file.
mysql-test/r/im_life_cycle.result
1.6 06/04/04 16:31:09 anozdrin@stripped +48 -24
1. Column name has been changed in SHOW INSTANCES.
2. Removed redundant SHOW INSTANCE STATUS statements.
mysql-test/r/im_daemon_life_cycle.result
1.2 06/04/04 16:31:09 anozdrin@stripped +1 -1
Column name has been changed in SHOW INSTANCES.
mysql-test/mysql-test-run.pl
1.78 06/04/04 16:31:09 anozdrin@stripped +1 -1
Polishing.
include/my_sys.h
1.189 06/04/04 16:31:09 anozdrin@stripped +4 -0
Added constants for modify_defaults_file().
BitKeeper/deleted/.del-im_options_unset.result~20a4790cd3c70a4f
1.2 06/03/08 01:03:46 anozdrin@stripped +0 -0
Delete: mysql-test/r/im_options_unset.result
BitKeeper/deleted/.del-im_options_set.result~59278f56be61d921
1.2 06/03/08 01:03:46 anozdrin@stripped +0 -0
Delete: mysql-test/r/im_options_set.result
BitKeeper/deleted/.del-im_options_unset.imtest~768eb186b51d0048
1.3 06/03/08 01:02:38 anozdrin@stripped +0 -0
Delete: mysql-test/t/im_options_unset.imtest
BitKeeper/deleted/.del-im_options_set.imtest~b53d9d60e5684833
1.3 06/03/08 01:02:38 anozdrin@stripped +0 -0
Delete: mysql-test/t/im_options_set.imtest
# 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: station.home
# Root: /home/alik/Documents/AllProgs/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-04-04 16:31:09 +04: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-04-04 16:31:09 +04: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-04-04 16:31:09 +04:00
@@ -1,5 +1,5 @@
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
Killing the process...
--- New file ---
+++ mysql-test/r/im_instance_conf.result 06/04/04 16:31:10
--------------------------------------------------------------------
server_id = 1
server_id = 2
--------------------------------------------------------------------
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
---> connection: mysql1_con
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
---> connection: default
CREATE INSTANCE mysqld3;
SHOW INSTANCES;
instance_name state
mysqld3 offline
mysqld2 offline
mysqld1 online
SHOW INSTANCE OPTIONS mysqld3;
option_name value
instance_name mysqld3
pid-file mysqld3-station.pid
--------------------------------------------------------------------
server_id = 1
server_id = 2
--------------------------------------------------------------------
CREATE INSTANCE mysqld1;
ERROR HY000: Instance already exists
CREATE INSTANCE mysqld2;
ERROR HY000: Instance already exists
CREATE INSTANCE mysqld3;
ERROR HY000: Instance already exists
--------------------------------------------------------------------
nonguarded
--------------------------------------------------------------------
CREATE INSTANCE mysqld4 nonguarded;
SHOW INSTANCES;
instance_name state
mysqld3 offline
mysqld4 offline
mysqld1 online
mysqld2 offline
SHOW INSTANCE OPTIONS mysqld4;
option_name value
instance_name mysqld4
nonguarded
pid-file mysqld4-station.pid
--------------------------------------------------------------------
nonguarded
nonguarded
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
CREATE INSTANCE mysqld5 test-A = 000, test-B = test;
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld4 offline
mysqld5 offline
mysqld2 offline
mysqld3 offline
SHOW INSTANCE OPTIONS mysqld5;
option_name value
instance_name mysqld5
test-A 000
test-B test
pid-file mysqld5-station.pid
--------------------------------------------------------------------
test-A=000
--------------------------------------------------------------------
test-B=test
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
CREATE INSTANCE mysqld6 test-C1 = 10 , test-C2 = 02 ;
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
SHOW INSTANCE OPTIONS mysqld6;
option_name value
instance_name mysqld6
test-C1 10
test-C2 02
pid-file mysqld6-station.pid
--------------------------------------------------------------------
test-C1=10
--------------------------------------------------------------------
test-C2=02
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
CREATE INSTANCE mysqld7 test-D = test-D-value ;
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
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
CREATE INSTANCE mysqld8 test-E 0 ;
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
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
CREATE INSTANCE mysqld8 test-F = ;
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
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
CREATE INSTANCE mysqld9 test-1=" hello world ", test-2=' ';
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
mysqld9 offline
SHOW INSTANCE OPTIONS mysqld9;
option_name value
instance_name mysqld9
test-1 hello world
test-2
pid-file mysqld9-station.pid
CREATE INSTANCE mysqld9a test-3='\b\babc\sdef';
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld9a offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
mysqld9 offline
mysqld2 offline
SHOW INSTANCE OPTIONS mysqld9a;
option_name value
instance_name mysqld9a
test-3 abc def
pid-file mysqld9a-station.pid
CREATE INSTANCE mysqld9b test-4='abc\tdef', test-5='abc\ndef';
SHOW INSTANCES;
instance_name state
mysqld9b offline
mysqld9a offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
mysqld9 offline
mysqld2 offline
mysqld1 online
SHOW INSTANCE OPTIONS mysqld9b;
option_name value
instance_name mysqld9b
test-4 abc def
test-5 abc
def
pid-file mysqld9b-station.pid
CREATE INSTANCE mysqld9c test-6="abc\rdef", test-7="abc\\def";
SHOW INSTANCES;
instance_name state
mysqld9b offline
mysqld6 offline
mysqld5 offline
mysqld9c offline
mysqld3 offline
mysqld4 offline
mysqld9 offline
mysqld2 offline
mysqld1 online
mysqld9a offline
SHOW INSTANCE OPTIONS mysqld9c;
option_name value
instance_name mysqld9c
test-6 abc
def
test-7 abc\def
pid-file mysqld9c-station.pid
CREATE INSTANCE mysqld10 test-bad=' \ ';
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
SHOW INSTANCES;
instance_name state
mysqld9b offline
mysqld6 offline
mysqld5 offline
mysqld9c offline
mysqld3 offline
mysqld4 offline
mysqld9 offline
mysqld2 offline
mysqld1 online
mysqld9a offline
--------------------------------------------------------------------
test-1= hello world
--------------------------------------------------------------------
test-2=
--------------------------------------------------------------------
test-3=abc def
--------------------------------------------------------------------
test-4=abc def
--------------------------------------------------------------------
test-5=abc
--------------------------------------------------------------------
test-6=abc
def
--------------------------------------------------------------------
test-7=abc\def
--------------------------------------------------------------------
--------------------------------------------------------------------
CREATE INSTANCE qqq1;
ERROR HY000: Malformed instance name.
--------------------------------------------------------------------
server_id = 1
server_id = 2
--------------------------------------------------------------------
DROP INSTANCE mysqld3;
SHOW INSTANCES;
instance_name state
mysqld9b offline
mysqld9a offline
mysqld5 offline
mysqld9c offline
mysqld6 offline
mysqld4 offline
mysqld9 offline
mysqld2 offline
mysqld1 online
--------------------------------------------------------------------
server_id = 1
server_id = 2
--------------------------------------------------------------------
DROP INSTANCE mysqld100;
ERROR HY000: Bad instance name. Check that the instance with such a name exists
DROP INSTANCE mysqld1;
ERROR HY000: Cannot drop an active instance. You should stop it first
CREATE INSTANCE mysqld10 datadir = '/';
START INSTANCE mysqld10;
DROP INSTANCE mysqld10;
ERROR HY000: Cannot drop an active instance. You should stop it first
STOP INSTANCE mysqld10;
SHOW INSTANCE STATUS mysqld10;
instance_name state version_number version deprecated?
mysqld10 offline VERSION_NUMBER VERSION good
DROP INSTANCE mysqld10;
--- 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-04-04 16:31:09 +04:00
@@ -1,69 +1,93 @@
+
+--------------------------------------------------------------------
+-- 1.1.1.
+--------------------------------------------------------------------
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
-SHOW INSTANCE STATUS mysqld1;
-instance_name status version_number version
-mysqld1 online VERSION_NUMBER VERSION
-SHOW INSTANCE STATUS mysqld2;
-instance_name status version_number version
-mysqld2 offline VERSION_NUMBER VERSION
+
+--------------------------------------------------------------------
+-- 1.1.2.
+--------------------------------------------------------------------
START INSTANCE mysqld2;
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 online
-SHOW INSTANCE STATUS mysqld1;
-instance_name status version_number version
-mysqld1 online VERSION_NUMBER VERSION
-SHOW INSTANCE STATUS mysqld2;
-instance_name status version_number version
-mysqld2 online VERSION_NUMBER VERSION
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
+instance_name state
mysqld1 online
mysqld2 offline
SHOW INSTANCE STATUS mysqld1;
-instance_name status version_number version
-mysqld1 online VERSION_NUMBER VERSION
+instance_name state version_number version deprecated?
+mysqld1 online VERSION_NUMBER VERSION good
SHOW INSTANCE STATUS mysqld2;
-instance_name status version_number version
-mysqld2 offline VERSION_NUMBER VERSION
+instance_name state version_number version deprecated?
+mysqld2 offline VERSION_NUMBER VERSION good
+
+--------------------------------------------------------------------
+-- 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
+
+--------------------------------------------------------------------
+-- 1.1.6.
+--------------------------------------------------------------------
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
Killing the process...
Sleeping...
Success: the process was restarted.
+
+--------------------------------------------------------------------
+-- 1.1.7.
+--------------------------------------------------------------------
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
START INSTANCE mysqld2;
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 online
Killing the process...
Sleeping...
Success: the process was killed.
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
+
+--------------------------------------------------------------------
+-- 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
+
+--------------------------------------------------------------------
+-- BUG#12813
+--------------------------------------------------------------------
START INSTANCE mysqld1,mysqld2,mysqld3;
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
STOP INSTANCE mysqld1,mysqld2,mysqld3;
--- New file ---
+++ mysql-test/r/im_options.result 06/04/04 16:31:10
server_id = 1
server_id = 2
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
SHOW INSTANCES;
instance_name state
mysqld1 starting
mysqld2 offline
UNSET mysqld1.server_id;
ERROR HY000: The instance is active. Stop the instance first
SET mysqld1.server_id = 11;
ERROR HY000: The instance is active. Stop the instance first
CREATE INSTANCE mysqld3 datadir = '/';
START INSTANCE mysqld3;
UNSET mysqld3.server_id;
ERROR HY000: The instance is active. Stop the instance first
SET mysqld3.server_id = 11;
ERROR HY000: The instance is active. Stop the instance first
STOP INSTANCE mysqld3;
SHOW INSTANCE STATUS mysqld3;
instance_name state version_number version deprecated?
mysqld3 offline VERSION_NUMBER VERSION good
DROP INSTANCE mysqld3;
UNSET mysqld2.server_id;
UNSET mysqld2.server_id;
SHOW INSTANCE OPTIONS mysqld2;
option_name value
instance_name option_value
socket option_value
pid-file option_value
port option_value
datadir option_value
log option_value
log-error option_value
log-slow-queries option_value
language option_value
character-sets-dir option_value
basedir option_value
skip-stack-trace option_value
skip-innodb option_value
skip-bdb option_value
skip-ndbcluster option_value
nonguarded option_value
log-output option_value
SET mysqld2.server_id = 2;
SET mysqld2.server_id = 2;
SHOW INSTANCE OPTIONS mysqld2;
option_name value
instance_name option_value
socket option_value
pid-file option_value
port option_value
datadir option_value
log option_value
log-error option_value
log-slow-queries option_value
language option_value
character-sets-dir option_value
basedir option_value
skip-stack-trace option_value
skip-innodb option_value
skip-bdb option_value
skip-ndbcluster option_value
nonguarded option_value
log-output option_value
server_id option_value
UNSET mysqld2.server_id = 11;
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
SET mysqld2.server_id = 222;
SET mysqld2.server_id = 222 ;
server_id = 1
server_id=222
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
FLUSH INSTANCES;
ERROR HY000: At least one instance is active. Stop all instances first
STOP INSTANCE mysqld1;
SHOW INSTANCES;
instance_name state
mysqld1 offline
mysqld2 offline
FLUSH INSTANCES;
--- 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-04-04 16:31:09 +04:00
@@ -1,11 +1,10 @@
SHOW INSTANCES;
-instance_name status
+instance_name state
mysqld1 online
mysqld2 offline
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.2/mysql-test/t/im_daemon_life_cycle-im.opt 2006-01-24 10:30:47 +03:00
+++ 1.3/mysql-test/t/im_daemon_life_cycle-im.opt 2006-04-04 16:31:09 +04:00
@@ -1,2 +1,3 @@
--run-as-service
--log=$MYSQLTEST_VARDIR/log/im.log
+--monitoring-interval=1
--- 1.1/mysql-test/t/im_daemon_life_cycle.imtest 2005-10-01 01:14:38 +04:00
+++ 1.2/mysql-test/t/im_daemon_life_cycle.imtest 2006-04-04 16:31:09 +04:00
@@ -10,6 +10,9 @@
###########################################################################
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
+
SHOW INSTANCES;
--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted
--- New file ---
+++ mysql-test/t/im_instance_conf-im.opt 06/04/04 16:31:10
--monitoring-interval=1
--- New file ---
+++ mysql-test/t/im_instance_conf.imtest 06/04/04 16:31:11
###########################################################################
#
# This test suite checks the following statements:
# - CREATE INSTANCE <instance_name> [option1[=option1_value], ...];
# - DROP INSTANCE <instance_name>;
#
# For CREATE INSTANCE we check that:
# - CREATE INSTANCE succeeds for non-existing instance;
# - CREATE INSTANCE fails for existing instance;
# - CREATE INSTANCE can get additional options with and w/o values;
# - CREATE INSTANCE parses options and handles grammar errors correctly.
# Check that strings with spaces are handled correctly, unknown (for
# mysqld) options should also be handled;
# - CREATE INSTANCE updates both config file and internal configuration cache;
# - CREATE INSTANCE allows to create instances only with properly formed
# names (mysqld*);
#
# For DROP INSTANCE we check that:
# - DROP INSTANCE succeeds for existing instance;
# - DROP INSTANCE fails for non-existing instance;
# - DROP INSTANCE fails for active instance.
# - DROP INSTANCE updates both config file and internal configuration cache;
#
###########################################################################
--source include/im_check_os.inc
###########################################################################
#
# Check starting conditions.
#
###########################################################################
# Check that the configuration file contains only instances that we expect.
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
# Check that mysqld1 is reported as running.
--sleep 3
# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES;
# Check that the expected mysqld instance is actually run (check that we can
# connect and execute something).
--echo
--echo ---> connection: mysql1_con
--connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--disconnect mysql1_con
--echo
--echo ---> connection: default
--connection default
###########################################################################
#
# CREATE INSTANCE tests.
#
###########################################################################
# Check that CREATE INSTANCE succeeds for non-existing instance and also check
# that both config file and internal configuration cache have been updated.
CREATE INSTANCE mysqld3;
SHOW INSTANCES;
SHOW INSTANCE OPTIONS mysqld3;
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
# Check that CREATE INSTANCE fails for existing instance. Let's all three
# existing instances (running one, stopped one and just created one). Just in
# case...
--error 3012 # ER_CREATE_EXISTING_INSTANCE
CREATE INSTANCE mysqld1;
--error 3012 # ER_CREATE_EXISTING_INSTANCE
CREATE INSTANCE mysqld2;
--error 3012 # ER_CREATE_EXISTING_INSTANCE
CREATE INSTANCE mysqld3;
# Check that CREATE INSTANCE can get additional options with and w/o values.
# Ensure that config file is updated properly.
# - without values;
--echo --------------------------------------------------------------------
--exec grep nonguarded $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
CREATE INSTANCE mysqld4 nonguarded;
SHOW INSTANCES;
SHOW INSTANCE OPTIONS mysqld4;
--echo --------------------------------------------------------------------
--exec grep nonguarded $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
# - with value;
--echo --------------------------------------------------------------------
--exec grep test-A $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-B $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
CREATE INSTANCE mysqld5 test-A = 000, test-B = test;
SHOW INSTANCES;
SHOW INSTANCE OPTIONS mysqld5;
--echo --------------------------------------------------------------------
--exec grep test-A $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-B $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
# Check that CREATE INSTANCE parses options and handles grammar errors
# correctly. Check that strings with spaces are handled correctly,
# unknown (for mysqld) options should also be handled.
# - check handling of extra spaces;
--echo --------------------------------------------------------------------
--exec grep test-C $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
CREATE INSTANCE mysqld6 test-C1 = 10 , test-C2 = 02 ;
SHOW INSTANCES;
SHOW INSTANCE OPTIONS mysqld6;
--echo --------------------------------------------------------------------
--exec grep test-C1 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-C2 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
# - check handling of grammar error;
--echo --------------------------------------------------------------------
--exec grep test-D $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-E $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--error ER_SYNTAX_ERROR
CREATE INSTANCE mysqld7 test-D = test-D-value ;
SHOW INSTANCES;
--error ER_SYNTAX_ERROR
CREATE INSTANCE mysqld8 test-E 0 ;
SHOW INSTANCES;
--error ER_SYNTAX_ERROR
CREATE INSTANCE mysqld8 test-F = ;
SHOW INSTANCES;
--echo --------------------------------------------------------------------
--exec grep test-D $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-E $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
# - check parsing of string option values
--echo --------------------------------------------------------------------
--exec grep test-1 $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-2 $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-3 $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-4 $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
CREATE INSTANCE mysqld9 test-1=" hello world ", test-2=' ';
SHOW INSTANCES;
SHOW INSTANCE OPTIONS mysqld9;
CREATE INSTANCE mysqld9a test-3='\b\babc\sdef';
# test-3='abc def'
SHOW INSTANCES;
SHOW INSTANCE OPTIONS mysqld9a;
CREATE INSTANCE mysqld9b test-4='abc\tdef', test-5='abc\ndef';
SHOW INSTANCES;
SHOW INSTANCE OPTIONS mysqld9b;
CREATE INSTANCE mysqld9c test-6="abc\rdef", test-7="abc\\def";
# test-6=abc
SHOW INSTANCES;
SHOW INSTANCE OPTIONS mysqld9c;
--error ER_SYNTAX_ERROR
CREATE INSTANCE mysqld10 test-bad=' \ ';
SHOW INSTANCES;
--echo --------------------------------------------------------------------
--exec grep test-1 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-2 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-3 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-4 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-5 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-6 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-7 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-bad $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
# Check that CREATE INSTANCE allows to create instances only with properly
# formed names (mysqld*).
--error 3014 # ER_MALFORMED_INSTANCE_NAME
CREATE INSTANCE qqq1;
###########################################################################
#
# DROP INSTANCE tests.
#
###########################################################################
# Check that DROP INSTANCE succeeds for existing instance. Ensure that both
# config file and internal configuration cache are updated.
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
DROP INSTANCE mysqld3;
SHOW INSTANCES;
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
# Check that DROP INSTANCE fails for non-existing instance.
--error 3000 # ER_BAD_INSTANCE_NAME
DROP INSTANCE mysqld100;
# Check that DROP INSTANCE fails for running instance.
--error 3011 # ER_DROP_ACTIVE_INSTANCE
DROP INSTANCE mysqld1;
# Check that DROP INSTANCE fails for active instance:
# - create dummy misconfigured instance;
# - start it;
# - try to drop it;
CREATE INSTANCE mysqld10 datadir = '/';
START INSTANCE mysqld10;
# FIXME: START INSTANCE should be synchronous.
--sleep 3
# should be longer than monitoring interval and enough to start instance.
# NOTE: We can not analyze state of the instance here -- it can be Failed or
# Starting because Instance Manager is trying to start the misconfigured
# instance several times.
--error 3011 # ER_DROP_ACTIVE_INSTANCE
DROP INSTANCE mysqld10;
STOP INSTANCE mysqld10;
# FIXME: STOP INSTANCE should be synchronous.
--sleep 3
# should be longer than monitoring interval and enough to stop instance.
--replace_column 3 VERSION_NUMBER 4 VERSION
SHOW INSTANCE STATUS mysqld10;
DROP INSTANCE mysqld10;
--- New file ---
+++ mysql-test/t/im_life_cycle-im.opt 06/04/04 16:31:11
--monitoring-interval=1
--- 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-04-04 16:31:09 +04:00
@@ -17,11 +17,15 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.1.
+--echo --------------------------------------------------------------------
+
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
+
SHOW INSTANCES;
---replace_column 3 VERSION_NUMBER 4 VERSION
-SHOW INSTANCE STATUS mysqld1;
---replace_column 3 VERSION_NUMBER 4 VERSION
-SHOW INSTANCE STATUS mysqld2;
###########################################################################
#
@@ -33,20 +37,22 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.2.
+--echo --------------------------------------------------------------------
+
START INSTANCE mysqld2;
-# FIXME
+# FIXME: START INSTANCE should be synchronous.
--sleep 3
+# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES;
---replace_column 3 VERSION_NUMBER 4 VERSION
-SHOW INSTANCE STATUS mysqld1;
---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,9 +67,15 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.3.
+--echo --------------------------------------------------------------------
+
STOP INSTANCE mysqld2;
-# FIXME
+# FIXME: STOP INSTANCE should be synchronous.
--sleep 3
+# should be longer than monitoring interval and enough to stop instance.
SHOW INSTANCES;
--replace_column 3 VERSION_NUMBER 4 VERSION
@@ -81,16 +93,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 +114,11 @@
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.5.
+--echo --------------------------------------------------------------------
+
--error 3000
STOP INSTANCE mysqld3;
@@ -109,31 +127,41 @@
# --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
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
+
###########################################################################
#
# 1.1.7. Check that Instance Manager does not restart non-guarded instance.
#
###########################################################################
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.7.
+--echo --------------------------------------------------------------------
+
SHOW INSTANCES;
START INSTANCE mysqld2;
-# FIXME
+# FIXME: START INSTANCE should be synchronous.
--sleep 3
+# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES;
@@ -147,7 +175,13 @@
# incomplete SHOW INSTANCE STATUS command.
#
###########################################################################
---error 1149
+
+--echo
+--echo --------------------------------------------------------------------
+--echo -- 1.1.8.
+--echo --------------------------------------------------------------------
+
+--error ER_SYNTAX_ERROR
SHOW INSTANCE STATUS;
#
@@ -159,8 +193,13 @@
# a list as argument.
#
---error 1149
+--echo
+--echo --------------------------------------------------------------------
+--echo -- BUG#12813
+--echo --------------------------------------------------------------------
+
+--error ER_SYNTAX_ERROR
START INSTANCE mysqld1,mysqld2,mysqld3;
---error 1149
+--error ER_SYNTAX_ERROR
STOP INSTANCE mysqld1,mysqld2,mysqld3;
--- New file ---
+++ mysql-test/t/im_options.imtest 06/04/04 16:31:11
###########################################################################
#
# This test suite checks the following statements:
# - SET <instance id>.<option name> = <option value>;
# - UNSET <instance id>.<option name> = <option value>;
# - FLUSH INSTANCES;
#
# For SET/UNSET we check that:
# - SET ignores spaces correctly;
# - UNSET does not allow option-value part (= <option value>);
# - SET/UNSET can be applied several times w/o error;
# - SET/UNSET is allowed only for stopped instances;
# - SET/UNSET updates both the configuration cache in IM and
# the configuration file;
#
# For FLUSH INSTANCES we check that:
# - FLUSH INSTANCES is allowed only when all instances are stopped;
#
# According to the IM implementation details, we should play at least with the
# following options:
# - server_id
# - port
# - nonguarded
# Let's test SET statement on the option 'server_id'. It's expected that
# originally the instances have the following server ids and states:
# - mysqld1: server_id: 1; running (online)
# - mysqld2: server_id: 2; stopped (offline)
#
###########################################################################
--source include/im_check_os.inc
###########################################################################
#
# Check starting conditions.
#
###########################################################################
# - check the configuration file;
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
# - check the running instances.
--connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--connection default
# - check the internal cache.
SHOW INSTANCES;
###########################################################################
#
# Check that SET/UNSET is allowed only for stopped instances.
#
###########################################################################
# - check that SET/UNSET is denied for running instances;
--error 3015 # ER_INSTANCE_IS_ACTIVE
UNSET mysqld1.server_id;
--error 3015 # ER_INSTANCE_IS_ACTIVE
SET mysqld1.server_id = 11;
# - check that SET/UNSET is denied for active instances:
# - create dummy misconfigured instance;
# - start it;
# - try to set/unset options;
CREATE INSTANCE mysqld3 datadir = '/';
START INSTANCE mysqld3;
# FIXME: START INSTANCE should be synchronous.
--sleep 3
# should be longer than monitoring interval and enough to start instance.
# NOTE: We can not analyze state of the instance here -- it can be Failed or
# Starting because Instance Manager is trying to start the misconfigured
# instance several times.
--error 3015 # ER_INSTANCE_IS_ACTIVE
UNSET mysqld3.server_id;
--error 3015 # ER_INSTANCE_IS_ACTIVE
SET mysqld3.server_id = 11;
STOP INSTANCE mysqld3;
# FIXME: STOP INSTANCE should be synchronous.
--sleep 3
# should be longer than monitoring interval and enough to stop instance.
--replace_column 3 VERSION_NUMBER 4 VERSION
SHOW INSTANCE STATUS mysqld3;
DROP INSTANCE mysqld3;
# - check that SET/UNSET succeed for stopped instances;
# - check that SET/UNSET can be applied multiple times;
UNSET mysqld2.server_id;
UNSET mysqld2.server_id;
--replace_column 2 option_value
SHOW INSTANCE OPTIONS mysqld2;
SET mysqld2.server_id = 2;
SET mysqld2.server_id = 2;
--replace_column 2 option_value
SHOW INSTANCE OPTIONS mysqld2;
# - check that UNSET does not allow option-value part (= <option value>);
--error ER_SYNTAX_ERROR
UNSET mysqld2.server_id = 11;
# - check that extra spaces are ignored;
SET mysqld2.server_id = 222;
SET mysqld2.server_id = 222 ;
###########################################################################
#
# Check that SET/UNSET updates both the configuration cache in IM and
# the configuration file.
#
###########################################################################
# - check that the configuration file has been updated (i.e. contains
# server_id=SERVER_ID for mysqld2);
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
# - (for mysqld1) check that the running instance has not been affected:
# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
# returns zero;
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--connection default
# - check that internal cache of Instance Manager has been affected;
# TODO: we should check only server_id option here.
# SHOW INSTANCE OPTIONS mysqld2;
###########################################################################
#
# Check that FLUSH INSTANCES is allowed only when all instances are stopped.
#
###########################################################################
SHOW INSTANCES;
--error 3016 # ER_THERE_IS_ACTIVE_INSTACE
FLUSH INSTANCES;
STOP INSTANCE mysqld1;
# FIXME: STOP INSTANCE should be synchronous.
--sleep 3
# should be longer than monitoring interval and enough to stop instance.
SHOW INSTANCES;
FLUSH INSTANCES;
--- New file ---
+++ mysql-test/t/im_utils-im.opt 06/04/04 16:31:11
--monitoring-interval=1
--- 1.1/mysql-test/t/im_utils.imtest 2005-10-01 01:14:39 +04:00
+++ 1.2/mysql-test/t/im_utils.imtest 2006-04-04 16:31:09 +04:00
@@ -17,6 +17,9 @@
# - the second instance is offline;
#
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
+
SHOW INSTANCES;
#
@@ -41,8 +44,9 @@
START INSTANCE mysqld2;
-# FIXME
--- sleep 3
+# FIXME: START INSTANCE should be synchronous.
+--sleep 3
+# should be longer than monitoring interval and enough to start instance.
STOP INSTANCE mysqld2;
--- New file ---
+++ server-tools/instance-manager/exit_codes.h 06/04/04 16:31:12
#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_PASSWORD_FILE_DOES_NOT_EXIST = 6;
const int ERR_CAN_NOT_READ_USER_NAME = 10;
const int ERR_CAN_NOT_READ_PASSWORD = 11;
const int ERR_USER_ALREADY_EXISTS = 12;
const int ERR_USER_NOT_FOUND = 13;
#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-04-04 16:31:09 +04: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.77/mysql-test/mysql-test-run.pl 2006-03-01 17:29:31 +03:00
+++ 1.78/mysql-test/mysql-test-run.pl 2006-04-04 16:31:09 +04:00
@@ -1909,7 +1909,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-04-04 16:31:10 +04: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"
@@ -25,6 +26,11 @@
#include "user_map.h"
#include "log.h"
#include "guardian.h"
+#include "portability.h"
+#include "parse.h"
+
+#include "mysqld_error.h"
+#include "mysql_manager_error.h"
#include <my_sys.h>
#include <m_string.h>
@@ -40,7 +46,7 @@
if (FILE *pid_file= my_fopen(pid_file_name,
O_WRONLY | O_CREAT | O_BINARY, MYF(0)))
{
- fprintf(pid_file, "%d\n", (int) getpid());
+ fprintf(pid_file, "%d\n", (int) getpid()); // XXX: what if we failed to write?!
my_fclose(pid_file, MYF(0));
return 0;
}
@@ -109,10 +115,13 @@
listener thread, write pid file and enter into signal handling.
See also comments in mysqlmanager.cc to picture general Instance Manager
architecture.
+
+ TODO: how about returning error status.
*/
void manager(const Options &options)
{
+ int err_code;
Thread_registry thread_registry;
/*
All objects created in the manager() function live as long as
@@ -132,15 +141,69 @@
manager_pid= getpid();
instance_map.guardian= &guardian_thread;
- if (instance_map.init() || user_map.init())
+ /* Initialize instance map. */
+
+ if (instance_map.init())
+ {
+ log_error("Error: can not initialize instance list: out of memory.");
return;
+ }
- if (user_map.load(options.password_file_name))
+ /* Initialize user map and load password file. */
+
+ if (user_map.init())
+ {
+ log_error("Error: can not initialize user list: out of memory.");
return;
+ }
+
+ switch (err_code= user_map.load(options.password_file_name))
+ {
+ case ERR_OK:
+ break;
+
+ case ERR_IO_ERROR:
+ log_error("Error: can not load password file (%s): %s.",
+ (const char *) options.password_file_name,
+ (const char *) strerror(errno));
+ return;
+
+ case ERR_PASSWORD_FILE_CORRUPTED:
+ log_error("Error: password file (%s) corrupted.",
+ (const char *) options.password_file_name);
+ return;
+
+ case ERR_PASSWORD_FILE_DOES_NOT_EXIST:
+ if (Options::mysqld_safe_compatible)
+ {
+ /*
+ The password file does not exist, but we are running in
+ mysqld_safe-compatible mode. Continue, but complain in log.
+ */
+
+ log_error("Warning: password file does not exist, "
+ "nobody will be able to connect to Instance Manager.");
+ break;
+ }
+
+ log_error("Error: password file (%s) does not exist.",
+ (const char *) options.password_file_name);
+ return;
+
+ case ERR_OUT_OF_MEMORY:
+ log_error("Error: out of memory while parsing password file (%s).",
+ (const char *) options.password_file_name);
+ return;
+
+ default:
+ log_error("Error: can not load password file (%s).",
+ (const char *) options.password_file_name);
+ return;
+ }
/* write pid file */
if (create_pid_file(options.pid_file_name))
- return;
+ return; /* necessary logging has been already done. */
sigset_t mask;
set_signals(&mask);
@@ -198,7 +261,15 @@
shutdown_complete= FALSE;
- if (instance_map.flush_instances())
+ instance_map.guardian->lock();
+ instance_map.lock();
+
+ int flush_instances_status = instance_map.flush_instances();
+
+ instance_map.unlock();
+ instance_map.guardian->unlock();
+
+ if (flush_instances_status)
{
log_error("Cannot init instances repository. This might be caused by "
"the wrong config file options. For instance, missing mysqld "
@@ -263,3 +334,72 @@
#endif
}
+
+int create_instance_in_config_file(const char *instance_name,
+ uint instance_name_len,
+ DYNAMIC_ARRAY *options)
+{
+ File cnf_file;
+
+ if (my_access(Options::config_file, W_OK))
+ {
+ log_error("Error: configuration file (%s) does not exist.",
+ (const char *) Options::config_file);
+ return ER_CONF_FILE_DOES_NOT_EXIST;
+ }
+
+ cnf_file= my_open(Options::config_file, O_WRONLY | O_APPEND, MYF(0));
+
+ if (cnf_file <= 0)
+ {
+ log_error("Error: can not open configuration file (%s): %s.",
+ (const char *) Options::config_file,
+ (const char *) strerror(errno));
+ 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)))
+ {
+ log_error("Error: I/O operation failed (configuration file: %s): %s.",
+ (const char *) Options::config_file,
+ (const char *) strerror(errno));
+ my_close(cnf_file, MYF(0));
+ 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)))
+ {
+ log_error("Error: I/O operation failed (configuration file: %s): %s.",
+ (const char *) Options::config_file,
+ (const char *) strerror(errno));
+ my_close(cnf_file, MYF(0));
+ return ER_ACCESS_OPTION_FILE;
+ }
+ }
+
+ my_close(cnf_file, MYF(0));
+
+ return 0;
+}
--- 1.4/server-tools/instance-manager/manager.h 2005-07-20 19:55:23 +04:00
+++ 1.5/server-tools/instance-manager/manager.h 2006-04-04 16:31:10 +04:00
@@ -16,8 +16,16 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <my_sys.h>
+
struct Options;
void manager(const Options &options);
+
+int create_instance_in_config_file(const char *instance_name,
+ uint instance_name_len,
+ DYNAMIC_ARRAY *options);
+
+
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
--- 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-04-04 16:31:10 +04: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>
@@ -57,6 +59,13 @@
char **Options::saved_argv= NULL;
/* 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;
+
+bool Options::mysqld_safe_compatible= false;
+
+PasswordMgmtCmd Options::pm_cmd= PMC_NOP;
/*
List of options, accepted by the instance manager.
@@ -64,23 +73,33 @@
*/
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,
+ OPT_LIST_USERS,
+ OPT_MYSQLD_SAFE_COMPATIBLE
};
static struct my_option my_long_options[] =
@@ -100,7 +119,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,17 +148,23 @@
(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},
+
#else
+
{ "run-as-service", OPT_RUN_AS_SERVICE,
"Daemonize and start angel process.", (gptr *) &Options::run_as_service,
0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
@@ -148,7 +173,9 @@
(gptr *) &Options::user,
(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 +184,42 @@
(gptr *) &net_read_timeout, (gptr *) &net_read_timeout, 0, GET_ULONG,
REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 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 },
+
+ { "list-users", OPT_LIST_USERS, "Print out a list of registered users",
+ 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 },
+
+ { "mysqld-safe-compatible", OPT_MYSQLD_SAFE_COMPATIBLE,
+ "Start Instance Manager in mysqld_safe compatible manner",
+ (gptr *) &Options::mysqld_safe_compatible,
+ (gptr *) &Options::mysqld_safe_compatible,
+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
+
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }
};
@@ -190,37 +253,355 @@
}
-static void passwd()
+/**************************************************************************
+ Password management functions.
+**************************************************************************/
+
+static char user_name_buf[1024];
+
+
+static const char *get_user_name()
+{
+ 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, "Error: unable to read user name from stdin.\n");
+ return NULL;
+ }
+
+ if ((ptr= strchr(user_name_buf, '\n')))
+ *ptr= 0;
+
+ return user_name_buf;
+}
+
+
+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, "Error: passwords do not match.\n");
+ return 0;
+ }
+
+ return passwd1;
+}
+
+
+static int load_password_file(User_map *user_map,
+ const char *password_file_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];
+ int err_code;
- fprintf(stderr, "Creating record for new user.\n");
- fprintf(stderr, "Enter user name: ");
- if (!fgets(user, sizeof(user), stdin))
+ if (user_map->init())
{
- fprintf(stderr, "Unable to read user.\n");
- return;
+ fprintf(stderr, "Error: can not initialize user map.\n");
+ return ERR_OUT_OF_MEMORY;
}
- if ((p= strchr(user, '\n'))) *p= 0;
- pw1= get_tty_password(pw1msg);
- pw2= get_tty_password(pw2msg);
+ switch (err_code= user_map->load(password_file_name))
+ {
+ case ERR_OK:
+ break;
+
+ case ERR_IO_ERROR:
+ fprintf(stderr, "Error: can not load password file (%s): %s.\n",
+ (const char *) password_file_name,
+ (const char *) strerror(errno));
+ break;
+
+ case ERR_PASSWORD_FILE_CORRUPTED:
+ fprintf(stderr, "Error: password file (%s) corrupted.\n",
+ (const char *) password_file_name);
+ break;
+
+ case ERR_PASSWORD_FILE_DOES_NOT_EXIST:
+ fprintf(stderr, "Error: password file (%s) does not exist.\n",
+ (const char *) password_file_name);
+ break;
+
+ case ERR_OUT_OF_MEMORY:
+ fprintf(stderr, "Error: out of memory while parsing password file (%s).\n",
+ (const char *) password_file_name);
+ break;
+
+ default:
+ fprintf(stderr, "Error: can not load password file (%s).\n",
+ (const char *) password_file_name);
+ break;
+ }
+
+ return err_code;
+}
+
- if (strcmp(pw1, pw2))
+static int save_password_file(User_map *user_map,
+ const char *password_file_name)
+{
+ int err_code;
+
+ switch (err_code= user_map->save(password_file_name))
{
- fprintf(stderr, "Sorry, passwords do not match.\n");
- return;
+ case ERR_OK:
+ break;
+
+ case ERR_IO_ERROR:
+ fprintf(stderr, "Error: can not save password file (%s): %s.\n",
+ (const char *) password_file_name,
+ (const char *) strerror(errno));
+ break;
+
+ default:
+ fprintf(stderr, "Error: can not save password file (%s).\n",
+ (const char *) password_file_name);
+ break;
}
- make_scrambled_password(crypted_pw, pw1);
- printf("%s:%s\n", user, crypted_pw);
+ return err_code;
+}
+
+
+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()
+{
+ const char *user_name;
+ const char *password;
+ char scrambled_password_buf[SCRAMBLED_PASSWORD_CHAR_LENGTH + 1];
+
+ User_map user_map;
+
+ int err_code;
+
+ if (!(user_name= get_user_name()))
+ return ERR_CAN_NOT_READ_USER_NAME;
+
+ // Load the password file.
+
+ if ((err_code= load_password_file(&user_map, Options::password_file_name)))
+ return err_code;
+
+ // Check that the user does not exist.
+
+ 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;
+ }
+
+ // Add the user.
+
+ if (!(password= get_password()))
+ return ERR_CAN_NOT_READ_PASSWORD;
+
+ make_scrambled_password(scrambled_password_buf, password);
+
+ User *new_user = new User();
+ strcpy(new_user->user, user_name);
+ strcpy(new_user->scrambled_password, scrambled_password_buf);
+
+ user_map.add_user(new_user);
+
+ // Save the password file.
+
+ return save_password_file(&user_map, Options::password_file_name);
}
+static int drop_user()
+{
+ const char *user_name;
+
+ User_map user_map;
+ User *user;
+
+ int err_code;
+
+ if (!(user_name= get_user_name()))
+ return ERR_CAN_NOT_READ_USER_NAME;
+
+ // Load the password file.
+
+ if ((err_code= load_password_file(&user_map, Options::password_file_name)))
+ return err_code;
+
+ // Find the user.
+
+ user= user_map.find_user(user_name, strlen(user_name));
+
+ if (!user)
+ {
+ fprintf(stderr, "Error: user '%s' does not exist.\n",
+ (const char *) user_name);
+ return ERR_USER_NOT_FOUND;
+ }
+
+ // Remove the user.
+
+ user_map.remove_user(user);
+
+ // Save the password file.
+
+ return save_password_file(&user_map, Options::password_file_name);
+}
+
+
+static int edit_user()
+{
+ const char *user_name;
+ const char *password;
+ char scrambled_password_buf[SCRAMBLED_PASSWORD_CHAR_LENGTH + 1];
+
+ User_map user_map;
+ User *user;
+
+ int err_code;
+
+ if (!(user_name= get_user_name()))
+ return ERR_CAN_NOT_READ_USER_NAME;
+
+ // Load the password file.
+
+ if ((err_code= load_password_file(&user_map, Options::password_file_name)))
+ return err_code;
+
+ // Find the user.
+
+ user= user_map.find_user(user_name, strlen(user_name));
+
+ if (!user)
+ {
+ fprintf(stderr, "Error: user '%s' does not exist.\n",
+ (const char *) user_name);
+ return ERR_USER_NOT_FOUND;
+ }
+
+ // Modify user's password.
+
+ if (!(password= get_password()))
+ return ERR_CAN_NOT_READ_PASSWORD;
+
+ make_scrambled_password(scrambled_password_buf, password);
+
+ strcpy(user->scrambled_password, scrambled_password_buf);
+
+ // Save the password file.
+
+ return save_password_file(&user_map, Options::password_file_name);
+}
+
+
+static int clean_password_file()
+{
+ User_map user_map;
+
+ if (user_map.init())
+ {
+ fprintf(stderr, "Error: can not initialize user map.\n");
+ return ERR_OUT_OF_MEMORY;
+ }
+
+ return save_password_file(&user_map, Options::password_file_name);
+}
+
+
+static int check_password_file()
+{
+ User_map user_map;
+
+ return load_password_file(&user_map, Options::password_file_name);
+}
+
+
+static int list_users()
+{
+ User_map user_map;
+
+ int err_code;
+
+ // Load the password file.
+
+ if ((err_code= load_password_file(&user_map, Options::password_file_name)))
+ return err_code;
+
+ // Print out registered users.
+
+ for (uint i= 0; i < user_map.hash.records; ++i)
+ {
+ fprintf(stderr, "%s\n",
+ (const char *) ((User *) hash_element(&user_map.hash, i))->user);
+ }
+
+ return ERR_OK;
+}
+
+
+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();
+
+ case PMC_LIST_USERS:
+ return list_users();
+
+ case PMC_NOP:
+ return ERR_INTERNAL_ERROR;
+ }
+
+ return ERR_INTERNAL_ERROR; /* just to avoid compiler's warning. */
+}
+
+/*************************************************************************/
+
+
C_MODE_START
static my_bool
@@ -232,9 +613,43 @@
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:
+ case OPT_LIST_USERS:
+ 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;
+ case OPT_LIST_USERS:
+ Options::pm_cmd= PMC_LIST_USERS;
+ break;
+ }
+
+ break;
case '?':
usage();
exit(0);
@@ -289,6 +704,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 ERR_INVALID_USAGE;
+ }
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-04-04 16:31:10 +04:00
@@ -26,6 +26,17 @@
#pragma interface
#endif
+enum PasswordMgmtCmd
+{
+ PMC_NOP,
+ PMC_ADD_USER,
+ PMC_DROP_USER,
+ PMC_EDIT_USER,
+ PMC_CLEAN_PASSWORD_FILE,
+ PMC_CHECK_PASSWORD_FILE,
+ PMC_LIST_USERS
+};
+
struct Options
{
#ifdef __WIN__
@@ -48,6 +59,15 @@
static const char *bind_address;
static const char *config_file;
+ /* Variables for storing user name and password for managing passwords. */
+
+ static const char *pf_user_name;
+ static const char *pf_password;
+
+ static bool mysqld_safe_compatible;
+
+ static PasswordMgmtCmd pm_cmd;
+
/* argv pointer returned by load_defaults() to be used by free_defaults() */
static char **saved_argv;
@@ -55,6 +75,13 @@
void cleanup();
#ifdef __WIN__
int setup_windows_defaults();
+#endif
+
+#ifdef __GNUC__
+ /* This is just to avoid compiler warning. */
+public:
+ Options()
+ {}
#endif
};
--- 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-04-04 16:31:10 +04:00
@@ -17,7 +17,9 @@
#include "commands.h"
#include "instance_map.h"
+#include "log.h"
#include "messages.h"
+#include "manager.h"
#include "mysqld_error.h"
#include "mysql_manager_error.h"
#include "protocol.h"
@@ -29,6 +31,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
@@ -88,358 +97,575 @@
}
-/* implementation for Show_instances: */
+/**************************************************************************
+ Implementation of Show_instances.
+**************************************************************************/
+int Show_instances::execute(struct st_net *net, ulong connection_id)
+{
+ int err_code;
-/*
- The method sends a list of instances in the instance map to the client.
+ if ((err_code= write_header(net)) ||
+ (err_code= write_data(net)))
+ return err_code;
- SYNOPSYS
- Show_instances::execute()
- net The network connection to the client.
- connection_id Client connection ID
+ if (send_eof(net) || net_flush(net))
+ return ER_OUT_OF_RESOURCES;
- RETURN
- 0 - ok
- 1 - error occured
-*/
+ return 0;
+}
-int Show_instances::execute(struct st_net *net, ulong connection_id)
+
+int Show_instances::write_header(struct st_net *net)
{
- Buffer send_buff; /* buffer for packets */
- LIST name, status;
- NAME_WITH_LENGTH name_field, status_field;
+ LIST name, state;
+ NAME_WITH_LENGTH name_field, state_field;
LIST *field_list;
- uint position=0;
name_field.name= (char*) "instance_name";
name_field.length= DEFAULT_FIELD_LENGTH;
name.data= &name_field;
- status_field.name= (char*) "status";
- status_field.length= DEFAULT_FIELD_LENGTH;
- status.data= &status_field;
- field_list= list_add(NULL, &status);
+
+ state_field.name= (char*) "state";
+ state_field.length= DEFAULT_FIELD_LENGTH;
+ state.data= &state_field;
+
+ field_list= list_add(NULL, &state);
field_list= list_add(field_list, &name);
- send_fields(net, field_list);
+ return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
+}
+
+int Show_instances::write_data(struct st_net *net)
+{
+ my_bool err_status= FALSE;
+
+ Instance *instance;
+ Instance_map::Iterator iterator(instance_map);
+
+ instance_map->guardian->lock();
+ instance_map->lock();
+
+ while ((instance= iterator.next()))
{
- Instance *instance;
- Instance_map::Iterator iterator(instance_map);
+ Buffer send_buf; /* buffer for packets */
+ uint position= 0;
- instance_map->lock();
- while ((instance= iterator.next()))
+ const char *instance_name= instance->options.instance_name;
+ const char *state_name= instance_map->get_instance_state_name(instance);
+
+ if (store_to_protocol_packet(&send_buf, instance_name, &position) ||
+ store_to_protocol_packet(&send_buf, state_name, &position) ||
+ my_net_write(net, send_buf.buffer, position))
{
- position= 0;
- store_to_protocol_packet(&send_buff, instance->options.instance_name,
- &position);
- if (instance->is_running())
- store_to_protocol_packet(&send_buff, (char*) "online", &position);
- else
- store_to_protocol_packet(&send_buff, (char*) "offline", &position);
- if (my_net_write(net, send_buff.buffer, (uint) position))
- goto err;
+ err_status= TRUE;
+ break;
}
- instance_map->unlock();
}
- if (send_eof(net))
- goto err;
- if (net_flush(net))
- goto err;
- return 0;
-err:
- return ER_OUT_OF_RESOURCES;
+ instance_map->unlock();
+ instance_map->guardian->unlock();
+
+ return err_status ? ER_OUT_OF_RESOURCES : 0;
}
-/* implementation for Flush_instances: */
+/**************************************************************************
+ Implementation of Flush_instances.
+**************************************************************************/
int Flush_instances::execute(struct st_net *net, ulong connection_id)
{
- if (instance_map->flush_instances() ||
- net_send_ok(net, connection_id, NULL))
+ instance_map->guardian->lock();
+ instance_map->lock();
+
+ if (instance_map->is_there_active_instance())
+ {
+ instance_map->unlock();
+ instance_map->guardian->unlock();
+ return ER_THERE_IS_ACTIVE_INSTACE;
+ }
+
+ if (instance_map->flush_instances())
+ {
+ instance_map->unlock();
+ instance_map->guardian->unlock();
return ER_OUT_OF_RESOURCES;
+ }
- return 0;
+ instance_map->unlock();
+ instance_map->guardian->unlock();
+
+ return net_send_ok(net, connection_id, NULL) ? ER_OUT_OF_RESOURCES : 0;
}
-/* implementation for Show_instance_status: */
+/**************************************************************************
+ Implementation of AbstractInstanceCmd.
+**************************************************************************/
-Show_instance_status::Show_instance_status(Instance_map *instance_map_arg,
- const char *name, uint len)
+AbstractInstanceCmd::AbstractInstanceCmd(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg)
:Command(instance_map_arg)
{
+ /*
+ MT-NOTE: we can not make a search for Instance object here,
+ because it can dissappear after releasing the lock.
+ */
+
+ if (instance_name_len_arg > MAX_INSTANCE_NAME_SIZE - 1)
+ instance_name_len_arg= MAX_INSTANCE_NAME_SIZE - 1;
+
+ strmake(instance_name, instance_name_arg, instance_name_len_arg);
+ instance_name_len= instance_name_len_arg;
+}
+
+int AbstractInstanceCmd::execute(struct st_net *net, ulong connection_id)
+{
+ int err_code;
Instance *instance;
- /* we make a search here, since we don't want to store the name */
- if ((instance= instance_map->find(name, len)))
- instance_name= instance->options.instance_name;
- else
- instance_name= NULL;
+ instance_map->lock();
+
+ instance= instance_map->find(instance_name, instance_name_len);
+
+ if (!instance)
+ {
+ instance_map->unlock();
+ return ER_BAD_INSTANCE_NAME;
+ }
+
+ err_code= exec_impl(net, connection_id, instance);
+
+ instance_map->unlock();
+
+ return err_code;
}
-/*
- The method sends a table with a status of requested instance to the client.
+/**************************************************************************
+ Implementation of Show_instance_status.
+**************************************************************************/
- SYNOPSYS
- Show_instance_status::do_command()
- net The network connection to the client.
- instance_name The name of the instance.
+Show_instance_status::Show_instance_status(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg)
+ :AbstractInstanceCmd(instance_map_arg, instance_name_arg,
+ instance_name_len_arg)
+{
+}
- RETURN
- 0 - ok
- 1 - error occured
-*/
+
+int Show_instance_status::exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance)
+{
+ int err_code;
+
+ if ((err_code= write_header(net)) ||
+ (err_code= write_data(net, instance)))
+ return err_code;
+
+ if (send_eof(net) || net_flush(net))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
-int Show_instance_status::execute(struct st_net *net,
- ulong connection_id)
+int Show_instance_status::write_header(struct st_net *net)
{
- enum { MAX_VERSION_LENGTH= 40 };
- Buffer send_buff; /* buffer for packets */
- LIST name, status, version, version_number;
+ LIST name, state, version, version_number, deprecated;
LIST *field_list;
- NAME_WITH_LENGTH name_field, status_field, version_field,
- version_number_field;
- uint position=0;
+ NAME_WITH_LENGTH name_field, state_field, version_field,
+ version_number_field, deprecated_field;
- if (!instance_name)
- return ER_BAD_INSTANCE_NAME;
-
- /* create list of the fileds to be passed to send_fields */
+ /* Create list of the fileds to be passed to send_fields(). */
+
name_field.name= (char*) "instance_name";
name_field.length= DEFAULT_FIELD_LENGTH;
name.data= &name_field;
- status_field.name= (char*) "status";
- status_field.length= DEFAULT_FIELD_LENGTH;
- status.data= &status_field;
+
+ state_field.name= (char*) "state";
+ state_field.length= DEFAULT_FIELD_LENGTH;
+ state.data= &state_field;
+
version_field.name= (char*) "version";
version_field.length= MAX_VERSION_LENGTH;
version.data= &version_field;
+
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);
+
+ deprecated_field.name= (char*) "deprecated?";
+ deprecated_field.length= DEFAULT_FIELD_LENGTH;
+ deprecated.data= &deprecated_field;
+
+ field_list= list_add(NULL, &deprecated);
+ 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, &state);
field_list= list_add(field_list, &name);
- send_fields(net, field_list);
-
- {
- Instance *instance;
+ return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
+}
- store_to_protocol_packet(&send_buff, (char*) instance_name, &position);
- if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
- goto err;
- if (instance->is_running())
- store_to_protocol_packet(&send_buff, (char*) "online", &position);
- else
- store_to_protocol_packet(&send_buff, (char*) "offline", &position);
- if (instance->options.mysqld_version)
- {
- char parsed_version[MAX_VERSION_LENGTH];
+int Show_instance_status::write_data(struct st_net *net, Instance *instance)
+{
+ Buffer send_buf; /* buffer for packets */
+ char version_num_buf[MAX_VERSION_LENGTH];
+ uint position=0;
- parse_version_number(instance->options.mysqld_version, parsed_version,
- sizeof(parsed_version));
- store_to_protocol_packet(&send_buff, parsed_version, &position);
+ const char *state_name;
+ const char *version_tag= "unknown";
+ const char *version_num= "unknown";
+ const char *deprecated_status;
+
+ instance_map->guardian->lock();
+ state_name= instance_map->get_instance_state_name(instance);
+ deprecated_status= instance->is_deprecated() ? "deprecated" : "good";
+ instance_map->guardian->unlock();
- store_to_protocol_packet(&send_buff, instance->options.mysqld_version,
- &position);
- }
- else
- {
- store_to_protocol_packet(&send_buff, (char*) "unknown", &position);
- store_to_protocol_packet(&send_buff, (char*) "unknown", &position);
- }
+ if (instance->options.mysqld_version)
+ {
+ if (parse_version_number(instance->options.mysqld_version, version_num_buf,
+ sizeof(version_num_buf)))
+ return ER_OUT_OF_RESOURCES;
- if (send_buff.is_error() ||
- my_net_write(net, send_buff.buffer, (uint) position))
- goto err;
+ version_num= version_num_buf;
+ version_tag= instance->options.mysqld_version;
}
- if (send_eof(net) || net_flush(net))
- goto err;
+ if (store_to_protocol_packet(&send_buf, instance_name, &position) ||
+ store_to_protocol_packet(&send_buf, state_name, &position) ||
+ store_to_protocol_packet(&send_buf, version_num, &position) ||
+ store_to_protocol_packet(&send_buf, version_tag, &position) ||
+ store_to_protocol_packet(&send_buf, deprecated_status, &position) ||
+ my_net_write(net, send_buf.buffer, (uint) position))
+ {
+ return ER_OUT_OF_RESOURCES;
+ }
return 0;
-
-err:
- return ER_OUT_OF_RESOURCES;
}
-/* Implementation for Show_instance_options */
+/**************************************************************************
+ Implementation of Show_instance_options.
+**************************************************************************/
Show_instance_options::Show_instance_options(Instance_map *instance_map_arg,
- const char *name, uint len):
- Command(instance_map_arg)
+ const char *instance_name_arg,
+ uint instance_name_len_arg)
+ :AbstractInstanceCmd(instance_map_arg, instance_name_arg,
+ instance_name_len_arg)
{
- Instance *instance;
+}
- /* we make a search here, since we don't want to store the name */
- if ((instance= instance_map->find(name, len)))
- instance_name= instance->options.instance_name;
- else
- instance_name= NULL;
+
+int Show_instance_options::exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance)
+{
+ int err_code;
+
+ if ((err_code= write_header(net)) ||
+ (err_code= write_data(net, instance)))
+ return err_code;
+
+ if (send_eof(net) || net_flush(net))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
}
-int Show_instance_options::execute(struct st_net *net, ulong connection_id)
+int Show_instance_options::write_header(struct st_net *net)
{
- Buffer send_buff; /* buffer for packets */
LIST name, option;
LIST *field_list;
NAME_WITH_LENGTH name_field, option_field;
- uint position=0;
-
- if (!instance_name)
- return ER_BAD_INSTANCE_NAME;
- /* create list of the fileds to be passed to send_fields */
+ /* Create list of the fileds to be passed to send_fields(). */
+
name_field.name= (char*) "option_name";
name_field.length= DEFAULT_FIELD_LENGTH;
name.data= &name_field;
+
option_field.name= (char*) "value";
option_field.length= DEFAULT_FIELD_LENGTH;
option.data= &option_field;
+
field_list= list_add(NULL, &option);
field_list= list_add(field_list, &name);
- send_fields(net, field_list);
+ return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
+}
+
+int Show_instance_options::write_data(struct st_net *net, Instance *instance)
+{
+ Buffer send_buff; /* buffer for packets */
+ uint position= 0;
+
+ if (store_to_protocol_packet(&send_buff, "instance_name", &position) ||
+ store_to_protocol_packet(&send_buff, instance_name, &position) ||
+ my_net_write(net, send_buff.buffer, position))
{
- Instance *instance;
+ return ER_OUT_OF_RESOURCES;
+ }
- if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
- goto err;
- store_to_protocol_packet(&send_buff, (char*) "instance_name", &position);
- 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;
- }
+ /* Loop through the options stored in DYNAMIC_ARRAY. */
- 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;
- }
+ for (int i= 0; i < instance->options.get_num_options(); i++)
+ {
+ Option option= instance->options.get_option(i);
+ const char *option_value= option.get_value()[0] ? option.get_value() : "";
+
+ position= 0;
- /* loop through the options stored in DYNAMIC_ARRAY */
- for (uint i= 0; i < instance->options.options_array.elements; i++)
+ if (store_to_protocol_packet(&send_buff, option.get_name(), &position) ||
+ store_to_protocol_packet(&send_buff, option_value, &position) ||
+ my_net_write(net, send_buff.buffer, position))
{
- 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 */
-
- 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);
- }
-
- if (send_buff.is_error() ||
- my_net_write(net, send_buff.buffer, (uint) position))
- goto err;
+ return ER_OUT_OF_RESOURCES;
}
}
- if (send_eof(net) || net_flush(net))
- goto err;
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation of Start_instance.
+**************************************************************************/
+
+Start_instance::Start_instance(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg)
+ :AbstractInstanceCmd(instance_map_arg, instance_name_arg,
+ instance_name_len_arg)
+{
+}
+
+
+int Start_instance::exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance)
+{
+ int err_code;
+
+ if ((err_code= instance->start()))
+ return err_code;
+
+ if (!(instance->options.nonguarded))
+ instance_map->guardian->guard(instance);
+
+ if (net_send_ok(net, connection_id, "Instance started"))
+ return ER_OUT_OF_RESOURCES;
return 0;
+}
+
-err:
- return ER_OUT_OF_RESOURCES;
+/**************************************************************************
+ Implementation of Stop_instance.
+**************************************************************************/
+
+Stop_instance::Stop_instance(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg)
+ :AbstractInstanceCmd(instance_map_arg, instance_name_arg,
+ instance_name_len_arg)
+{
}
-/* Implementation for Start_instance */
+int Stop_instance::exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance)
+{
+ uint err_code;
-Start_instance::Start_instance(Instance_map *instance_map_arg,
- const char *name, uint len)
+ if (!(instance->options.nonguarded))
+ instance_map->guardian->stop_guard(instance);
+
+ if ((err_code= instance->stop()))
+ return err_code;
+
+ if (net_send_ok(net, connection_id, NULL))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation for Create_instance.
+**************************************************************************/
+
+Create_instance *Create_instance::create(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg)
+{
+ Create_instance *cmd= new Create_instance(instance_map_arg,
+ instance_name_arg,
+ instance_name_len_arg);
+
+ if (my_init_dynamic_array(&cmd->options, sizeof(Option), 0, 32))
+ {
+ delete cmd;
+ return NULL;
+ }
+
+ return cmd;
+}
+
+
+Create_instance::Create_instance(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg)
:Command(instance_map_arg)
{
- /* we make a search here, since we don't want to store the name */
- if ((instance= instance_map->find(name, len)))
- instance_name= instance->options.instance_name;
+ if (instance_name_len_arg > MAX_INSTANCE_NAME_SIZE - 1)
+ instance_name_len_arg= MAX_INSTANCE_NAME_SIZE - 1;
+
+ strmake(instance_name, instance_name_arg, instance_name_len_arg);
+ instance_name_len= instance_name_len_arg;
}
-int Start_instance::execute(struct st_net *net, ulong connection_id)
+Create_instance::~Create_instance()
{
- uint err_code;
- if (instance == 0)
- return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
- else
+ delete_dynamic(&options);
+}
+
+
+int Create_instance::execute(struct st_net *net, ulong connection_id)
+{
+ int err_code;
+
+ /* 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(instance_name, instance_name_len))
{
- if ((err_code= instance->start()))
- return err_code;
+ instance_map->unlock();
+ return ER_CREATE_EXISTING_INSTANCE;
+ }
- if (!(instance->options.nonguarded))
- instance_map->guardian->guard(instance);
+ if ((err_code= create_instance_in_config_file(instance_name,
+ instance_name_len,
+ &options)))
+ {
+ instance_map->unlock();
+ return err_code;
+ }
- net_send_ok(net, connection_id, "Instance started");
- return 0;
+ if ((err_code= instance_map->create_instance(instance_name,
+ instance_name_len,
+ &options,
+ USUAL_INSTANCE)))
+ {
+ instance_map->unlock();
+ return err_code;
}
+
+ /* That's all. */
+
+ instance_map->unlock();
+
+ /* Send the result. */
+
+ if (net_send_ok(net, connection_id, NULL))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation for Drop_instance.
+**************************************************************************/
+
+Drop_instance::Drop_instance(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg)
+ :AbstractInstanceCmd(instance_map_arg, instance_name_arg,
+ instance_name_len_arg)
+{
}
-/* implementation for Show_instance_log: */
+int Drop_instance::exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance)
+{
+ int err_code;
+
+ /* Check that the instance is offline. */
+
+ if (instance_map->is_active(instance))
+ return ER_DROP_ACTIVE_INSTANCE;
+
+ 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)
+ 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);
+
+ if (net_send_ok(net, connection_id, "Instance dropped"))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+/**************************************************************************
+ Implementation for Show_instance_log.
+**************************************************************************/
Show_instance_log::Show_instance_log(Instance_map *instance_map_arg,
- const char *name, uint len,
+ const char *instance_name_arg,
+ uint instance_name_len_arg,
Log_type log_type_arg,
const char *size_arg,
const char *offset_arg)
- :Command(instance_map_arg)
+ :AbstractInstanceCmd(instance_map_arg, instance_name_arg,
+ instance_name_len_arg)
{
- Instance *instance;
+ offset= offset_arg != NULL ? atoi(offset_arg) : 0;
+ // XXX: is it desired behaviour? should not we complain about malformed
+ // offset parameter?
- if (offset_arg != NULL)
- offset= atoi(offset_arg);
- else
- offset= 0;
size= atoi(size_arg);
- log_type= log_type_arg;
+ // XXX: is it desired behaviour? should not we complain about malformed
+ // size parameter?
- /* we make a search here, since we don't want to store the name */
- if ((instance= instance_map->find(name, len)))
- instance_name= instance->options.instance_name;
- else
- instance_name= NULL;
+ log_type= log_type_arg;
}
-
/*
Open the logfile, read requested part of the log and send the info
to the client.
@@ -466,104 +692,127 @@
ER_OUT_OF_RESOURCES We weren't able to allocate some resources
*/
-int Show_instance_log::execute(struct st_net *net, ulong connection_id)
+int Show_instance_log::exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance)
+{
+ int err_code;
+
+ if ((err_code= check_params(instance)))
+ return err_code;
+
+ if ((err_code= write_header(net)) ||
+ (err_code= write_data(net, instance)))
+ return err_code;
+
+ if (send_eof(net) || net_flush(net))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+int Show_instance_log::check_params(Instance *instance)
+{
+ const char *logpath= instance->options.logs[log_type];
+
+ /* Cannot read negative number of bytes. */
+
+ if (offset > size)
+ return ER_OFFSET_ERROR;
+
+ /* Instance has no such log. */
+
+ if (logpath == NULL)
+ return ER_NO_SUCH_LOG;
+
+ if (*logpath == '\0')
+ return ER_GUESS_LOGFILE;
+
+ return 0;
+}
+
+
+int Show_instance_log::write_header(struct st_net *net)
{
- Buffer send_buff; /* buffer for packets */
LIST name;
LIST *field_list;
NAME_WITH_LENGTH name_field;
- uint position= 0;
- /* create list of the fileds to be passed to send_fields */
+ /* Create list of the fields to be passed to send_fields(). */
+
name_field.name= (char*) "Log";
name_field.length= DEFAULT_FIELD_LENGTH;
+
name.data= &name_field;
+
field_list= list_add(NULL, &name);
- if (!instance_name)
- return ER_BAD_INSTANCE_NAME;
+ return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
+}
- /* cannot read negative number of bytes */
- if (offset > size)
- return ER_OFFSET_ERROR;
- send_fields(net, field_list);
+int Show_instance_log::write_data(struct st_net *net, Instance *instance)
+{
+ Buffer send_buff; /* buffer for packets */
+ uint pos= 0;
- {
- Instance *instance;
- const char *logpath;
- File fd;
+ const char *logpath= instance->options.logs[log_type];
+ File fd;
- if ((instance= instance_map->find(instance_name,
- strlen(instance_name))) == NULL)
- goto err;
+ size_t buff_size;
+ int read_len;
- logpath= instance->options.logs[log_type];
+ MY_STAT file_stat;
+ Buffer read_buff;
- /* Instance has no such log */
- if (logpath == NULL)
- return ER_NO_SUCH_LOG;
+ if ((fd= my_open(logpath, O_RDONLY | O_BINARY, MYF(MY_WME))) <= 0)
+ return ER_OPEN_LOGFILE;
- if (*logpath == '\0')
- return ER_GUESS_LOGFILE;
+ /* my_fstat doesn't use the flag parameter */
+ if (my_fstat(fd, &file_stat, MYF(0)))
+ {
+ close(fd);
+ return ER_OUT_OF_RESOURCES;
+ }
+ /* calculate buffer size */
+ buff_size= (size - offset);
- if ((fd= my_open(logpath, O_RDONLY | O_BINARY, MYF(MY_WME))) >= 0)
- {
- size_t buff_size;
- int read_len;
- /* calculate buffer size */
- MY_STAT file_stat;
- Buffer read_buff;
-
- /* my_fstat doesn't use the flag parameter */
- if (my_fstat(fd, &file_stat, MYF(0)))
- goto err;
-
- buff_size= (size - offset);
-
- read_buff.reserve(0, buff_size);
-
- /* read in one chunk */
- read_len= (int)my_seek(fd, file_stat.st_size - size, MY_SEEK_SET, MYF(0));
-
- if ((read_len= my_read(fd, (byte*) read_buff.buffer,
- buff_size, MYF(0))) < 0)
- return ER_READ_FILE;
- store_to_protocol_packet(&send_buff, read_buff.buffer,
- &position, read_len);
- close(fd);
- }
- else
- return ER_OPEN_LOGFILE;
+ read_buff.reserve(0, buff_size);
- if (my_net_write(net, send_buff.buffer, (uint) position))
- goto err;
+ /* read in one chunk */
+ read_len= (int)my_seek(fd, file_stat.st_size - size, MY_SEEK_SET, MYF(0));
+
+ if ((read_len= my_read(fd, (byte*) read_buff.buffer,
+ buff_size, MYF(0))) < 0)
+ {
+ close(fd);
+ return ER_READ_FILE;
}
- if (send_eof(net) || net_flush(net))
- goto err;
+ close(fd);
- return 0;
+ if (store_to_protocol_packet(&send_buff, read_buff.buffer, &pos, read_len) ||
+ my_net_write(net, send_buff.buffer, pos))
+ {
+ return ER_OUT_OF_RESOURCES;
+ }
-err:
- return ER_OUT_OF_RESOURCES;
+ return 0;
}
-/* implementation for Show_instance_log_files: */
+/**************************************************************************
+ Implementation of Show_instance_log_files.
+**************************************************************************/
Show_instance_log_files::Show_instance_log_files
- (Instance_map *instance_map_arg, const char *name, uint len)
- :Command(instance_map_arg)
+ (Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg)
+ :AbstractInstanceCmd(instance_map_arg, instance_name_arg,
+ instance_name_len_arg)
{
- Instance *instance;
-
- /* we make a search here, since we don't want to store the name */
- if ((instance= instance_map->find(name, len)))
- instance_name= instance->options.instance_name;
- else
- instance_name= NULL;
}
@@ -582,153 +831,144 @@
0 - ok
*/
-int Show_instance_log_files::execute(struct st_net *net, ulong connection_id)
+int Show_instance_log_files::exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance)
+{
+ int err_code;
+
+ if ((err_code= write_header(net)) ||
+ (err_code= write_data(net, instance)))
+ return err_code;
+
+ if (send_eof(net) || net_flush(net))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
+}
+
+
+int Show_instance_log_files::write_header(struct st_net *net)
{
- Buffer send_buff; /* buffer for packets */
LIST name, path, size;
LIST *field_list;
NAME_WITH_LENGTH name_field, path_field, size_field;
- uint position= 0;
- if (!instance_name)
- return ER_BAD_INSTANCE_NAME;
+ /* Create list of the fileds to be passed to send_fields(). */
- /* create list of the fileds to be passed to send_fields */
name_field.name= (char*) "Logfile";
name_field.length= DEFAULT_FIELD_LENGTH;
name.data= &name_field;
+
path_field.name= (char*) "Path";
path_field.length= DEFAULT_FIELD_LENGTH;
path.data= &path_field;
+
size_field.name= (char*) "File size";
size_field.length= DEFAULT_FIELD_LENGTH;
size.data= &size_field;
+
field_list= list_add(NULL, &size);
field_list= list_add(field_list, &path);
field_list= list_add(field_list, &name);
- send_fields(net, field_list);
+ return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
+}
- Instance *instance;
- if ((instance= instance_map->
- find(instance_name, strlen(instance_name))) == NULL)
- goto err;
+int Show_instance_log_files::write_data(struct st_net *net, Instance *instance)
+{
+ Buffer send_buff; /* buffer for packets */
+
+ /*
+ We have alike structure in instance_options.cc. We use such to be able
+ to loop through the options, which we need to handle in some common way.
+ */
+ struct log_files_st
+ {
+ const char *name;
+ const char *value;
+ } logs[]=
+ {
+ {"ERROR LOG", instance->options.logs[IM_LOG_ERROR]},
+ {"GENERAL LOG", instance->options.logs[IM_LOG_GENERAL]},
+ {"SLOW LOG", instance->options.logs[IM_LOG_SLOW]},
+ {NULL, NULL}
+ };
+ struct log_files_st *log_files;
+ for (log_files= logs; log_files->name; log_files++)
{
+ if (!log_files->value)
+ continue;
+
+ struct stat file_stat;
/*
- We have alike structure in instance_options.cc. We use such to be able
- to loop through the options, which we need to handle in some common way.
+ Save some more space for the log file names. In fact all
+ we need is strlen("GENERAL_LOG") + 1
*/
- struct log_files_st
- {
- const char *name;
- const char *value;
- } logs[]=
- {
- {"ERROR LOG", instance->options.logs[IM_LOG_ERROR]},
- {"GENERAL LOG", instance->options.logs[IM_LOG_GENERAL]},
- {"SLOW LOG", instance->options.logs[IM_LOG_SLOW]},
- {NULL, NULL}
- };
- struct log_files_st *log_files;
+ enum { LOG_NAME_BUFFER_SIZE= 20 };
+ char buff[LOG_NAME_BUFFER_SIZE];
+
+ uint position= 0;
+
+ const char *log_path= "";
+ const char *log_size= "0";
- for (log_files= logs; log_files->name; log_files++)
+ if (!stat(log_files->value, &file_stat) &&
+ MY_S_ISREG(file_stat.st_mode))
{
- if (log_files->value != NULL)
- {
- struct stat file_stat;
- /*
- Save some more space for the log file names. In fact all
- we need is srtlen("GENERAL_LOG") + 1
- */
- enum { LOG_NAME_BUFFER_SIZE= 20 };
- char buff[LOG_NAME_BUFFER_SIZE];
-
- position= 0;
- /* store the type of the log in the send buffer */
- store_to_protocol_packet(&send_buff, log_files->name, &position);
- if (stat(log_files->value, &file_stat))
- {
- store_to_protocol_packet(&send_buff, "", &position);
- store_to_protocol_packet(&send_buff, (char*) "0", &position);
- }
- else if (MY_S_ISREG(file_stat.st_mode))
- {
- store_to_protocol_packet(&send_buff,
- (char*) log_files->value,
- &position);
- int10_to_str(file_stat.st_size, buff, 10);
- store_to_protocol_packet(&send_buff, (char*) buff, &position);
- }
-
- if (my_net_write(net, send_buff.buffer, (uint) position))
- goto err;
- }
+ int10_to_str(file_stat.st_size, buff, 10);
+
+ log_path= log_files->value;
+ log_size= buff;
}
- }
- if (send_eof(net) || net_flush(net))
- goto err;
+ if (store_to_protocol_packet(&send_buff, log_files->name, &position) ||
+ store_to_protocol_packet(&send_buff, log_path, &position) ||
+ store_to_protocol_packet(&send_buff, log_size, &position) ||
+ my_net_write(net, send_buff.buffer, position))
+ return ER_OUT_OF_RESOURCES;
+ }
return 0;
-
-err:
- return ER_OUT_OF_RESOURCES;
}
-/* implementation for SET instance_name.option=option_value: */
+/**************************************************************************
+ Implementation of Set_option.
+**************************************************************************/
Set_option::Set_option(Instance_map *instance_map_arg,
- const char *name, uint len,
- const char *option_arg, uint option_len_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg,
+ const char *option_name_arg, uint option_name_len_arg,
const char *option_value_arg, uint option_value_len_arg)
- :Command(instance_map_arg)
+ :AbstractInstanceCmd(instance_map_arg, instance_name_arg,
+ instance_name_len_arg)
{
- Instance *instance;
-
- /* we make a search here, since we don't want to store the name */
- if ((instance= instance_map->find(name, len)))
+ if (option_name_len_arg <= MAX_OPTION_LEN - 1 ||
+ option_value_len_arg <= MAX_OPTION_LEN - 1)
{
- instance_name= instance->options.instance_name;
-
- /* add prefix for add_option */
- if ((option_len_arg < MAX_OPTION_LEN - 1) ||
- (option_value_len_arg < MAX_OPTION_LEN - 1))
- {
- strmake(option, option_arg, option_len_arg);
- strmake(option_value, option_value_arg, option_value_len_arg);
- }
- else
- {
- option[0]= 0;
- option_value[0]= 0;
- }
- instance_name_len= len;
+ strmake(option_name, option_name_arg, option_name_len_arg);
+ strmake(option_value, option_value_arg, option_value_len_arg);
}
else
{
- instance_name= NULL;
- instance_name_len= 0;
+ option_name[0]= 0;
+ option_value[0]= 0;
}
}
/*
- The method sends a table with a list of log files
- used by the instance.
+ Correct the option file. The "skip" option is used to remove the found
+ option.
SYNOPSYS
Set_option::correct_file()
skip Skip the option, being searched while writing the result file.
That is, to delete it.
- DESCRIPTION
-
- Correct the option file. The "skip" option is used to remove the found
- option.
-
RETURN
ER_OUT_OF_RESOURCES out of resources
ER_ACCESS_OPTION_FILE Cannot access the option file
@@ -737,98 +977,104 @@
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);
+ error= modify_defaults_file(Options::config_file, option_name, option_value,
+ instance_name, skip);
DBUG_ASSERT(error >= 0 && error <= 2);
- return mysys_to_im_error[error];
+ return modify_defaults_to_im_error[error];
}
/*
- The method sets an option in the the default config file (/etc/my.cnf).
+ The method sets an option in the config file.
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);
- return error;
+ if (error)
+ return error;
+
+ /* Update the internal cache. */
+
+ if (instance->options.set_option(option_name, option_value))
+ return ER_OUT_OF_RESOURCES;
+
+ return 0;
}
-int Set_option::execute(struct st_net *net, ulong connection_id)
+int Set_option::exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance)
{
- if (instance_name != NULL)
- {
- int val;
+ int err_code;
- val= do_command(net);
+ /* Check that the instance is offline. */
- if (val == 0)
- net_send_ok(net, connection_id, NULL);
+ if (instance_map->is_active(instance))
+ return ER_INSTANCE_IS_ACTIVE;
- return val;
+ /* Check that the option is valid. */
+
+ if (instance->is_deprecated() &&
+ Instance_options::is_option_im_specific(option_name))
+ {
+ log_error("Error: IM-option (%s) can not be used "
+ "in the configuration of deprecated instance (%s).",
+ (const char *) option_name,
+ (const char *) instance_name);
+ return ER_INCOMPATIBLE_OPTION;
}
- return ER_BAD_INSTANCE_NAME;
-}
+ /* Perform command-specific (SET/UNSET) actions. */
+ err_code= do_command(net, instance);
-/* the only function from Unset_option we need to Implement */
+ if (err_code == 0)
+ net_send_ok(net, connection_id, NULL);
-int Unset_option::do_command(struct st_net *net)
-{
- return correct_file(TRUE);
+ return err_code;
}
-/* Implementation for Stop_instance: */
+/**************************************************************************
+ Implementation of Unset_option.
+**************************************************************************/
-Stop_instance::Stop_instance(Instance_map *instance_map_arg,
- const char *name, uint len)
- :Command(instance_map_arg)
+int Unset_option::do_command(struct st_net *net, Instance *instance)
{
- /* we make a search here, since we don't want to store the name */
- if ((instance= instance_map->find(name, len)))
- instance_name= instance->options.instance_name;
-}
+ /* Update the configuration file. */
+ int err_code= correct_file(TRUE);
-int Stop_instance::execute(struct st_net *net, ulong connection_id)
-{
- uint err_code;
+ if (err_code)
+ return err_code;
- if (instance == 0)
- return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
+ /* Update the internal cache. */
- if (!(instance->options.nonguarded))
- instance_map->guardian->stop_guard(instance);
+ instance->options.unset_option(option_name);
- if ((err_code= instance->stop()))
- return err_code;
-
- net_send_ok(net, connection_id, NULL);
return 0;
}
+
+/**************************************************************************
+ Implementation of Syntax_error.
+**************************************************************************/
int Syntax_error::execute(struct st_net *net, ulong connection_id)
{
--- 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-04-04 16:31:10 +04:00
@@ -19,6 +19,7 @@
#include "command.h"
#include "instance.h"
#include "parse.h"
+#include "priv.h"
/*
Print all instances of this instance manager.
@@ -32,6 +33,10 @@
{}
int execute(struct st_net *net, ulong connection_id);
+
+private:
+ int write_header(struct st_net *net);
+ int write_data(struct st_net *net);
};
@@ -51,18 +56,49 @@
/*
+ Abstract class for Instance-specific commands.
+*/
+
+class AbstractInstanceCmd : public Command
+{
+public:
+ AbstractInstanceCmd(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg);
+
+public:
+ virtual int execute(struct st_net *net, ulong connection_id);
+
+protected:
+ /* MT-NOTE: this operation is called under acquired Instance_map's lock. */
+ virtual int exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance) = 0;
+
+protected:
+ uint instance_name_len;
+ char instance_name[MAX_INSTANCE_NAME_SIZE];
+};
+
+
+/*
Print status of an instance.
Grammar: SHOW ISTANCE STATUS <instance_name>
*/
-class Show_instance_status : public Command
+class Show_instance_status : public AbstractInstanceCmd
{
public:
-
Show_instance_status(Instance_map *instance_map_arg,
- const char *name, uint len);
- int execute(struct st_net *net, ulong connection_id);
- const char *instance_name;
+ const char *instance_name_arg,
+ uint instance_name_len_arg);
+
+protected:
+ virtual int exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance);
+
+private:
+ int write_header(struct st_net *net);
+ int write_data(struct st_net *net, Instance *instance);
};
@@ -71,15 +107,20 @@
Grammar: SHOW INSTANCE OPTIONS <instance_name>
*/
-class Show_instance_options : public Command
+class Show_instance_options : public AbstractInstanceCmd
{
public:
-
Show_instance_options(Instance_map *instance_map_arg,
- const char *name, uint len);
+ const char *instance_name_arg,
+ uint instance_name_len_arg);
- int execute(struct st_net *net, ulong connection_id);
- const char *instance_name;
+protected:
+ virtual int exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance);
+
+private:
+ int write_header(struct st_net *net);
+ int write_data(struct st_net *net, Instance *instance);
};
@@ -88,14 +129,16 @@
Grammar: START INSTANCE <instance_name>
*/
-class Start_instance : public Command
+class Start_instance : public AbstractInstanceCmd
{
public:
- Start_instance(Instance_map *instance_map_arg, const char *name, uint len);
+ Start_instance(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg);
- int execute(struct st_net *net, ulong connection_id);
- const char *instance_name;
- Instance *instance;
+protected:
+ virtual int exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance);
};
@@ -104,14 +147,68 @@
Grammar: STOP INSTANCE <instance_name>
*/
-class Stop_instance : public Command
+class Stop_instance : public AbstractInstanceCmd
{
public:
- Stop_instance(Instance_map *instance_map_arg, const char *name, uint len);
+ Stop_instance(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg);
- Instance *instance;
- int execute(struct st_net *net, ulong connection_id);
- const char *instance_name;
+protected:
+ virtual int exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance);
+};
+
+
+/*
+ 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 *instance_name_arg,
+ uint instance_name_len_arg);
+
+public:
+ virtual ~Create_instance();
+
+protected:
+ virtual int execute(struct st_net *net, ulong connection_id);
+
+private:
+ Create_instance(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg);
+
+public:
+ DYNAMIC_ARRAY options;
+
+private:
+ uint instance_name_len;
+ char instance_name[MAX_INSTANCE_NAME_SIZE];
+};
+
+
+/*
+ Drop an instance. Operation is permitted only if the instance is stopped.
+ On successful completion the instance section is removed from config-file
+ and the instance is removed from the instance map.
+ Grammar: DROP INSTANCE <instance_name>
+*/
+
+class Drop_instance : public AbstractInstanceCmd
+{
+public:
+ Drop_instance(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg);
+
+protected:
+ virtual int exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance);
};
@@ -121,16 +218,26 @@
SHOW <instance_name> log {ERROR | SLOW | GENERAL} size[, offset_from_end]
*/
-class Show_instance_log : public Command
+class Show_instance_log : public AbstractInstanceCmd
{
public:
-
- Show_instance_log(Instance_map *instance_map_arg, const char *name,
- uint len, Log_type log_type_arg, const char *size_arg,
+ Show_instance_log(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg,
+ Log_type log_type_arg, const char *size_arg,
const char *offset_arg);
- int execute(struct st_net *net, ulong connection_id);
+
+protected:
+ virtual int exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance);
+
+private:
+ int check_params(Instance *instance);
+ int write_header(struct st_net *net);
+ int write_data(struct st_net *net, Instance *instance);
+
+private:
Log_type log_type;
- const char *instance_name;
uint size;
uint offset;
};
@@ -141,55 +248,47 @@
Grammar: SHOW <instance_name> LOG FILES
*/
-class Show_instance_log_files : public Command
+class Show_instance_log_files : public AbstractInstanceCmd
{
public:
-
Show_instance_log_files(Instance_map *instance_map_arg,
- const char *name, uint len);
- int execute(struct st_net *net, ulong connection_id);
- const char *instance_name;
- const char *option;
-};
-
+ const char *instance_name_arg,
+ uint instance_name_len_arg);
-/*
- Syntax error command. This command is issued if parser reported a syntax
- error. We need it to distinguish the parse error and the situation when
- parser internal error occured. E.g. parsing failed because we hadn't had
- enought memory. In the latter case parse_command() should return an error.
-*/
+protected:
+ virtual int exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance);
-class Syntax_error : public Command
-{
-public:
- int execute(struct st_net *net, ulong connection_id);
+private:
+ int write_header(struct st_net *net);
+ int write_data(struct st_net *net, Instance *instance);
};
+
/*
Set an option for the instance.
Grammar: SET instance_name.option=option_value
*/
-class Set_option : public Command
+class Set_option : public AbstractInstanceCmd
{
public:
- Set_option(Instance_map *instance_map_arg, const char *name, uint len,
- const char *option_arg, uint option_len,
- const char *option_value_arg, uint option_value_len);
- /*
- the following function is virtual to let Unset_option to use
- */
- virtual int do_command(struct st_net *net);
- int execute(struct st_net *net, ulong connection_id);
+ Set_option(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg,
+ const char *option_name_arg, uint option_name_len_arg,
+ const char *option_value_arg, uint option_value_len_arg);
+
protected:
int correct_file(int skip);
+
+ virtual int do_command(struct st_net *net, Instance *instance);
+
+ virtual int exec_impl(struct st_net *net, ulong connection_id,
+ Instance *instance);
+
public:
- const char *instance_name;
- uint instance_name_len;
- /* buffer for the option */
- enum { MAX_OPTION_LEN= 1024 };
- char option[MAX_OPTION_LEN];
+ char option_name[MAX_OPTION_LEN];
char option_value[MAX_OPTION_LEN];
};
@@ -202,14 +301,41 @@
class Unset_option: public Set_option
{
public:
- Unset_option(Instance_map *instance_map_arg, const char *name, uint len,
- const char *option_arg, uint option_len,
- const char *option_value_arg, uint option_value_len):
- Set_option(instance_map_arg, name, len, option_arg, option_len,
- option_value_arg, option_value_len)
+ Unset_option(Instance_map *instance_map_arg,
+ const char *instance_name_arg,
+ uint instance_name_len_arg,
+ const char *option_name_arg, uint option_name_len_arg,
+ const char *option_value_arg, uint option_value_len_arg)
+ :Set_option(instance_map_arg,
+ instance_name_arg,
+ instance_name_len_arg,
+ option_name_arg, option_name_len_arg,
+ option_value_arg, option_value_len_arg)
{}
- int do_command(struct st_net *net);
+
+protected:
+ virtual int do_command(struct st_net *net, Instance *instance);
};
+
+/*
+ Syntax error command. This command is issued if parser reported a syntax
+ error. We need it to distinguish the parse error and the situation when
+ parser internal error occured. E.g. parsing failed because we hadn't had
+ enought memory. In the latter case parse_command() should return an error.
+*/
+
+class Syntax_error : public Command
+{
+public:
+ int execute(struct st_net *net, ulong connection_id);
+
+#ifdef __GNUC__
+ /* This is just to avoid compiler warning. */
+public:
+ Syntax_error() :Command(NULL)
+ {}
+#endif
+};
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H */
--- 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-04-04 16:31:10 +04:00
@@ -32,7 +32,6 @@
#include <signal.h>
-
pthread_handler_t guardian(void *arg)
{
Guardian_thread *guardian_thread= (Guardian_thread *) arg;
@@ -40,6 +39,37 @@
return 0;
}
+
+const char *
+Guardian_thread::get_instance_state_name(enum_instance_state state)
+{
+ switch (state) {
+ case NOT_STARTED:
+ return "offline";
+
+ case STARTING:
+ return "starting";
+
+ case STARTED:
+ return "online";
+
+ case JUST_CRASHED:
+ return "failed";
+
+ case CRASHED:
+ return "crashed";
+
+ case CRASHED_AND_ABANDONED:
+ return "abandoned";
+
+ case STOPPING:
+ return "stopping";
+ }
+
+ return NULL; /* just to ignore compiler warning. */
+}
+
+
Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg,
Instance_map *instance_map_arg,
uint monitoring_interval_arg) :
@@ -159,7 +189,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 +235,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);
@@ -244,7 +276,9 @@
SYNOPSYS
Guardian_thread::init()
- NOTE: One should always lock guardian before calling this routine.
+ NOTE: The operation should be invoked with the following locks acquired:
+ - Guardian_thread;
+ - Instance_map;
RETURN
0 - ok
@@ -263,12 +297,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 +369,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 +452,24 @@
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;
}
--- 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-04-04 16:31:10 +04:00
@@ -79,6 +79,8 @@
time_t last_checked;
};
+ /* Return client state name. */
+ static const char *get_instance_state_name(enum_instance_state state);
Guardian_thread(Thread_registry &thread_registry_arg,
Instance_map *instance_map_arg,
@@ -99,6 +101,20 @@
void lock();
void unlock();
+ /*
+ Return an internal list node for the given instance if the instance is
+ managed by Guardian. Otherwise, return NULL.
+
+ MT-NOTE: must be called under acquired lock.
+ */
+ LIST *find_instance_node(Instance *instance);
+
+ /*
+ Return state of the given instance list node. The pointer must specify
+ a valid list node.
+ */
+ inline enum_instance_state get_instance_state(LIST *instance_node);
+
public:
pthread_cond_t COND_guardian;
@@ -108,6 +124,7 @@
/* check instance state and act accordingly */
void process_instance(Instance *instance, GUARD_NODE *current_node,
LIST **guarded_instances, LIST *elem);
+
int stopped;
private:
@@ -119,5 +136,12 @@
/* this variable is set to TRUE when we want to stop Guardian thread */
bool shutdown_requested;
};
+
+
+inline Guardian_thread::enum_instance_state
+Guardian_thread::get_instance_state(LIST *instance_node)
+{
+ return ((Guardian_thread::GUARD_NODE *) instance_node->data)->state;
+}
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_GUARDIAN_H */
--- 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-04-04 16:31:10 +04:00
@@ -34,6 +34,13 @@
#include <mysql.h>
+const char * const Instance::DFLT_INSTANCE_NAME= "mysqld";
+const uint Instance::DFLT_INSTANCE_NAME_LEN= 6;
+
+static const char * const INSTANCE_NAME_PREFIX= Instance::DFLT_INSTANCE_NAME;
+static const int INSTANCE_NAME_PREFIX_LEN= Instance::DFLT_INSTANCE_NAME_LEN;
+
+
static void start_and_monitor_instance(Instance_options *old_instance_options,
Instance_map *instance_map);
@@ -266,7 +273,9 @@
/* don't check for return value */
wait_process(&process_info);
+ instance_map->lock();
current_instance= instance_map->find(instance_name_buff, instance_name_len);
+ instance_map->unlock();
if (current_instance)
current_instance->set_crash_flag_n_wake_all();
@@ -275,6 +284,17 @@
}
+bool Instance::is_name_valid(const char *name)
+{
+ const char *name_suffix= name + INSTANCE_NAME_PREFIX_LEN;
+
+ if (strncmp(name, INSTANCE_NAME_PREFIX, INSTANCE_NAME_PREFIX_LEN) != 0)
+ return false;
+
+ return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix);
+}
+
+
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)
@@ -594,6 +614,8 @@
int Instance::init(const char *name_arg)
{
+ deprecated= strcmp(name_arg, INSTANCE_NAME_PREFIX) == 0;
+
return options.init(name_arg);
}
@@ -603,5 +625,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-04-04 16:31:10 +04:00
@@ -28,6 +28,21 @@
class Instance
{
public:
+ /*
+ The following two constants defines name of the default mysqld-instance
+ ("mysqld").
+ */
+ static const char * const DFLT_INSTANCE_NAME;
+ static const uint DFLT_INSTANCE_NAME_LEN;
+
+public:
+ /*
+ The operation is intended to check whether string is a well-formed
+ instance name or not.
+ */
+ static bool is_name_valid(const char *name);
+
+public:
Instance();
~Instance();
@@ -44,12 +59,18 @@
void set_crash_flag_n_wake_all();
Instance_map *get_map();
+ /* The operation is intended to check if the instance is deprecated or not. */
+ inline bool is_deprecated() const;
+
public:
enum { DEFAULT_SHUTDOWN_DELAY= 35 };
Instance_options options;
private:
int crashed;
+ bool configured;
+ bool deprecated;
+
/*
Mutex protecting the instance. Currently we use it to avoid the
double start of the instance. This happens when the instance is starting
@@ -65,5 +86,23 @@
void remove_pid();
};
+
+
+/*
+ The operation is intended to check if the instance is deprecated or not.
+
+ SYNOPSYS
+ is_deprecated()
+
+ RETURN
+ TRUE the instance is deprecated, i.e. only mysqld-specific options are
+ allowed in the configuration.
+ FALSE otherwise.
+*/
+
+inline bool Instance::is_deprecated() const
+{
+ return deprecated;
+}
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H */
--- 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-04-04 16:31:10 +04:00
@@ -24,6 +24,10 @@
#include "instance.h"
#include "log.h"
#include "options.h"
+#include "manager.h"
+
+#include "mysqld_error.h"
+#include "mysql_manager_error.h"
#include <m_ctype.h>
#include <mysql_com.h>
@@ -106,31 +110,34 @@
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->options.add_option(option))
- goto err; /* the instance'll be deleted when we destroy the map */
+ if (!(instance= (Instance *) hash_search(&hash, (byte *) group,
+ strlen(group))))
+ {
+ if (!(instance= new Instance()))
+ return 1;
+
+ if (instance->init(group) || add_instance(instance))
+ {
+ delete instance;
+ return 1;
}
- return 0;
+ if (instance->is_deprecated())
+ log_info("Warning: instance name '%s' is deprecated.",
+ (const char *) group);
-err_instance:
- delete instance;
-err:
- return 1;
+ log_info("mysqld instance '%s' has been added successfully.",
+ (const char *) group);
+ }
+
+ if (option && instance->options.add_option(option))
+ return 1; /* the instance'll be deleted when we destroy the map */
+
+ return 0;
}
@@ -194,9 +201,9 @@
In order to avoid such side effects one should never call
FLUSH INSTANCES without prior stop of all running instances.
- TODO
- FLUSH INSTANCES should return an error if it's called
- while there is a running instance.
+ NOTE: The operation should be invoked with the following locks acquired:
+ - Guardian_thread;
+ - Instance_map;
*/
int Instance_map::flush_instances()
@@ -209,67 +216,189 @@
guardian (2) reload the instance map (3) reinitialize the guardian
with new instances.
*/
- guardian->lock();
- pthread_mutex_lock(&LOCK_instance_map);
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);
- guardian->unlock();
return rc;
}
-Instance *
-Instance_map::find(const char *name, uint name_len)
+bool Instance_map::is_active(Instance *instance)
{
- Instance *instance;
- pthread_mutex_lock(&LOCK_instance_map);
- instance= (Instance *) hash_search(&hash, (byte *) name, name_len);
- pthread_mutex_unlock(&LOCK_instance_map);
- return instance;
+ bool active;
+
+ guardian->lock();
+
+ active= guardian->find_instance_node(instance) != NULL;
+
+ /* is_running() can take a long time, so let's unlock mutex first. */
+ guardian->unlock();
+
+ if (!active)
+ active= instance->is_running();
+
+ return active;
}
-int Instance_map::complete_initialization()
+bool Instance_map::is_there_active_instance()
{
Instance *instance;
- uint i= 0;
+ Iterator iterator(this);
+
+ while ((instance= iterator.next()))
+ {
+ if (guardian->find_instance_node(instance) != NULL ||
+ instance->is_running())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+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);
+}
+
+
+int Instance_map::create_instance(const char *instance_name,
+ uint instance_name_len,
+ DYNAMIC_ARRAY *options,
+ uint instance_type)
+{
+ Instance *instance= new Instance();
+
+ if (!instance || instance->init(instance_name))
+ {
+ log_error("Error: can not initialize (name: '%s').",
+ (const char *) instance_name);
+ delete instance;
+ return ER_OUT_OF_RESOURCES;
+ }
+
+ for (uint i= 0; i < options->elements; ++i)
+ {
+ Option option;
+ get_dynamic(options, (gptr) &option, i);
+ if (instance->is_deprecated() &&
+ Instance_options::is_option_im_specific(option.get_name()))
+ {
+ log_error("Error: IM-option (%s) can not be used "
+ "in configuration of deprecated instance (%s).",
+ (const char *) option.get_name(),
+ (const char *) instance_name);
+ delete instance;
+ return ER_INCOMPATIBLE_OPTION;
+ }
- if (hash.records == 0) /* no instances found */
+ instance->options.set_option(option.get_name(), option.get_value());
+ }
+
+ if (instance->is_deprecated())
+ log_info("Warning: instance name '%s' is deprecated.",
+ (const char *) instance_name);
+
+ if (instance->complete_initialization(this, mysqld_path, instance_type))
{
- if ((instance= new Instance) == 0)
- goto err;
+ log_error("Error: can not complete initialization of instance (name: '%s').",
+ (const char *) instance_name);
+ delete instance;
+ return ER_OUT_OF_RESOURCES; // XXX: is it correct error status in this case?
+ }
+
+ if (add_instance(instance))
+ {
+ log_error("Error: can not register instance (name: '%s').",
+ (const char *) instance_name);
+ delete instance;
+ return ER_OUT_OF_RESOURCES;
+ }
+
+ return 0;
+}
- if (instance->init("mysqld") || my_hash_insert(&hash, (byte *) instance))
- goto err_instance;
- /*
- After an instance have been added to the instance_map,
- hash_free should handle it's deletion => goto err, not
- err_instance.
- */
- if (instance->complete_initialization(this, mysqld_path,
- DEFAULT_SINGLE_INSTANCE))
- goto err;
+Instance *
+Instance_map::find(const char *name, uint name_len)
+{
+ return (Instance *) hash_search(&hash, (byte *) name, name_len);
+}
+
+
+int Instance_map::complete_initialization()
+{
+ for (uint i= 0; i < hash.records; ++i)
+ {
+ Instance *instance= (Instance *) hash_element(&hash, i);
+ if (instance->complete_initialization(this, mysqld_path, USUAL_INSTANCE))
+ return 1;
}
- else
- while (i < hash.records)
+
+ if (Options::mysqld_safe_compatible)
+ {
+ bool mysqld_found= false;
+
+ 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++;
+ Instance *instance= (Instance *) hash_element(&hash, i);
+
+ if (strcmp(instance->options.instance_name,
+ Instance::DFLT_INSTANCE_NAME) == 0)
+ {
+ mysqld_found= true;
+ break;
+ }
+ }
+
+ if (!mysqld_found)
+ {
+ DYNAMIC_ARRAY instance_options;
+
+ memset(&instance_options, 0, sizeof (DYNAMIC_ARRAY));
+
+ switch (create_instance_in_config_file(Instance::DFLT_INSTANCE_NAME,
+ Instance::DFLT_INSTANCE_NAME_LEN,
+ &instance_options))
+ {
+ case 0:
+ case ER_CONF_FILE_DOES_NOT_EXIST:
+ /*
+ Continue if the instance has been added to the config file
+ successfully, or the config file just does not exist.
+ */
+ break;
+
+ default:
+ log_error("Error: could not add default instance to the config file.");
+ return 1;
+ }
+
+ if (create_instance(Instance::DFLT_INSTANCE_NAME,
+ Instance::DFLT_INSTANCE_NAME_LEN,
+ &instance_options,
+ DEFAULT_SINGLE_INSTANCE))
+ {
+ log_error("Error: could not create default instance.");
+ return 1;
+ }
}
+ }
return 0;
-err_instance:
- delete instance;
-err:
- return 1;
}
@@ -319,10 +448,7 @@
process_option, (void*) this))
log_info("Falling back to compiled-in defaults");
- if (complete_initialization())
- return 1;
-
- return 0;
+ return complete_initialization();
}
@@ -343,3 +469,20 @@
return NULL;
}
+
+const char *Instance_map::get_instance_state_name(Instance *instance)
+{
+ LIST *instance_node= guardian->find_instance_node(instance);
+
+ if (instance_node != NULL)
+ {
+ /* The instance is managed by Guardian: we can report precise state. */
+
+ return Guardian_thread::get_instance_state_name(
+ guardian->get_instance_state(instance_node));
+ }
+
+ /* The instance is not managed by Guardian: we can report status only. */
+
+ return instance->is_running() ? "online" : "offline";
+}
--- 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-04-04 16:31:10 +04:00
@@ -56,21 +56,66 @@
};
friend class Iterator;
public:
- /* returns a pointer to the instance or NULL, if there is no such instance */
+ /*
+ Return a pointer to the instance or NULL, if there is no such instance.
+ MT-NOTE: must be called under acquired lock.
+ */
Instance *find(const char *name, uint name_len);
+ /* Clear the configuration cache and reload the configuration file. */
int flush_instances();
+
+ /* The operation is used to check if the instance is active or not. */
+ bool is_active(Instance *instance);
+
+ /* The operation is used to check if there is an active instance or not. */
+ bool is_there_active_instance();
+
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 an instance into the internal hash.
+
+ MT-NOTE: the operation must be called under acquired lock.
+ */
+ int add_instance(Instance *instance);
+
+ /*
+ Remove instance from the internal hash.
+
+ MT-NOTE: the operation must be called under acquired lock.
+ */
+ int remove_instance(Instance *instance);
+
+ /*
+ Create a new instance and register it in the internal hash.
+
+ MT-NOTE: the operation must be called under acquired lock.
+ */
+ int create_instance(const char *instance_name, uint instance_name_len,
+ DYNAMIC_ARRAY *options, uint instance_type);
+
Instance_map(const char *default_mysqld_path_arg);
~Instance_map();
+
+ /*
+ Retrieve client state name of the given instance.
+
+ MT-NOTE: the options must be called under acquired locks of the following
+ objects:
+ - Instance_map;
+ - Guardian_thread;
+ */
+ const char *get_instance_state_name(Instance *instance);
public:
const char *mysqld_path;
--- 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-04-04 16:31:10 +04: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 @@
}
+bool Instance_options::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,13 +413,31 @@
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;
+ print_argv();
+
return 0;
err:
@@ -418,75 +445,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);
+}
+
+
+void Instance_options::unset_option(const char *option_name)
+{
+ int idx= find_option(option_name);
-int Instance_options::add_option(const char* option)
+ 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)
{
- char *tmp;
- enum { SAVE_VALUE= 1, SAVE_WHOLE, SAVE_WHOLE_AND_ADD };
- struct selected_options_st
+ 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 +597,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 +614,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-04-04 16:31:10 +04:00
@@ -18,6 +18,7 @@
#include <my_global.h>
#include <my_sys.h>
+#include <string.h>
#include "parse.h"
#include "portability.h"
@@ -41,17 +42,30 @@
class Instance_options
{
public:
+ /* The operation is used to check if the option is IM-specific or not. */
+ static bool is_option_im_specific(const char *option_name);
+
+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 +90,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 +103,52 @@
/* 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-04-04 16:31:10 +04:00
@@ -70,8 +70,25 @@
"in the instance options";
case ER_ACCESS_OPTION_FILE:
return "Cannot open the option file to edit. Check permissions";
+ case ER_DROP_ACTIVE_INSTANCE:
+ return "Cannot drop an active 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.";
+ case ER_INSTANCE_IS_ACTIVE:
+ return "The instance is active. Stop the instance first";
+ case ER_THERE_IS_ACTIVE_INSTACE:
+ return "At least one instance is active. Stop all instances first";
+ case ER_INCOMPATIBLE_OPTION:
+ return "InstanceManager-specific options are prohibited from being used "
+ "in the configuration of deprecated instances";
+ case ER_CONF_FILE_DOES_NOT_EXIST:
+ return "Configuration file does not exist";
default:
- DBUG_ASSERT(0);
+ DBUG_ASSERT(0); // XXX: is it really desired behaviour here?
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-04-04 16:31:10 +04:00
@@ -190,8 +190,6 @@
int Mysql_connection_thread::check_connection()
{
ulong pkt_len=0; // to hold client reply length
- /* maximum size of the version string */
- enum { MAX_VERSION_LENGTH= 80 };
/* buffer for the first packet */ /* packet contains: */
char buff[MAX_VERSION_LENGTH + 1 + // server version, 0-ended
@@ -336,7 +334,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-04-04 16:31:10 +04:00
@@ -29,5 +29,13 @@
#define ER_ACCESS_OPTION_FILE 3008
#define ER_OFFSET_ERROR 3009
#define ER_READ_FILE 3010
+#define ER_DROP_ACTIVE_INSTANCE 3011
+#define ER_CREATE_EXISTING_INSTANCE 3012
+#define ER_INSTANCE_MISCONFIGURED 3013
+#define ER_MALFORMED_INSTANCE_NAME 3014
+#define ER_INSTANCE_IS_ACTIVE 3015
+#define ER_THERE_IS_ACTIVE_INSTACE 3016
+#define ER_INCOMPATIBLE_OPTION 3017
+#define ER_CONF_FILE_DOES_NOT_EXIST 3018
#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-04-04 16:31:10 +04: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,192 @@
}
+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 */
+ if (v > *value)
+ --v;
+ break;
+
+ case 't': /* \t -- tab */
+ *v= '\t';
+ ++v;
+ break;
+
+ case 'n': /* \n -- newline */
+ *v= '\n';
+ ++v;
+ break;
+
+ case 'r': /* \r -- carriage return */
+ *v= '\r';
+ ++v;
+ break;
+
+ case '\\': /* \\ -- back slash */
+ *v= '\\';
+ ++v;
+ break;
+
+ case 's': /* \s -- space */
+ *v= ' ';
+ ++v;
+ break;
+
+ default: /* Unknown escape sequence. Treat as error. */
+ 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. */
+
+ *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 +328,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 +338,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 +394,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 +406,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-04-04 16:31:10 +04: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-04-04 16:31:10 +04: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-04-04 16:31:10 +04:00
@@ -31,6 +31,13 @@
/* 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;
+
+const int MAX_VERSION_LENGTH= 80;
+
+const int MAX_INSTANCE_NAME_SIZE= FN_REFLEN;
+
/* 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-04-04 16:31:10 +04:00
@@ -20,19 +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)
{
@@ -72,6 +64,8 @@
memcpy(user, name_begin, user_length);
user[user_length]= 0;
+ memcpy(scrambled_password, password, strlen(password) - 1);
+ scrambled_password[strlen(password) - 1]= 0;
get_salt_from_password(salt, password);
log_info("loaded user %s", user);
@@ -121,6 +115,7 @@
Load all users from the password file. Must be called once right after
construction.
In case of failure, puts error message to the log file and returns 1
+ TODO
*/
int User_map::load(const char *password_file_name)
@@ -134,13 +129,11 @@
User *user;
int rc= 1;
+ if (my_access(password_file_name, F_OK) != 0)
+ return ERR_PASSWORD_FILE_DOES_NOT_EXIST;
+
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 +141,56 @@
if (line[0] == '#' || line[0] == '\n' &&
(line[1] == '\0' || line[1] == '\r'))
continue;
+
if ((user= new User) == 0)
- goto done;
- if (user->init(line) || my_hash_insert(&hash, (byte *) user))
- goto err_init_user;
+ {
+ my_fclose(file, MYF(0));
+ return ERR_OUT_OF_MEMORY;
+ }
+
+ if (user->init(line))
+ {
+ delete user;
+ my_fclose(file, MYF(0));
+ return ERR_PASSWORD_FILE_CORRUPTED;
+ }
+
+ if (my_hash_insert(&hash, (byte *) 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:
+
+ 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->scrambled_password);
+ }
+
my_fclose(file, MYF(0));
- return rc;
+
+ return ERR_OK;
}
@@ -176,9 +206,29 @@
const char *scrambled_password,
const char *scramble) const
{
- const User *user= (const User *) hash_search((HASH *) &hash,
- (byte *) user_name, length);
- if (user)
- return check_scramble(scrambled_password, scramble, user->salt);
- return 2;
+ const User *user= find_user(user_name, length);
+ return user ? check_scramble(scrambled_password, scramble, user->salt) : 2;
+}
+
+
+User *User_map::find_user(const char *user_name, uint user_name_len)
+{
+ return (User*) hash_search((HASH*) &hash, (byte*) user_name, user_name_len);
+}
+
+const User *User_map::find_user(const char *user_name, uint user_name_len) const
+{
+ return const_cast<User_map *> (this)->find_user(user_name, user_name_len);
+}
+
+
+void User_map::add_user(User *user)
+{
+ my_hash_insert(&hash, (byte*) user);
+}
+
+
+void User_map::remove_user(User *user)
+{
+ hash_delete(&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-04-04 16:31:10 +04:00
@@ -20,12 +20,29 @@
#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 scrambled_password[SCRAMBLED_PASSWORD_CHAR_LENGTH + 1];
+ uint8 user_length;
+ uint8 salt[SCRAMBLE_LENGTH];
+ int init(const char *line);
+
+#ifdef __GNUC__
+ /* This is just to avoid compiler warning. */
+public:
+ User()
+ {}
+#endif
+};
+
/*
User_map -- all users and passwords
*/
@@ -37,11 +54,29 @@
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;
+ User *find_user(const char *user_name, uint user_name_len);
+ void add_user(User *user);
+ void remove_user(User *user);
+
private:
+ User_map(const User_map &);
+ User_map &operator =(const User_map &);
+
+public:
HASH hash;
+
+#ifdef __GNUC__
+ /* This is just to avoid compiler warning. */
+public:
+ User_map()
+ {}
+#endif
};
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MAP_H
--- 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-04-04 16:31:10 +04: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.2210) | Alexander Nozdrin | 4 Apr |