1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-02 14:22:51 +03:00

Merge pilot.mysql.com:/data/msvensson/mysql/mysql-5.1-rpl

into  pilot.mysql.com:/data/msvensson/mysql/mysql-5.1-mtr
This commit is contained in:
msvensson@pilot.mysql.com
2008-02-28 12:21:44 +01:00
306 changed files with 14244 additions and 18872 deletions

View File

@ -58,6 +58,7 @@
./mysql.sln
./mysql.suo
./prepare
.DS_Store
.defs.mk
.depend
.depend.mk
@ -1178,6 +1179,7 @@ libmysqld/sql_parse.cc
libmysqld/sql_partition.cc
libmysqld/sql_plugin.cc
libmysqld/sql_prepare.cc
libmysqld/sql_profile.cc
libmysqld/sql_rename.cc
libmysqld/sql_repl.cc
libmysqld/sql_select.cc
@ -1279,8 +1281,12 @@ mysql-5.0.2-alpha.tar.gz
mysql-max-4.0.2-alpha-pc-linux-gnu-i686.tar.gz
mysql-test/*.ds?
mysql-test/*.vcproj
mysql-test/.DS_Store
mysql-test/funcs_1.log
mysql-test/funcs_1.tar
mysql-test/gmon.out
mysql-test/install_test_db
mysql-test/lib/My/SafeProcess/my_safe_process
mysql-test/lib/init_db.sql
mysql-test/mtr
mysql-test/mysql-test-run
@ -1367,9 +1373,12 @@ mysql-test/r/symlink.log
mysql-test/r/system_mysql_db.log
mysql-test/r/tmp.result
mysql-test/r/udf.log
mysql-test/reg.log
mysql-test/rpl.log
mysql-test/share/mysql
mysql-test/std_data/*.pem
mysql-test/suite/funcs_1.tar.gz
mysql-test/suite/funcs_1.tar.zip
mysql-test/suite/funcs_1/r/innodb_trig_03e.warnings
mysql-test/suite/funcs_1/r/innodb_views.warnings
mysql-test/suite/funcs_1/r/memory_trig_03e.warnings
@ -3012,11 +3021,3 @@ win/vs8cache.txt
ylwrap
zlib/*.ds?
zlib/*.vcproj
mysql-test/funcs_1.log
mysql-test/funcs_1.tar
mysql-test/suite/funcs_1.tar.gz
mysql-test/.DS_Store
.DS_Store
libmysqld/sql_profile.cc
mysql-test/suite/funcs_1.tar.zip
mysql-test/reg.log

View File

@ -245,3 +245,4 @@ IF(WITH_EMBEDDED_SERVER)
ADD_SUBDIRECTORY(libmysqld)
ADD_SUBDIRECTORY(libmysqld/examples)
ENDIF(WITH_EMBEDDED_SERVER)
ADD_SUBDIRECTORY(mysql-test/lib/My/SafeProcess)

View File

@ -1320,42 +1320,64 @@ void show_diff(DYNAMIC_STRING* ds,
const char* filename1, const char* filename2)
{
const char* diff_failed= 0;
DYNAMIC_STRING ds_tmp;
if (init_dynamic_string(&ds_tmp, "", 256, 256))
die("Out of memory");
/* First try with unified diff */
/* First try with diff --help to see if the command exists at all */
if (run_tool("diff",
&ds_tmp, /* Get output from diff in ds_tmp */
"-u",
filename1,
filename2,
"--help",
"2>&1",
NULL) > 1) /* Most "diff" tools return >1 if error */
NULL) != 0) /* Most "diff --help" tools return 0 */
{
diff_failed= "You don't appear to have diff installed";
}
else
{
dynstr_set(&ds_tmp, "");
/* First try with unified diff */
/* Fallback to context diff with "diff -c" */
if (run_tool("diff",
&ds_tmp, /* Get output from diff in ds_tmp */
"-c",
"-u",
filename1,
filename2,
"2>&1",
NULL) > 1) /* Most "diff" tools return >1 if error */
{
/*
Fallback to dump both files to result file and inform
about installing "diff"
*/
dynstr_set(&ds_tmp, "");
dynstr_append(&ds_tmp,
/* Fallback to context diff with "diff -c" */
if (run_tool("diff",
&ds_tmp, /* Get output from diff in ds_tmp */
"-c",
filename1,
filename2,
"2>&1",
NULL) > 1) /* Most "diff" tools return >1 if error */
{
dynstr_set(&ds_tmp, "");
diff_failed= "Could not execute 'diff -u' or 'diff -c'";
}
}
}
if (diff_failed)
{
/*
Fallback to dump both files to result file and inform
about installing "diff"
*/
dynstr_append(&ds_tmp, "\n");
dynstr_append(&ds_tmp, diff_failed);
dynstr_append(&ds_tmp,
"\n"
"The two files differ but it was not possible to execute 'diff' in\n"
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
"order to show only the difference. Instead the whole content of the\n"
"two files was shown for you to diff manually.\n\n"
"To get a better report you should install 'diff' on your system, which you\n"
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
#ifdef __WIN__
@ -1363,16 +1385,15 @@ void show_diff(DYNAMIC_STRING* ds,
#endif
"\n");
dynstr_append(&ds_tmp, " --- ");
dynstr_append(&ds_tmp, filename1);
dynstr_append(&ds_tmp, " >>>\n");
cat_file(&ds_tmp, filename1);
dynstr_append(&ds_tmp, "<<<\n --- ");
dynstr_append(&ds_tmp, filename1);
dynstr_append(&ds_tmp, " >>>\n");
cat_file(&ds_tmp, filename2);
dynstr_append(&ds_tmp, "<<<<\n");
}
dynstr_append(&ds_tmp, " --- ");
dynstr_append(&ds_tmp, filename1);
dynstr_append(&ds_tmp, " >>>\n");
cat_file(&ds_tmp, filename1);
dynstr_append(&ds_tmp, "<<<\n --- ");
dynstr_append(&ds_tmp, filename1);
dynstr_append(&ds_tmp, " >>>\n");
cat_file(&ds_tmp, filename2);
dynstr_append(&ds_tmp, "<<<<\n");
}
if (ds)
@ -2181,8 +2202,19 @@ void eval_expr(VAR *v, const char *p, const char **p_end)
int open_file(const char *name)
{
char buff[FN_REFLEN];
size_t length;
DBUG_ENTER("open_file");
DBUG_PRINT("enter", ("name: %s", name));
/* Extract path from current file and try it as base first */
if (dirname_part(buff, cur_file->file_name, &length))
{
strxmov(buff, buff, name, NullS);
if (access(buff, F_OK) == 0){
DBUG_PRINT("info", ("The file exists"));
name= buff;
}
}
if (!test_if_hard_path(name))
{
strxmov(buff, opt_basedir, name, NullS);
@ -7444,6 +7476,9 @@ void do_get_replace(struct st_command *command)
if (!*from)
die("Wrong number of arguments to replace_result in '%s'",
command->query);
#ifdef __WIN__
fix_win_paths(to, from - to);
#endif
insert_pointer_name(&from_array,to);
to= get_string(&buff, &from, command);
insert_pointer_name(&to_array,to);

View File

@ -2758,8 +2758,8 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
server-tools/Makefile server-tools/instance-manager/Makefile dnl
cmd-line-utils/Makefile cmd-line-utils/libedit/Makefile dnl
libmysqld/Makefile libmysqld/examples/Makefile dnl
mysql-test/Makefile dnl
mysql-test/ndb/Makefile netware/Makefile sql-bench/Makefile dnl
mysql-test/Makefile mysql-test/lib/My/SafeProcess/Makefile dnl
netware/Makefile sql-bench/Makefile dnl
include/mysql_version.h plugin/Makefile win/Makefile)
AC_CONFIG_COMMANDS([default], , test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h)

View File

@ -17,119 +17,24 @@
## Process this file with automake to create Makefile.in
SUBDIRS = ndb
testdir = $(prefix)/mysql-test
benchdir_root= $(prefix)
testdir = $(benchdir_root)/mysql-test
EXTRA_SCRIPTS = mysql-test-run-shell.sh install_test_db.sh \
valgrind.supp $(PRESCRIPTS)
EXTRA_DIST = $(EXTRA_SCRIPTS) suite
GENSCRIPTS = mysql-test-run-shell install_test_db mtr mysql-test-run
PRESCRIPTS = mysql-test-run.pl mysql-stress-test.pl
test_SCRIPTS = $(GENSCRIPTS) $(PRESCRIPTS)
CLEANFILES = $(GENSCRIPTS)
EXTRA_DIST = README \
mysql-test-run.pl \
mysql-stress-test.pl \
t r include suite extra \
lib std_data \
valgrind.supp
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I..
test_SCRIPTS = mtr mysql-test-run
CLEANFILES = $(test_SCRIPTS)
SUBDIRS = lib/My/SafeProcess
dist-hook:
mkdir -p \
$(distdir)/t \
$(distdir)/extra/binlog_tests \
$(distdir)/extra/rpl_tests \
$(distdir)/r \
$(distdir)/include \
$(distdir)/std_data \
$(distdir)/std_data/ndb_backup50 \
$(distdir)/std_data/ndb_backup51 \
$(distdir)/std_data/ndb_backup51_data_be \
$(distdir)/std_data/ndb_backup51_data_le \
$(distdir)/std_data/parts \
$(distdir)/lib \
$(distdir)/lib/My
-$(INSTALL_DATA) $(srcdir)/t/*.def $(distdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.test $(distdir)/t
-$(INSTALL_DATA) $(srcdir)/t/*.imtest $(distdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.sql $(distdir)/t
-$(INSTALL_DATA) $(srcdir)/t/*.disabled $(distdir)/t
-$(INSTALL_DATA) $(srcdir)/t/*.opt $(srcdir)/t/*.slave-mi $(distdir)/t
-$(INSTALL_SCRIPT) $(srcdir)/t/*.sh $(distdir)/t
$(INSTALL_DATA) $(srcdir)/extra/binlog_tests/*.test $(distdir)/extra/binlog_tests
$(INSTALL_DATA) $(srcdir)/extra/rpl_tests/*.test $(distdir)/extra/rpl_tests
-$(INSTALL_DATA) $(srcdir)/extra/binlog_tests/*.opt $(distdir)/extra/binlog_tests
-$(INSTALL_DATA) $(srcdir)/extra/rpl_tests/*.opt $(distdir)/extra/rpl_tests
$(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include
$(INSTALL_DATA) $(srcdir)/include/*.sql $(distdir)/include
$(INSTALL_DATA) $(srcdir)/include/*.test $(distdir)/include
$(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r
$(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/Index.xml $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.pem $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.frm $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.MY* $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup50/BACKUP* $(distdir)/std_data/ndb_backup50
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51/BACKUP* $(distdir)/std_data/ndb_backup51
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_data_be/BACKUP* $(distdir)/std_data/ndb_backup51_data_be
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_data_le/BACKUP* $(distdir)/std_data/ndb_backup51_data_le
$(INSTALL_DATA) $(srcdir)/std_data/parts/part_* $(distdir)/std_data/parts
$(INSTALL_DATA) $(srcdir)/lib/*.pl $(distdir)/lib
$(INSTALL_DATA) $(srcdir)/lib/My/*.pm $(distdir)/lib/My
-rm -rf `find $(distdir)/suite -type d -name SCCS` $(distdir)/suite/row_lock
# Install all files and files in directories listed in EXTRA_DIST
install-data-local:
$(mkinstalldirs) \
$(DESTDIR)$(testdir)/t \
$(DESTDIR)$(testdir)/extra/binlog_tests \
$(DESTDIR)$(testdir)/extra/rpl_tests \
$(DESTDIR)$(testdir)/r \
$(DESTDIR)$(testdir)/include \
$(DESTDIR)$(testdir)/std_data \
$(DESTDIR)$(testdir)/std_data/ndb_backup50 \
$(DESTDIR)$(testdir)/std_data/ndb_backup51 \
$(DESTDIR)$(testdir)/std_data/ndb_backup51_data_be \
$(DESTDIR)$(testdir)/std_data/ndb_backup51_data_le \
$(DESTDIR)$(testdir)/std_data/parts \
$(DESTDIR)$(testdir)/lib \
$(DESTDIR)$(testdir)/lib/My
$(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(testdir)
-$(INSTALL_DATA) $(srcdir)/t/*.def $(DESTDIR)$(testdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.test $(DESTDIR)$(testdir)/t
-$(INSTALL_DATA) $(srcdir)/t/*.imtest $(DESTDIR)$(testdir)/t
$(INSTALL_DATA) $(srcdir)/t/*.sql $(DESTDIR)$(testdir)/t
-$(INSTALL_DATA) $(srcdir)/t/*.disabled $(DESTDIR)$(testdir)/t
-$(INSTALL_DATA) $(srcdir)/t/*.opt $(DESTDIR)$(testdir)/t
-$(INSTALL_SCRIPT) $(srcdir)/t/*.sh $(DESTDIR)$(testdir)/t
-$(INSTALL_DATA) $(srcdir)/t/*.slave-mi $(DESTDIR)$(testdir)/t
$(INSTALL_DATA) $(srcdir)/r/*.result $(DESTDIR)$(testdir)/r
$(INSTALL_DATA) $(srcdir)/r/*.require $(DESTDIR)$(testdir)/r
$(INSTALL_DATA) $(srcdir)/extra/binlog_tests/*.test $(DESTDIR)$(testdir)/extra/binlog_tests
$(INSTALL_DATA) $(srcdir)/extra/rpl_tests/*.test $(DESTDIR)$(testdir)/extra/rpl_tests
-$(INSTALL_DATA) $(srcdir)/extra/binlog_tests/*.opt $(DESTDIR)$(testdir)/extra/binlog_tests
-$(INSTALL_DATA) $(srcdir)/extra/rpl_tests/*.opt $(DESTDIR)$(testdir)/extra/rpl_tests
$(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include
$(INSTALL_DATA) $(srcdir)/include/*.sql $(DESTDIR)$(testdir)/include
$(INSTALL_DATA) $(srcdir)/include/*.test $(DESTDIR)$(testdir)/include
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.*001 $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/Index.xml $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.frm $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.MY* $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup50/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup50
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup51
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_data_be/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup51_data_be
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_data_le/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup51_data_le
$(INSTALL_DATA) $(srcdir)/std_data/parts/part_* $(DESTDIR)$(testdir)/std_data/parts
$(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib
$(INSTALL_DATA) $(srcdir)/lib/My/*.pm $(DESTDIR)$(testdir)/lib/My
for f in `(cd $(srcdir); find suite -type f | egrep -v 'SCCS|row_lock')`; \
for f in `(cd $(srcdir); find $(EXTRA_DIST) -type f)`; \
do \
d=$(DESTDIR)$(testdir)/`dirname $$f`; \
mkdir -p $$d ; \
@ -149,31 +54,5 @@ mysql-test-run:
$(RM) -f mysql-test-run
$(LN_S) mysql-test-run.pl mysql-test-run
SUFFIXES = .sh
.sh:
@RM@ -f $@ $@-t
@SED@ \
-e 's!@''testdir''@!$(testdir)!g' \
-e 's!@''bindir''@!$(bindir)!g' \
-e 's!@''scriptdir''@!$(bindir)!g' \
-e 's!@''prefix''@!$(prefix)!g' \
-e 's!@''datadir''@!$(datadir)!g' \
-e 's!@''localstatedir''@!$(localstatedir)!g' \
-e 's!@''libexecdir''@!$(libexecdir)!g' \
-e 's!@''PERL''@!@PERL@!' \
-e 's!@''VERSION''@!@VERSION@!' \
-e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \
-e 's!@''MYSQL_TCP_PORT_DEFAULT''@!@MYSQL_TCP_PORT_DEFAULT@!' \
-e 's!@''MYSQL_BASE_VERSION''@!@MYSQL_BASE_VERSION@!' \
-e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \
-e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \
-e 's!@''MYSQL_NO_DASH_VERSION''@!@MYSQL_NO_DASH_VERSION@!' \
-e 's!@''MYSQL_SERVER_SUFFIX''@!@MYSQL_SERVER_SUFFIX@!' \
-e 's!@''USE_NDBCLUSTER''@!@TEST_NDBCLUSTER@!g' \
$< > $@-t
@CHMOD@ +x $@-t
@MV@ $@-t $@
# Don't update the files from bitkeeper
%::SCCS/s.%

View File

@ -1,65 +0,0 @@
#! /bin/sh
# This script is a hack for lazy developers who want to get a quick
# start on the result file. The code here is rather dirty, but it works
# If you have a spare moment feel free to improve it - the right way is
# to start mysqld yourself and run mysqltest -r
RESULT_DIR=r
if [ -z "$EDITOR" ] ; then
EDITOR=vi
fi
function die()
{
echo $1
exit 1
}
function usage()
{
echo "Usage: $0 test_name"
exit 1
}
test_name=$1
[ -z "$test_name" ] && usage
result_file=$RESULT_DIR/$test_name.result
reject_file=$RESULT_DIR/$test_name.reject
[ -f $result_file ] && die "result file $result_file has already been created"
touch $result_file
echo "Running the test case against empty file, will fail, but don't worry"
./mysql-test-run --local $test_name
if [ -f $reject_file ] ; then
echo "Below are the contents of the reject file:"
echo "-----start---------------------"
cat $reject_file
echo "-----end-----------------------"
echo "Is this the output you expected from your test case?(y/n)[n]"
read yes_no
if [ x$yes_no = xy ] ; then
echo "Press any key to edit it in $EDITOR, or Ctrl-C to abort"
read junk
$EDITOR $reject_file
edited="edited"
fi
echo "Save $edited file as master result? (y/n)[y]"
read yes_no
if [ x$yes_no != xn ]; then
mv $reject_file $result_file
fi
else
echo "Your test failed so bad, it did not even produce a reject file"
echo "You need to fix your bugs in the test case, the code, or both"
exit 1
fi

View File

@ -7,7 +7,7 @@
-- source include/have_log_bin.inc
# The server need to be started in $MYSQLTEST_VARDIR since it
# uses ../std_data_ln/
# uses ../../std_data/
-- source include/uses_vardir.inc
--disable_warnings
@ -114,7 +114,7 @@ insert into t1 values(1);
insert ignore into t1 values(1);
replace into t1 values(100);
create table t2 (a varchar(200)) engine=blackhole;
eval load data infile '../std_data_ln/words.dat' into table t2;
eval load data infile '../../std_data/words.dat' into table t2;
alter table t1 add b int;
alter table t1 drop b;
create table t3 like t1;

View File

@ -16,7 +16,8 @@ source include/show_binlog_events.inc;
# escaped).
flush logs;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
--exec $MYSQL_BINLOG --short-form $MYSQLTEST_VARDIR/log/master-bin.000001
let $MYSQLD_DATADIR= `select @@datadir`;
--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001
drop table t2;
# End of 4.1 tests

View File

@ -278,7 +278,7 @@ CREATE TABLE t5 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
# execute
--error ER_DUP_ENTRY
load data infile '../std_data_ln/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2);
load data infile '../../std_data/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2);
# check
select * from t4;
select count(*) from t1 /* must be 2 */;

View File

@ -20,7 +20,8 @@
eval create table t1 (a int) engine=$engine_type;
flush tables;
system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYI ;
let $MYSQLD_DATADIR= `select @@datadir`;
system rm $MYSQLD_DATADIR/test/t1.MYI ;
drop table if exists t1;
save_master_pos;
connection slave;

View File

@ -137,6 +137,8 @@ sync_slave_with_master;
select hex(c1), hex(c2) from t1;
connection master;
let $MYSQLD_DATADIR= `select @@datadir`;
--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001
drop table t1;
sync_slave_with_master;

View File

@ -23,12 +23,12 @@ connection master;
select last_insert_id();
create table t1(a int not null auto_increment, b int, primary key(a) );
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
# verify that LAST_INSERT_ID() is set by LOAD DATA INFILE
select last_insert_id();
create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60));
load data infile '../std_data_ln/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines;
load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines;
create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60));
insert into t3 select * from t2;
@ -63,7 +63,7 @@ sync_with_master;
insert into t1 values(1,10);
connection master;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
save_master_pos;
connection slave;
@ -87,7 +87,7 @@ connection master;
set sql_log_bin=0;
delete from t1;
set sql_log_bin=1;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
save_master_pos;
connection slave;
# The SQL slave thread should be stopped now.
@ -112,7 +112,7 @@ connection master;
set sql_log_bin=0;
delete from t1;
set sql_log_bin=1;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
save_master_pos;
connection slave;
# The SQL slave thread should be stopped now.
@ -132,7 +132,7 @@ reset master;
eval create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60),
unique(day)) engine=$engine_type; # no transactions
--error ER_DUP_ENTRY
load data infile '../std_data_ln/rpl_loaddata2.dat' into table t2 fields
load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields
terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by
'\n##\n' starting by '>' ignore 1 lines;
select * from t2;
@ -148,7 +148,7 @@ alter table t2 drop key day;
connection master;
delete from t2;
--error ER_DUP_ENTRY
load data infile '../std_data_ln/rpl_loaddata2.dat' into table t2 fields
load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields
terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by
'\n##\n' starting by '>' ignore 1 lines;
connection slave;
@ -162,7 +162,7 @@ drop table t1;
CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB;
--error ER_DUP_ENTRY
LOAD DATA INFILE "../std_data_ln/words.dat" INTO TABLE t1;
LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1;
--disable_warnings
DROP TABLE IF EXISTS t1;

View File

@ -32,8 +32,13 @@ reset master;
eval create table t1(n int not null auto_increment primary key)ENGINE=$engine_type;
insert into t1 values (NULL);
drop table t1;
let $LOAD_FILE= ../../std_data/words.dat;
if (!`SELECT length(load_file('$LOAD_FILE'))`){
let $LOAD_FILE= ../$LOAD_FILE;
}
eval create table t1 (word char(20) not null)ENGINE=$engine_type;
load data infile '../std_data_ln/words.dat' into table t1 ignore 1 lines;
--replace_result $LOAD_FILE LOAD_FILE
eval load data infile '$LOAD_FILE' into table t1 ignore 1 lines;
select count(*) from t1;
--replace_result $VERSION VERSION
--replace_column 2 # 5 #

View File

@ -1,7 +1,9 @@
let $LOAD_FILE= $MYSQLTEST_VARDIR/std_data/words.dat;
CREATE TABLE t1 (word CHAR(20) NOT NULL);
LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t1;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/std_data/words.dat' INTO TABLE t1;
--replace_result $LOAD_FILE LOAD_FILE
eval LOAD DATA INFILE '$LOAD_FILE' INTO TABLE t1;
--replace_result $LOAD_FILE LOAD_FILE
eval LOAD DATA INFILE '$LOAD_FILE' INTO TABLE t1;
SELECT * FROM t1 ORDER BY word LIMIT 10;
#

View File

@ -2,7 +2,7 @@
-- source include/master-slave.inc
create table t1 (word char(20) not null);
load data infile '../std_data_ln/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
eval load data local infile '$MYSQL_TEST_DIR/std_data/words.dat' into table t1;
select * from t1 limit 10;

View File

@ -1,22 +0,0 @@
#! /bin/sh
# Sasha's hack to fix results generated with mysql-test-run --record
# to be version and test port independent. In some cases, further minor
# manual edititing may be required, but most of the time it should not
# happen
#It is assumed we are running the script in mysql-test directory
VERSION=4.0.1-alpha-debug-log
TEST_CASE=$1
if [ -z "$TEST_CASE" ] ;
then
echo "usage: $0 test_case_name"
exit 1
fi
../extra/replace $VERSION '$VERSION' 9306 '$MASTER_MYPORT' 9307 \
'$SLAVE_MYPORT' \\ \\\\ -- r/$TEST_CASE.result

View File

@ -1,34 +1,47 @@
#
# This test is executed twice for each test case if mysql-test-run is passed
# the flag --check-testcase.
# Before every testcase it's run with mysqltest in record mode and will
# thus produce an output file
# that can be compared to output from after the tescase.
# In that way it's possible to check that a testcase does not have
# the flag --check-testcase. Before every testcase it is run with mysqltest
# in record mode and will thus produce an output file that can be compared
# to output from after the tescase.
# In that way its possible to check that a testcase does not have
# any unwanted side affects.
#
#
# Dump all global variables
#
show global variables;
# Dump all global variables except those
# that are supposed to change
show global variables where Variable_name != 'timestamp';
#
# Dump all databases
#
# Dump all databases, there should be none
# except mysql, test and information_schema
show databases;
#
# Dump the "test" database, all it's tables and their data
#
--exec $MYSQL_DUMP --skip-comments --skip-lock-tables test
# The test database should not contain any tables
show tables from test;
#
# Dump the "mysql" database and it's tables
# Select data separately to add "order by"
#
--exec $MYSQL_DUMP --skip-comments --skip-lock-tables --no-data mysql
# Dump the "mysql" database and its tables
use mysql;
show tables;
show create table columns_priv;
show create table db;
show create table func;
show create table help_category;
show create table help_keyword;
show create table help_relation;
show create table help_relation;
show create table host;
show create table proc;
show create table procs_priv;
show create table tables_priv;
show create table time_zone;
show create table time_zone_leap_second;
show create table time_zone_name;
show create table time_zone_transition;
show create table time_zone_transition_type;
show create table user;
# Select data from system tables to make sure they have been properly
# restored after test
select * from columns_priv;
select * from db order by host, db, user;
select * from func;

View File

@ -0,0 +1,25 @@
# Use default setting for mysqld processes
!include default_mysqld.cnf
[mysqld.1]
# Run the master.sh script before starting this process
#!run-master-sh
log-bin= master-bin
[mysqlbinlog]
disable-force-if-open
# mysql_fix_privilege_tables.sh does not read from [client] so it
# need its own section
[mysql_fix_privilege_tables]
socket= @client.socket
port= @client.port
user= @client.user
password= @client.password
[ENV]
MASTER_MYPORT= @mysqld.1.port
MASTER_MYSOCK= @mysqld.1.socket

View File

@ -0,0 +1,21 @@
# Default values that applies to all MySQL Servers
[mysqld]
open-files-limit= 1024
local-infile
default-character-set= latin1
# Increase default connect_timeout to avoid intermittent
# disconnects when test servers are put under load see BUG#28359
connect-timeout= 60
log-bin-trust-function-creators=1
key_buffer_size= 1M
sort_buffer= 256K
max_heap_table_size= 1M
loose-innodb_data_file_path= ibdata1:10M:autoextend
set-variable= slave_net_timeout=120
log-bin

View File

@ -0,0 +1,27 @@
[cluster_config]
MaxNoOfSavedMessages= 1000
MaxNoOfConcurrentTransactions= 64
MaxNoOfConcurrentOperations= 10000
DataMemory= 20M
IndexMemory= 1M
Diskless= 0
TimeBetweenWatchDogCheck= 30000
MaxNoOfOrderedIndexes= 32
MaxNoOfAttributes= 2048
TimeBetweenGlobalCheckpoints= 500
NoOfFragmentLogFiles= 4
FragmentLogFileSize= 12M
DiskPageBufferMemory= 4M
# O_DIRECT has issues on 2.4 whach have not been handled, Bug #29612
#ODirect= 1
# the following parametes just function as a small regression
# test that the parameter exists
InitialNoOfOpenFiles= 27
# Increase timeouts for slow test-machines
HeartbeatIntervalDbDb= 30000
HeartbeatIntervalDbApi= 30000
#TransactionDeadlockDetectionTimeout= 7500

View File

@ -1,28 +0,0 @@
--source include/have_log_bin.inc
--source include/not_embedded.inc
--source ./include/have_federated_db.inc
source ./include/master-slave.inc;
# remote table creation
# We have to sync with master, to ensure slave had time to start properly
# before we stop it. If not, we get errors about UNIX_TIMESTAMP() in the log.
connection master;
sync_slave_with_master;
connection slave;
#--replicate-ignore-db=federated
stop slave;
--disable_warnings
# at this point, we are connected to master
DROP DATABASE IF EXISTS federated;
--enable_warnings
CREATE DATABASE federated;
connection master;
--disable_warnings
DROP DATABASE IF EXISTS federated;
--enable_warnings
CREATE DATABASE federated;

View File

@ -1,4 +1,5 @@
disable_query_log;
--require r/true.require
select (support = 'YES' or support = 'DEFAULT') as `TRUE` from information_schema.engines where engine = 'blackhole';
enable_query_log;
if (!`SELECT count(*) FROM information_schema.engines WHERE
(support = 'YES' OR support = 'DEFAULT') AND
engine = 'blackhole'`){
skip Need blackhole engine;
}

View File

@ -1,7 +0,0 @@
#
# Check if the variable MYSQL_BUG25714 is set
#
--require r/have_bug25714.require
disable_query_log;
eval select LENGTH("$MYSQL_BUG25714") > 0 as "have_bug25714_exe";
enable_query_log;

View File

@ -1,4 +0,0 @@
disable_query_log;
--require r/true.require
select (support = 'YES' or support = 'DEFAULT') as `TRUE` from information_schema.engines where engine = 'federated';
enable_query_log;

View File

@ -1,4 +1,4 @@
--require r/have_ndbapi_examples.require
disable_query_log;
eval select LENGTH("$MY_NDB_EXAMPLES_BINARY") > 0 as "have_ndb_example";
eval select LENGTH("$NDB_EXAMPLES_BINARY") > 0 as "have_ndb_example";
enable_query_log;

View File

@ -7,16 +7,20 @@ eval SET SESSION STORAGE_ENGINE = $engine_type;
drop table if exists t1;
--enable_warnings
let $load_file= $MYSQLTEST_VARDIR/std_data/loaddata2.dat;
# NDB does not support the create option 'Binlog of table with BLOB attribute and no PK'
# So use a dummy PK here.
create table t1 (id int unsigned not null auto_increment primary key, a text, b text);
start transaction;
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''' (a, b);
--replace_result $load_file LOAD_FILE
eval load data infile '$load_file' into table t1 fields terminated by ',' enclosed by '''' (a, b);
commit;
select count(*) from t1;
truncate table t1;
start transaction;
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''' (a, b);
--replace_result $load_file LOAD_FILE
eval load data infile '$load_file' into table t1 fields terminated by ',' enclosed by '''' (a, b);
rollback;
select count(*) from t1;

View File

@ -623,7 +623,8 @@ DROP TABLE t1,t2,t3;
#
create table t1 (a int) engine=innodb;
copy_file $MYSQLTEST_VARDIR/master-data/test/t1.frm $MYSQLTEST_VARDIR/master-data/test/bug29807.frm;
let $MYSQLD_DATADIR= `select @@datadir`;
copy_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/bug29807.frm;
--error 1146
select * from bug29807;
drop table t1;

View File

@ -2,23 +2,21 @@
# By JBM 2006-02-16 So that the code is not repeated #
# in test cases and can be reused. #
######################################################
--exec $NDB_MGM --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -e "start backup" >> $NDB_TOOLS_OUTPUT
--exec $NDB_MGM --no-defaults --ndb-connectstring="$NDB_CONNECTSTRING" -e "start backup" >> $NDB_TOOLS_OUTPUT
# there is no neat way to find the backupid, this is a hack to find it...
let $dump_file= $MYSQLTEST_VARDIR/tmp/tmp.dat;
--exec $NDB_TOOLS_DIR/ndb_select_all --ndb-connectstring="$NDB_CONNECTSTRING" -d sys --delimiter=',' SYSTAB_0 | grep 520093696 > $dump_file
--exec $NDB_TOOLS_DIR/ndb_select_all --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -d sys --delimiter=',' SYSTAB_0 | grep 520093696 > $MYSQLTEST_VARDIR/tmp.dat
CREATE TEMPORARY TABLE test.backup_info (id INT, backup_id INT) ENGINE = HEAP;
CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP;
DELETE FROM test.backup_info;
LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ',';
--replace_column 1 <the_backup_id>
SELECT @the_backup_id:=backup_id FROM test.backup_info;
let the_backup_id=`select @the_backup_id`;
--replace_result $dump_file DUMP_FILE
eval LOAD DATA INFILE '$dump_file' INTO TABLE test.backup_info FIELDS TERMINATED BY ',';
# Load backup id into environment variable
let the_backup_id=`SELECT backup_id from test.backup_info`;
DROP TABLE test.backup_info;
remove_file $dump_file;

View File

@ -17,7 +17,7 @@ while ($mysql_errno)
{
if (!$counter)
{
die("Failed while waiting for mysqld to come out of readonly mode");
die Failed while waiting for mysqld to come out of readonly mode;
}
dec $counter;
--sleep 0.1

View File

@ -3,6 +3,6 @@
# in test cases and can be reused. #
######################################################
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -p 8 -b $the_backup_id -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="$NDB_CONNECTSTRING" -p 8 -b $the_backup_id -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -p 8 -b $the_backup_id -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="$NDB_CONNECTSTRING" -p 8 -b $the_backup_id -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT

View File

@ -3,9 +3,9 @@
# in test cases and can be reused. #
######################################################
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT_SLAVE" -p 8 -b $the_backup_id -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="$NDB_CONNECTSTRING_SLAVE" -p 8 -b $the_backup_id -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT_SLAVE" -p 8 -b $the_backup_id -n 2 -r -e --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="$NDB_CONNECTSTRING_SLAVE" -p 8 -b $the_backup_id -n 2 -r -e --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT

View File

@ -19,12 +19,6 @@
# #
###################################################################
--disable_query_log
eval set @USE_RUNNING_SERVER= '$USE_RUNNING_SERVER';
--require r/testdb_only.require
SELECT 'use extern server'
AS "Variable_name ",
IF(@USE_RUNNING_SERVER= '1','YES',
IF(@USE_RUNNING_SERVER= '0','NO','UNEXPECTED'))
AS "Value" ;
--enable_query_log
if ($USE_RUNNING_SERVER){
skip Not with extern server;
}

View File

@ -32,7 +32,7 @@ let $wait_counter= 150;
while ($wait_counter)
{
let $result= `SHOW $show_type`;
let $success= `SELECT '$result' LIKE $show_pattern`;
let $success= `SELECT "$result" LIKE $show_pattern`;
if ($success)
{
let $wait_counter= 0;

View File

@ -1,115 +0,0 @@
#!/bin/sh
# Copyright (C) 1997-2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# This scripts creates the privilege tables db, host, user, tables_priv,
# columns_priv in the mysql database, as well as the func table.
if [ x$1 = x"--bin" ]; then
shift 1
BINARY_DIST=1
bindir=../bin
scriptdir=bin
libexecdir=../libexec
# Check if it's a binary distribution or a 'make install'
if test -x ../libexec/mysqld
then
execdir=../libexec
elif test -x ../../sbin/mysqld # RPM installation
then
execdir=../../sbin
bindir=../../bin
scriptdir=../bin
libexecdir=../../libexec
else
execdir=../bin
fi
fix_bin=mysql-test
else
execdir=../sql
bindir=../client
fix_bin=.
scriptdir=scripts
libexecdir=../libexec
fi
vardir=var
logdir=$vardir/log
if [ x$1 = x"-slave" ]
then
shift 1
data=var/slave-data
else
if [ x$1 = x"-1" ]
then
data=var/master-data1
else
data=var/master-data
fi
fi
ldata=$fix_bin/$data
mdata=$data/mysql
EXTRA_ARG=""
mysqld=
if test -x $execdir/mysqld
then
mysqld=$execdir/mysqld
else
if test ! -x $libexecdir/mysqld
then
echo "mysqld is missing - looked in $execdir and in $libexecdir"
exit 1
else
mysqld=$libexecdir/mysqld
fi
fi
# On IRIX hostname is in /usr/bsd so add this to the path
PATH=$PATH:/usr/bsd
hostname=`hostname` # Install this too in the user table
hostname="$hostname%" # Fix if not fully qualified hostname
#create the directories
[ -d $vardir ] || mkdir $vardir
[ -d $logdir ] || mkdir $logdir
# Create database directories mysql & test
if [ -d $data ] ; then rm -rf $data ; fi
mkdir $data $data/mysql $data/test
#for error messages
if [ x$BINARY_DIST = x1 ] ; then
basedir=..
else
basedir=.
EXTRA_ARG="--windows"
fi
INSTALL_CMD="$scriptdir/mysql_install_db --no-defaults $EXTRA_ARG --basedir=$basedir --datadir=mysql-test/$ldata --srcdir=."
echo "running $INSTALL_CMD"
cd ..
if $INSTALL_CMD
then
exit 0
else
echo "Error executing mysqld --bootstrap"
exit 1
fi

View File

@ -4,6 +4,7 @@ package My::Config::Option;
use strict;
use warnings;
use Carp;
sub new {
@ -31,7 +32,7 @@ package My::Config::Group;
use strict;
use warnings;
use Carp;
sub new {
my ($class, $group_name)= @_;
@ -68,7 +69,7 @@ sub remove {
return undef unless defined $option;
# Remove from the hash
delete($self->{options_by_name}->{$option_name}) or die;
delete($self->{options_by_name}->{$option_name}) or croak;
# Remove from the array
@{$self->{options}}= grep { $_->name ne $option_name } @{$self->{options}};
@ -88,6 +89,33 @@ sub name {
return $self->{name};
}
sub suffix {
my ($self)= @_;
# Everything in name from the last .
my @parts= split(/\./, $self->{name});
my $suffix= pop(@parts);
return ".$suffix";
}
sub after {
my ($self, $prefix)= @_;
die unless defined $prefix;
# everything after $prefix
my $name= $self->{name};
if ($name =~ /^\Q$prefix\E(.*)$/)
{
return $1;
}
die "Failed to extract the value after '$prefix' in $name";
}
sub split {
my ($self)= @_;
# Return an array with name parts
return split(/\./, $self->{name});
}
#
# Return a specific option in the group
@ -100,23 +128,37 @@ sub option {
#
# Return a specific value for an option in the group
# Return value for an option in the group, fail if it does not exist
#
sub value {
my ($self, $option_name)= @_;
my $option= $self->option($option_name);
die "No option named '$option_name' in this group"
croak "No option named '$option_name' in group '$self->{name}'"
if ! defined($option);
return $option->value();
}
#
# Return value for an option if it exist
#
sub if_exist {
my ($self, $option_name)= @_;
my $option= $self->option($option_name);
return undef if ! defined($option);
return $option->value();
}
package My::Config;
use strict;
use warnings;
use Carp;
use IO::File;
use File::Basename;
@ -132,13 +174,13 @@ sub new {
my $self= bless { groups => [] }, $class;
my $F= IO::File->new($path, "<")
or die "Could not open '$path': $!";
or croak "Could not open '$path': $!";
while ( my $line= <$F> ) {
chomp($line);
# [group]
if ( $line =~ /\[(.*)\]/ ) {
if ( $line =~ /^\[(.*)\]/ ) {
# New group found
$group_name= $1;
#print "group: $group_name\n";
@ -149,7 +191,7 @@ sub new {
# Magic #! comments
elsif ( $line =~ /^#\!/) {
my $magic= $line;
die "Found magic comment '$magic' outside of group"
croak "Found magic comment '$magic' outside of group"
unless $group_name;
#print "$magic\n";
@ -171,8 +213,13 @@ sub new {
# !include <filename>
elsif ( $line =~ /^\!include\s*(.*?)\s*$/ ) {
my $include_file_name= dirname($path)."/".$1;
# Check that the file exists
die "The include file '$include_file_name' does not exist"
# Check that the file exists relative to path of first config file
if (! -f $include_file_name){
# Try to include file relativ to current dir
$include_file_name= $1;
}
croak "The include file '$include_file_name' does not exist"
unless -f $include_file_name;
$self->append(My::Config->new($include_file_name));
@ -182,7 +229,7 @@ sub new {
elsif ( $line =~ /^([\@\w-]+)\s*$/ ) {
my $option= $1;
die "Found option '$option' outside of group"
croak "Found option '$option' outside of group"
unless $group_name;
#print "$option\n";
@ -194,13 +241,13 @@ sub new {
my $option= $1;
my $value= $2;
die "Found option '$option=$value' outside of group"
croak "Found option '$option=$value' outside of group"
unless $group_name;
#print "$option=$value\n";
$self->insert($group_name, $option, $value);
} else {
die "Unexpected line '$line' found in '$path'";
croak "Unexpected line '$line' found in '$path'";
}
}
@ -231,6 +278,7 @@ sub insert {
# Add the option to the group
$group->insert($option, $value, $if_not_exist);
}
return $group;
}
#
@ -240,11 +288,11 @@ sub remove {
my ($self, $group_name, $option_name)= @_;
my $group= $self->group($group_name);
die "group '$group_name' does not exist"
croak "group '$group_name' does not exist"
unless defined($group);
$group->remove($option_name) or
die "option '$option_name' does not exist";
croak "option '$option_name' does not exist";
}
@ -267,10 +315,10 @@ sub group_exists {
#
sub _group_insert {
my ($self, $group_name)= @_;
caller eq __PACKAGE__ or die;
caller eq __PACKAGE__ or croak;
# Check that group does not already exist
die "Group already exists" if $self->group_exists($group_name);
croak "Group already exists" if $self->group_exists($group_name);
my $group= My::Config::Group->new($group_name);
push(@{$self->{groups}}, $group);
@ -354,11 +402,11 @@ sub value {
my ($self, $group_name, $option_name)= @_;
my $group= $self->group($group_name);
die "group '$group_name' does not exist"
croak "group '$group_name' does not exist"
unless defined($group);
my $option= $group->option($option_name);
die "option '$option_name' does not exist"
croak "option '$option_name' does not exist"
unless defined($option);
return $option->value();
@ -372,7 +420,7 @@ sub exists {
my ($self, $group_name, $option_name)= @_;
my $group= $self->group($group_name);
die "group '$group_name' does not exist"
croak "group '$group_name' does not exist"
unless defined($group);
my $option= $group->option($option_name);
@ -412,11 +460,11 @@ sub stringify {
# Save the config to named file
#
sub save {
my ($self, $path)= @_;
my $F= IO::File->new($path, ">")
or die "Could not open '$path': $!";
print $F $self;
undef $F; # Close the file
my ($self, $path)= @_;
my $F= IO::File->new($path, ">")
or croak "Could not open '$path': $!";
print $F $self;
undef $F; # Close the file
}
1;

View File

@ -0,0 +1,621 @@
# -*- cperl -*-
package My::ConfigFactory;
use strict;
use warnings;
use Carp;
use My::Config;
use My::Find;
use File::Basename;
#
# Rules to run first of all
#
my @pre_rules=
(
);
my @share_locations= ("share/mysql", "sql/share", "share");
sub get_basedir {
my ($self, $group)= @_;
my $basedir= $group->if_exist('basedir') ||
$self->{ARGS}->{basedir};
return $basedir;
}
sub fix_charset_dir {
my ($self, $config, $group_name, $group)= @_;
return my_find_dir($self->get_basedir($group),
\@share_locations, "charsets");
}
sub fix_language {
my ($self, $config, $group_name, $group)= @_;
return my_find_dir($self->get_basedir($group),
\@share_locations, "english");
}
sub fix_datadir {
my ($self, $config, $group_name)= @_;
my $vardir= $self->{ARGS}->{vardir};
return "$vardir/$group_name/data";
}
sub fix_pidfile {
my ($self, $config, $group_name, $group)= @_;
my $vardir= $self->{ARGS}->{vardir};
return "$vardir/run/$group_name.pid";
}
sub fix_port {
my ($self, $config, $group_name, $group)= @_;
my $hostname= $group->value('#host');
return $self->{HOSTS}->{$hostname}++;
}
sub fix_host {
my ($self)= @_;
# Get next host from HOSTS array
my @hosts= keys(%{$self->{HOSTS}});;
my $host_no= $self->{NEXT_HOST}++ % @hosts;
return $hosts[$host_no];
}
sub is_unique {
my ($config, $name, $value)= @_;
foreach my $group ( $config->groups() ) {
if ($group->option($name)) {
if ($group->value($name) eq $value){
return 0;
}
}
}
return 1;
}
sub fix_server_id {
my ($self, $config, $group_name, $group)= @_;
#define in the order that mysqlds are listed in my.cnf
my $server_id= $group->if_exist('server-id');
if (defined $server_id){
if (!is_unique($config, 'server-id', $server_id)) {
croak "The server-id($server_id) for '$group_name' is not unique";
}
return $server_id;
}
do {
$server_id= $self->{SERVER_ID}++;
} while(!is_unique($config, 'server-id', $server_id));
#print "$group_name: server_id: $server_id\n";
return $server_id;
}
sub fix_socket {
my ($self, $config, $group_name, $group)= @_;
# Put socket file in tmpdir
my $dir= $group->value('tmpdir');
return "$dir/$group_name.sock";
}
sub fix_log_error {
my ($self, $config, $group_name, $group)= @_;
my $dir= dirname($group->value('datadir'));
return "$dir/mysqld.err";
}
sub fix_log {
my ($self, $config, $group_name, $group)= @_;
my $dir= dirname($group->value('datadir'));
return "$dir/mysqld.log";
}
sub fix_log_slow_queries {
my ($self, $config, $group_name, $group)= @_;
my $dir= dirname($group->value('datadir'));
return "$dir/mysqld-slow.log";
}
sub fix_secure_file_priv {
my ($self)= @_;
my $vardir= $self->{ARGS}->{vardir};
# By default, prevent the started mysqld to access files outside of vardir
return $vardir;
}
sub fix_std_data {
my ($self, $config, $group_name, $group)= @_;
my $basedir= $self->get_basedir($group);
return "$basedir/mysql-test/std_data";
}
sub ssl_supported {
my ($self)= @_;
return $self->{ARGS}->{ssl};
}
sub fix_ssl_ca {
return if !ssl_supported(@_);
my $std_data= fix_std_data(@_);
return "$std_data/cacert.pem"
}
sub fix_ssl_server_cert {
return if !ssl_supported(@_);
my $std_data= fix_std_data(@_);
return "$std_data/server-cert.pem"
}
sub fix_ssl_client_cert {
return if !ssl_supported(@_);
my $std_data= fix_std_data(@_);
return "$std_data/client-cert.pem"
}
sub fix_ssl_server_key {
return if !ssl_supported(@_);
my $std_data= fix_std_data(@_);
return "$std_data/server-key.pem"
}
sub fix_ssl_client_key {
return if !ssl_supported(@_);
my $std_data= fix_std_data(@_);
return "$std_data/client-key.pem"
}
#
# Rules to run for each mysqld in the config
# - will be run in order listed here
#
my @mysqld_rules=
(
{ 'basedir' => sub { return shift->{ARGS}->{basedir}; } },
{ 'tmpdir' => sub { return shift->{ARGS}->{tmpdir}; } },
{ 'character-sets-dir' => \&fix_charset_dir },
{ 'language' => \&fix_language },
{ 'datadir' => \&fix_datadir },
{ 'pid-file' => \&fix_pidfile },
{ '#host' => \&fix_host },
{ 'port' => \&fix_port },
{ 'socket' => \&fix_socket },
{ 'log-error' => \&fix_log_error },
{ 'log' => \&fix_log },
{ 'log-slow-queries' => \&fix_log_slow_queries },
{ '#user' => sub { return shift->{ARGS}->{user} || ""; } },
{ '#password' => sub { return shift->{ARGS}->{password} || ""; } },
{ 'server-id' => \&fix_server_id, },
# By default, prevent the started mysqld to access files outside of vardir
{ 'secure-file-priv' => sub { return shift->{ARGS}->{vardir}; } },
{ 'ssl-ca' => \&fix_ssl_ca },
{ 'ssl-cert' => \&fix_ssl_server_cert },
{ 'ssl-key' => \&fix_ssl_server_key },
);
sub fix_ndb_mgmd_port {
my ($self, $config, $group_name, $group)= @_;
my $hostname= $group->value('HostName');
return $self->{HOSTS}->{$hostname}++;
}
sub fix_cluster_dir {
my ($self, $config, $group_name, $group)= @_;
my $vardir= $self->{ARGS}->{vardir};
my (undef, $process_type, $idx, $suffix)= split(/\./, $group_name);
return "$vardir/mysql_cluster.$suffix/$process_type.$idx";
}
sub fix_cluster_backup_dir {
my ($self, $config, $group_name, $group)= @_;
my $vardir= $self->{ARGS}->{vardir};
my (undef, $process_type, $idx, $suffix)= split(/\./, $group_name);
return "$vardir/mysql_cluster.$suffix/";
}
#
# Rules to run for each ndb_mgmd in the config
# - will be run in order listed here
#
my @ndb_mgmd_rules=
(
{ 'PortNumber' => \&fix_ndb_mgmd_port },
{ 'DataDir' => \&fix_cluster_dir },
);
#
# Rules to run for each ndbd in the config
# - will be run in order listed here
#
my @ndbd_rules=
(
{ 'HostName' => \&fix_host },
{ 'DataDir' => \&fix_cluster_dir },
{ 'BackupDataDir' => \&fix_cluster_backup_dir },
);
#
# Rules to run for each cluster_config section
# - will be run in order listed here
#
my @cluster_config_rules=
(
{ 'ndb_mgmd' => \&fix_host },
{ 'ndbd' => \&fix_host },
{ 'mysqld' => \&fix_host },
{ 'ndbapi' => \&fix_host },
);
#
# Rules to run for [client] section
# - will be run in order listed here
#
my @client_rules=
(
);
#
# Rules to run for [mysqltest] section
# - will be run in order listed here
#
my @mysqltest_rules=
(
{ 'ssl-ca' => \&fix_ssl_ca },
{ 'ssl-cert' => \&fix_ssl_client_cert },
{ 'ssl-key' => \&fix_ssl_client_key },
);
#
# Rules to run for [mysqlbinlog] section
# - will be run in order listed here
#
my @mysqlbinlog_rules=
(
{ 'character-sets-dir' => \&fix_charset_dir },
);
#
# Generate a [client.<suffix>] group to be
# used for connecting to [mysqld.<suffix>]
#
sub post_check_client_group {
my ($self, $config, $client_group_name, $mysqld_group_name)= @_;
# Settings needed for client, copied from its "mysqld"
my %client_needs=
(
port => 'port',
socket => 'socket',
host => '#host',
user => '#user',
password => '#password',
);
my $group_to_copy_from= $config->group($mysqld_group_name);
while (my ($name_to, $name_from)= each( %client_needs )) {
my $option= $group_to_copy_from->option($name_from);
if (! defined $option){
#print $config;
croak "Could not get value for '$name_from'";
}
$config->insert($client_group_name, $name_to, $option->value())
}
}
sub post_check_client_groups {
my ($self, $config)= @_;
my $first_mysqld= $config->first_like('mysqld.');
return unless $first_mysqld;
# Always generate [client] pointing to the first
# [mysqld.<suffix>]
$self->post_check_client_group($config,
'client',
$first_mysqld->name());
# Then generate [client.<suffix>] for each [mysqld.<suffix>]
foreach my $mysqld ( $config->like('mysqld.') ) {
$self->post_check_client_group($config,
'client'.$mysqld->after('mysqld'),
$mysqld->name())
}
}
#
# Generate [embedded] by copying the values
# needed from first [mysqld.<suffix>]
#
sub post_check_embedded_group {
my ($self, $config)= @_;
return unless $self->{ARGS}->{embedded};
my $first_mysqld= $config->first_like('mysqld.') or
croak "Can't run with embedded, config has no mysqld";
my @no_copy =
(
'log-error', # Embedded server writes stderr to mysqltest's log file
);
foreach my $option ( $first_mysqld->options() ) {
# Don't copy options whose name is in "no_copy" list
next if grep ( $option->name() eq $_, @no_copy);
$config->insert('embedded', $option->name(), $option->value())
}
}
sub resolve_at_variable {
my ($self, $config, $group, $option)= @_;
# Split the options value on last .
my @parts= split(/\./, $option->value());
my $option_name= pop(@parts);
my $group_name= join('.', @parts);
$group_name =~ s/^\@//; # Remove at
my $from_group= $config->group($group_name)
or croak "There is no group named '$group_name' that ",
"can be used to resolve '$option_name'";
my $from= $from_group->value($option_name);
$config->insert($group->name(), $option->name(), $from)
}
sub post_fix_resolve_at_variables {
my ($self, $config)= @_;
foreach my $group ( $config->groups() ) {
foreach my $option ( $group->options()) {
next unless defined $option->value();
$self->resolve_at_variable($config, $group, $option)
if ($option->value() =~ /^\@/);
}
}
}
sub post_fix_mysql_cluster_section {
my ($self, $config)= @_;
# Add a [mysl_cluster.<suffix>] section for each
# defined [cluster_config.<suffix>] section
foreach my $group ( $config->like('cluster_config.') )
{
my @urls;
# Generate ndb_connectstring for this cluster
foreach my $ndb_mgmd ( $config->like('cluster_config.ndb_mgmd.')) {
if ($ndb_mgmd->suffix() eq $group->suffix()) {
my $host= $ndb_mgmd->value('HostName');
my $port= $ndb_mgmd->value('PortNumber');
push(@urls, "$host:$port");
}
}
croak "Could not generate valid ndb_connectstring for '$group'"
unless @urls > 0;
my $ndb_connectstring= join(";", @urls);
# Add ndb_connectstring to [mysql_cluster.<suffix>]
$config->insert('mysql_cluster'.$group->suffix(),
'ndb_connectstring', $ndb_connectstring);
# Add ndb_connectstring to each mysqld connected to this
# cluster
foreach my $mysqld ( $config->like('cluster_config.mysqld.')) {
if ($mysqld->suffix() eq $group->suffix()) {
my $after= $mysqld->after('cluster_config.mysqld');
$config->insert("mysqld$after",
'ndb_connectstring', $ndb_connectstring);
}
}
}
}
#
# Rules to run last of all
#
my @post_rules=
(
\&post_check_client_groups,
\&post_fix_mysql_cluster_section,
\&post_fix_resolve_at_variables,
\&post_check_embedded_group,
);
sub run_rules_for_group {
my ($self, $config, $group, @rules)= @_;
foreach my $hash ( @rules ) {
while (my ($option, $rule)= each( %{$hash} )) {
# Only run this rule if the value is not already defined
if (!$config->exists($group->name(), $option)) {
my $value;
if (ref $rule eq "CODE") {
# Call the rule function
$value= &$rule($self, $config, $group->name(),
$config->group($group->name()));
} else {
$value= $rule;
}
if (defined $value) {
$config->insert($group->name(), $option, $value, 1);
}
}
}
}
}
sub run_section_rules {
my ($self, $config, $name, @rules)= @_;
foreach my $group ( $config->like($name) ) {
$self->run_rules_for_group($config, $group, @rules);
}
}
sub run_generate_sections_from_cluster_config {
my ($self, $config)= @_;
my @options= ('ndb_mgmd', 'ndbd',
'mysqld', 'ndbapi');
foreach my $group ( $config->like('cluster_config.') ) {
# Keep track of current index per process type
my %idxes;
map { $idxes{$_}= 1; } @options;
foreach my $option_name ( @options ) {
my $value= $group->value($option_name);
my @hosts= split(/,/, $value, -1); # -1 => return also empty strings
# Add at least one host
push(@hosts, undef) unless scalar(@hosts);
# Assign hosts unless already fixed
@hosts= map { $self->fix_host() unless $_; } @hosts;
# Write the hosts value back
$group->insert($option_name, join(",", @hosts));
# Generate sections for each host
foreach my $host ( @hosts ){
my $idx= $idxes{$option_name}++;
my $suffix= $group->suffix();
# Generate a section for ndb_mgmd to read
$config->insert("cluster_config.$option_name.$idx$suffix",
"HostName", $host);
if ($option_name eq 'mysqld'){
my $datadir=
$self->fix_cluster_dir($config,
"cluster_config.mysqld.$idx$suffix",
$group);
$config->insert("mysqld.$idx$suffix",
'datadir', "$datadir/data");
}
}
}
}
}
sub new_config {
my ($class, $args)= @_;
my @required_args= ('basedir', 'baseport', 'vardir', 'template_path');
foreach my $required ( @required_args ) {
croak "you must pass '$required'" unless defined $args->{$required};
}
# Fill in hosts/port hash
my $hosts= {};
my $baseport= $args->{baseport};
$args->{hosts}= [ 'localhost' ] unless exists($args->{hosts});
foreach my $host ( @{$args->{hosts}} ) {
$hosts->{$host}= $baseport;
}
# Open the config template
my $config= My::Config->new($args->{'template_path'});
my $extra_template_path= $args->{'extra_template_path'};
if ($extra_template_path){
$config->append(My::Config->new($extra_template_path));
}
my $self= bless {
CONFIG => $config,
ARGS => $args,
HOSTS => $hosts,
NEXT_HOST => 0,
SERVER_ID => 1,
}, $class;
{
# Run pre rules
foreach my $rule ( @pre_rules ) {
&$rule($self, $config);
}
}
$self->run_section_rules($config,
'cluster_config.',
@cluster_config_rules);
$self->run_generate_sections_from_cluster_config($config);
$self->run_section_rules($config,
'cluster_config.ndb_mgmd.',
@ndb_mgmd_rules);
$self->run_section_rules($config,
'cluster_config.ndbd',
@ndbd_rules);
$self->run_section_rules($config,
'mysqld.',
@mysqld_rules);
# [mysqlbinlog] need additional settings
$self->run_rules_for_group($config,
$config->insert('mysqlbinlog'),
@mysqlbinlog_rules);
# Additional rules required for [client]
$self->run_rules_for_group($config,
$config->insert('client'),
@client_rules);
# Additional rules required for [mysqltest]
$self->run_rules_for_group($config,
$config->insert('mysqltest'),
@mysqltest_rules);
{
# Run post rules
foreach my $rule ( @post_rules ) {
&$rule($self, $config);
}
}
return $config;
}
1;

View File

@ -0,0 +1,83 @@
# -*- cperl -*-
package My::File::Path;
use strict;
#
# File::Path::rmtree has a problem with deleting files
# and directories where it hasn't got read permission
#
# Patch this by installing a 'rmtree' function in local
# scope that first chmod all files to 0777 before calling
# the original rmtree function.
#
# This is almost gone in version 1.08 of File::Path -
# but unfortunately some hosts still suffers
# from this also in 1.08
#
use Exporter;
use base "Exporter";
our @EXPORT= qw / rmtree mkpath copytree /;
use File::Find;
use File::Path;
use File::Copy;
use Carp;
no warnings 'redefine';
sub rmtree {
my ($dir)= @_;
#
# chmod all files to 0777 before calling rmtree
#
find( {
no_chdir => 1,
wanted => sub {
chmod(0777, $_)
or warn("couldn't chmod(0777, $_): $!");
}
},
$dir
);
# Call rmtree from File::Path
goto &File::Path::rmtree;
};
sub mkpath {
goto &File::Path::mkpath;
};
sub copytree {
my ($from_dir, $to_dir) = @_;
die "Usage: copytree(<fromdir>, <todir>" unless @_ == 2;
mkpath("$to_dir");
opendir(DIR, "$from_dir")
or croak("Can't find $from_dir$!");
for(readdir(DIR)) {
next if "$_" eq "." or "$_" eq "..";
# Skip SCCS/ directories
next if "$_" eq "SCCS";
if ( -d "$from_dir/$_" )
{
copytree("$from_dir/$_", "$to_dir/$_");
next;
}
copy("$from_dir/$_", "$to_dir/$_");
}
closedir(DIR);
}
1;

190
mysql-test/lib/My/Find.pm Normal file
View File

@ -0,0 +1,190 @@
# -*- cperl -*-
# Copyright (C) 2004-2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
package My::Find;
#
# Utility functions to find files in a MySQL source or bindist
#
use strict;
use Carp;
use My::Platform;
use base qw(Exporter);
our @EXPORT= qw(my_find_bin my_find_dir);
our $vs_config_dir;
my $bin_extension= ".exe" if IS_WINDOWS;
#
# my_find_bin - find an executable with "name_1...name_n" in
# paths "path_1...path_n" and return the full path
#
# Example:
# my $mysqld_exe= my_find_bin($basedir.
# ["sql", "bin"],
# ["mysqld", "mysqld-debug"]);
# my $mysql_exe= my_find_bin($basedir,
# ["client", "bin"],
# "mysql");
#
# NOTE: The function honours MTR_VS_CONFIG environment variable
#
#
sub my_find_bin {
my ($base, $paths, $names)= @_;
croak "usage: my_find_bin(<base>, <paths>, <names>)"
unless @_ == 3;
# -------------------------------------------------------
# Find and return the first executable
# -------------------------------------------------------
foreach my $path (my_find_paths($base, $paths, $names, $bin_extension)) {
return $path if ( -x $path or (IS_WINDOWS and -f $path) );
}
find_error($base, $paths, $names);
}
#
# my_find_dir - find the first existing directory in one of
# the given paths
#
# Example:
# my $charset_set= my_find_dir($basedir,
# ["mysql/share","sql/share", "share"],
# ["charset"]);
# or
# my $charset_set= my_find_dir($basedir,
# ['client_release', 'client_debug',
# 'client', 'bin']);
#
# NOTE: The function honours MTR_VS_CONFIG environment variable
#
#
sub my_find_dir {
my ($base, $paths, $dirs)= @_;
croak "usage: my_find_dir(<base>, <paths>[, <dirs>])"
unless (@_ == 3 or @_ == 2);
# -------------------------------------------------------
# Find and return the first directory
# -------------------------------------------------------
foreach my $path (my_find_paths($base, $paths, $dirs)) {
return $path if ( -d $path );
}
find_error($base, $paths, $dirs);
}
sub my_find_paths {
my ($base, $paths, $names, $extension)= @_;
# Convert the arguments into two normal arrays to ease
# further mappings
my (@names, @paths);
push(@names, ref $names eq "ARRAY" ? @$names : $names);
push(@paths, ref $paths eq "ARRAY" ? @$paths : $paths);
#print "base: $base\n";
#print "names: @names\n";
#print "paths: @paths\n";
# User can select to look in a special build dir
# which is a subdirectory of any of the paths
my @extra_dirs;
my $build_dir= $vs_config_dir || $ENV{MTR_VS_CONFIG} || $ENV{MTR_BUILD_DIR};
push(@extra_dirs, $build_dir) if defined $build_dir;
if (defined $extension){
# Append extension to names, if name does not already have extension
map { $_.=$extension unless /\.(.*)+$/ } @names;
}
# -------------------------------------------------------
# Windows specific
# -------------------------------------------------------
if (IS_WINDOWS) {
# Add the default extra build dirs unless a specific one has
# already been selected
push(@extra_dirs,
("release",
"relwithdebinfo",
"debug")) if @extra_dirs == 0;
}
#print "extra_build_dir: @extra_dirs\n";
# -------------------------------------------------------
# Build cross product of "paths * extra_build_dirs"
# -------------------------------------------------------
push(@paths, map { my $path= $_;
map { "$path/$_" } @extra_dirs
} @paths);
#print "paths: @paths\n";
# -------------------------------------------------------
# Build cross product of "paths * names"
# -------------------------------------------------------
@paths= map { my $path= $_;
map { "$path/$_" } @names
} @paths;
#print "paths: @paths\n";
# -------------------------------------------------------
# Prepend base to all paths
# -------------------------------------------------------
@paths= map { "$base/$_" } @paths;
#print "paths: @paths\n";
# -------------------------------------------------------
# Return the list of paths
# -------------------------------------------------------
return @paths;
}
sub commify {
return
(@_ == 0) ? '' :
(@_ == 1) ? $_[0] :
(@_ == 2) ? join(" or ", @_) :
join(", ", @_[0..($#_-1)], "or $_[-1]");
}
sub fnuttify {
return map('\''.$_.'\'', @_);
}
sub find_error {
my ($base, $paths, $names)= @_;
my (@names, @paths);
push(@names, ref $names eq "ARRAY" ? @$names : $names);
push(@paths, ref $paths eq "ARRAY" ? @$paths : $paths);
croak "** ERROR: Could not find ",
commify(fnuttify(@names)), " in ",
commify(fnuttify(my_find_paths($base, $paths, $names))), "\n";
}
1;

View File

@ -0,0 +1,196 @@
# -*- cperl -*-
# Copyright (C) 2004-2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
package My::Options;
#
# Utility functions to work with list of options
#
use strict;
sub same($$) {
my $l1= shift;
my $l2= shift;
return compare($l1,$l2) == 0;
}
sub compare ($$) {
my $l1= shift;
my $l2= shift;
my @l1= @$l1;
my @l2= @$l2;
return -1 if @l1 < @l2;
return 1 if @l1 > @l2;
while ( @l1 ) # Same length
{
my $e1= shift @l1;
my $e2= shift @l2;
my $cmp= ($e1 cmp $e2);
return $cmp if $cmp != 0;
}
return 0; # They are the same
}
sub _split_option {
my ($option)= @_;
if ($option=~ /^--(.*)=(.*)$/){
return ($1, $2);
}
elsif ($option=~ /^--(.*)$/){
return ($1, undef)
}
elsif ($option=~ /^(.*)=(.*)$/){
return ($1, $2)
}
elsif ($option=~ /^-O$/){
return (undef, undef);
}
die "Unknown option format '$option'";
}
sub _build_option {
my ($name, $value)= @_;
if ($name =~ /^O, /){
return "-".$name."=".$value;
}
elsif ($value){
return "--".$name."=".$value;
}
return "--".$name;
}
#
# Compare two list of options and return what would need
# to be done to get the server running with the new settings
#
sub diff {
my ($from_opts, $to_opts)= @_;
my %from;
foreach my $from (@$from_opts)
{
my ($opt, $value)= _split_option($from);
next unless defined($opt);
$from{$opt}= $value;
}
#print "from: ", %from, "\n";
my %to;
foreach my $to (@$to_opts)
{
my ($opt, $value)= _split_option($to);
next unless defined($opt);
$to{$opt}= $value;
}
#print "to: ", %to, "\n";
# Remove the ones that are in both lists
foreach my $name (keys %from){
if (exists $to{$name} and $to{$name} eq $from{$name}){
#print "removing '$name' from both lists\n";
delete $to{$name};
delete $from{$name};
}
}
#print "from: ", %from, "\n";
#print "to: ", %to, "\n";
# Add all keys in "to" to result
my @result;
foreach my $name (keys %to){
push(@result, _build_option($name, $to{$name}));
}
# Add all keys in "from" that are not in "to"
# to result as "set to default"
foreach my $name (keys %from){
if (not exists $to{$name}) {
push(@result, _build_option($name, "default"));
}
}
return @result;
}
sub is_set {
my ($opts, $set_opts)= @_;
foreach my $opt (@$opts){
my ($opt_name1, $value1)= _split_option($opt);
foreach my $set_opt (@$set_opts){
my ($opt_name2, $value2)= _split_option($set_opt);
if ($opt_name1 eq $opt_name2){
# Option already set
return 1;
}
}
}
return 0;
}
sub toSQL {
my (@options)= @_;
my @sql;
foreach my $option (@options) {
my ($name, $value)= _split_option($option);
#print "name: $name\n";
#print "value: $value\n";
if ($name =~ /^O, (.*)/){
push(@sql, "SET GLOBAL $1=$value");
}
elsif ($name =~ /^set-variable=(.*)/){
push(@sql, "SET GLOBAL $1=$value");
}
else {
my $sql_name= $name;
$sql_name=~ s/-/_/g;
push(@sql, "SET GLOBAL $sql_name=$value");
}
}
return join("; ", @sql);
}
sub toStr {
my $name= shift;
return "$name: ",
"['", join("', '", @_), "']\n";
}
1;

View File

@ -0,0 +1,95 @@
# -*- cperl -*-
# Copyright (C) 2004-2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
package My::Platform;
use strict;
use base qw(Exporter);
our @EXPORT= qw(IS_CYGWIN IS_WINDOWS IS_WIN32PERL
native_path posix_path mixed_path);
BEGIN {
if ($^O eq "cygwin") {
# Make sure cygpath works
if ((system("cygpath > /dev/null 2>&1") >> 8) != 1){
die "Could not execute 'cygpath': $!";
}
eval 'sub IS_CYGWIN { 1 }';
}
else {
eval 'sub IS_CYGWIN { 0 }';
}
if ($^O eq "MSWin32") {
eval 'sub IS_WIN32PERL { 1 }';
}
else {
eval 'sub IS_WIN32PERL { 0 }';
}
}
BEGIN {
if (IS_CYGWIN or IS_WIN32PERL) {
eval 'sub IS_WINDOWS { 1 }';
}
else {
eval 'sub IS_WINDOWS { 0 }';
}
}
#
# native_path
# Convert from path format used by perl to the underlying
# operating systems format
#
# NOTE
# Used when running windows binaries (that expect windows paths)
# in cygwin perl (that uses unix paths)
#
sub mixed_path {
my ($path)= @_;
if (IS_CYGWIN){
return unless defined $path;
$path= `cygpath -m $path`;
chomp $path;
}
return $path;
}
sub native_path {
my ($path)= @_;
$path=~ s/\//\\/g
if (IS_CYGWIN or IS_WIN32PERL);
return $path;
}
sub posix_path {
my ($path)= @_;
if (IS_CYGWIN){
return unless defined $path;
$path= `cygpath $path`;
chomp $path;
}
return $path;
}
1;

View File

@ -0,0 +1,512 @@
# -*- cperl -*-
# Copyright (C) 2004-2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
package My::SafeProcess;
#
# Class that encapsulates process creation, monitoring and cleanup
#
# Spawns a monitor process which spawns a new process locally or
# remote using subclasses My::Process::Local or My::Process::Remote etc.
#
# The monitor process runs a simple event loop more or less just
# waiting for a reason to zap the process it monitors. Thus the user
# of this class does not need to care about process cleanup, it's
# handled automatically.
#
# The monitor process wait for:
# - the parent process to close the pipe, in that case it
# will zap the "monitored process" and exit
# - the "monitored process" to exit, in which case it will exit
# itself with same exit code as the "monitored process"
# - the parent process to send the "shutdown" signal in wich case
# monitor will kill the "monitored process" hard and exit
#
#
# When used it will look something like this:
# $> ps
# [script.pl]
# - [monitor for `mysqld`]
# - [mysqld]
# - [monitor for `mysqld`]
# - [mysqld]
# - [monitor for `mysqld`]
# - [mysqld]
#
#
use strict;
use POSIX qw(WNOHANG);
use My::SafeProcess::Base;
use base 'My::SafeProcess::Base';
use My::Find;
use My::Platform;
my %running;
END {
# Kill any children still running
for my $proc (values %running){
if ( $proc->is_child($$) ){
print "Killing: $proc\n";
$proc->kill();
}
}
}
sub is_child {
my ($self, $parent_pid)= @_;
die "usage: \$safe_proc->is_child()" unless (@_ == 2 and ref $self);
return ($self->{PARENT} == $parent_pid);
}
# Find the safe process binary or script
my @safe_process_cmd;
my $safe_kill;
if (IS_WIN32PERL or IS_CYGWIN){
# Use my_safe_process.exe
my $exe= my_find_bin(".", ["lib/My/SafeProcess", "My/SafeProcess"],
"my_safe_process");
die "Could not find my_safe_process" unless $exe;
push(@safe_process_cmd, $exe);
# Use my_safe_kill.exe
$safe_kill= my_find_bin(".", "lib/My/SafeProcess", "my_safe_kill");
die "Could not find my_safe_kill" unless $safe_kill;
}
else
{
my $use_safe_process_binary= 1;
if ($use_safe_process_binary) {
# Use my_safe_process
my $exe= my_find_bin(".", ["lib/My/SafeProcess", "My/SafeProcess"],
"my_safe_process");
die "Could not find my_safe_process" unless $exe;
push(@safe_process_cmd, $exe);
}
else
{
# Use safe_process.pl
my $script= "lib/My/SafeProcess/safe_process.pl";
$script= "../$script" unless -f $script;
die "Could not find safe_process.pl" unless -f $script;
# Call $script with Perl interpreter
push(@safe_process_cmd, $^X, $script);
}
}
sub new {
my $class= shift;
my %opts=
(
verbose => 0,
@_
);
my $path = delete($opts{'path'}) or die "path required";
my $args = delete($opts{'args'}) or die "args required";
my $input = delete($opts{'input'});
my $output = delete($opts{'output'});
my $error = delete($opts{'error'});
my $verbose = delete($opts{'verbose'});
my $host = delete($opts{'host'});
my $shutdown = delete($opts{'shutdown'});
# if (defined $host) {
# $safe_script= "lib/My/SafeProcess/safe_process_cpcd.pl";
# }
if (IS_CYGWIN){
$path= mixed_path($path);
$input= mixed_path($input);
$output= mixed_path($output);
$error= mixed_path($error);
}
my @safe_args;
my ($safe_path, $safe_script)= @safe_process_cmd;
push(@safe_args, $safe_script) if defined $safe_script;
push(@safe_args, "--verbose") if $verbose > 0;
# Point the safe_process at the right parent if running on cygwin
push(@safe_args, "--parent-pid=".Cygwin::pid_to_winpid($$)) if IS_CYGWIN;
push(@safe_args, "--");
push(@safe_args, $path); # The program safe_process should execute
push(@safe_args, @$$args);
print "### safe_path: ", $safe_path, " ", join(" ", @safe_args), "\n"
if $verbose > 1;
my ($pid, $winpid)= create_process(
path => $safe_path,
input => $input,
output => $output,
error => $error,
append => $opts{append},
args => \@safe_args,
);
my $name = delete($opts{'name'}) || "SafeProcess$pid";
my $proc= bless
({
SAFE_PID => $pid,
SAFE_WINPID => $winpid,
SAFE_NAME => $name,
SAFE_SHUTDOWN => $shutdown,
PARENT => $$,
}, $class);
# Put the new process in list of running
$running{$pid}= $proc;
return $proc;
}
sub run {
my $proc= new(@_);
$proc->wait_one();
return $proc->exit_status();
}
#
# Start a process that returns after "duration" seconds
# or when it's parent process does not exist anymore
#
sub timer {
my $class= shift;
my $duration= shift or die "duration required";
my $parent_pid= $$;
my $pid= My::SafeProcess::Base::_safe_fork();
if ($pid){
# Parent
my $proc= bless
({
SAFE_PID => $pid,
SAFE_NAME => "timer",
PARENT => $$,
}, $class);
# Put the new process in list of running
$running{$pid}= $proc;
return $proc;
}
# Child, install signal handlers and sleep for "duration"
$SIG{INT}= 'DEFAULT';
$SIG{TERM}= sub {
#print STDERR "timer $$: woken up, exiting!\n";
exit(0);
};
$0= "safe_timer($duration)";
my $count_down= $duration;
while($count_down--){
# Check that parent is still alive
if (kill(0, $parent_pid) == 0){
#print STDERR "timer $$: parent gone, exiting!\n";
exit(0);
}
sleep(1);
}
print STDERR "timer $$: expired after $duration seconds\n";
exit(0);
}
#
# Shutdown process nicely, and wait for shutdown_timeout seconds
# If processes hasn't shutdown, kill them hard and wait for return
#
sub shutdown {
my $shutdown_timeout= shift;
my @processes= @_;
return if (@processes == 0);
#print "shutdown: @processes\n";
# Call shutdown function if process has one, else
# use kill
foreach my $proc (@processes){
my $shutdown= $proc->{SAFE_SHUTDOWN};
if ($shutdown_timeout > 0 and defined $shutdown){
$shutdown->();
}
else {
$proc->start_kill();
}
}
my @kill_processes= ();
# Wait for shutdown_timeout for processes to exit
foreach my $proc (@processes){
my $ret= $proc->wait_one($shutdown_timeout);
if ($ret != 0) {
push(@kill_processes, $proc);
}
# Only wait for the first process with shutdown timeout
$shutdown_timeout= 0;
}
# Return if all servers has exited
return if (@kill_processes == 0);
foreach my $proc (@kill_processes){
$proc->start_kill();
}
foreach my $proc (@kill_processes){
$proc->wait_one();
}
return;
}
#
# Tell the process to die as fast as possible
#
sub start_kill {
my ($self)= @_;
die "usage: \$safe_proc->start_kill()" unless (@_ == 1 and ref $self);
#print "start_kill $self\n";
if (defined $safe_kill and $self->{SAFE_WINPID}){
# Use my_safe_kill to tell my_safe_process
# it's time to kill it's child and return
my $pid= $self->{SAFE_WINPID};
my $ret= system($safe_kill, $pid);
#print STDERR "start_kill, safe_killed $pid, ret: $ret\n";
} else {
my $pid= $self->{SAFE_PID};
die "Can't kill not started process" unless defined $pid;
my $ret= kill(15, $pid);
#print STDERR "start_kill, sent signal 15 to $pid, ret: $ret\n";
}
return 1;
}
#
# Kill the process as fast as possible
# and wait for it to return
#
sub kill {
my ($self)= @_;
die "usage: \$safe_proc->kill()" unless (@_ == 1 and ref $self);
$self->start_kill();
$self->wait_one();
return 1;
}
sub _collect {
my ($self)= @_;
#print "_collect\n";
$self->{EXIT_STATUS}= $?;
# Take the process out of running list
my $pid= $self->{SAFE_PID};
die unless delete($running{$pid});
}
# Wait for process to exit
# optionally with a timeout
#
# timeout
# undef -> wait blocking infinitely
# 0 -> just poll with WNOHANG
# >0 -> wait blocking for max timeout seconds
#
# RETURN VALUES
# 0 Not running
# 1 Still running
#
sub wait_one {
my ($self, $timeout)= @_;
die "usage: \$safe_proc->wait_one([timeout])" unless ref $self;
#print "wait_one $self, $timeout\n";
if ( ! defined($self->{SAFE_PID}) ) {
# No pid => not running
return 0;
}
if ( defined $self->{EXIT_STATUS} ) {
# Exit status already set => not running
return 0;
}
my $pid= $self->{SAFE_PID};
my $use_alarm;
my $blocking;
if (defined $timeout)
{
if ($timeout == 0)
{
# 0 -> just poll with WNOHANG
$blocking= 0;
$use_alarm= 0;
}
else
{
# >0 -> wait blocking for max timeout seconds
$blocking= 1;
$use_alarm= 1;
}
}
else
{
# undef -> wait blocking infinitely
$blocking= 1;
$use_alarm= 0;
}
my $retpid;
eval
{
# alarm should break the wait
local $SIG{ALRM}= sub { die "waitpid timeout"; };
alarm($timeout) if $use_alarm;
$retpid= waitpid($pid, $blocking ? 0 : &WNOHANG);
alarm(0) if $use_alarm;
};
if ($@)
{
die "Got unexpected: $@" if ($@ !~ /waitpid timeout/);
if (!defined $retpid) {
# Got timeout
return 1;
}
# Got pid _and_ alarm, continue
}
if ( $retpid == 0 ) {
# 0 => still running
return 1;
}
if ( not $blocking and $retpid == -1 ) {
# still running
return 1;
}
warn "wait_one: expected pid $pid but got $retpid"
unless( $retpid == $pid );
$self->_collect();
return 0;
}
#
# Wait for any process to exit
#
# Returns a reference to the SafeProcess that
# exited or undefined
#
sub wait_any {
my $ret_pid;
if (IS_WIN32PERL) {
# Can't wait for -1 => use a polling loop
do {
Win32::Sleep(10); # 10 milli seconds
foreach my $pid (keys %running){
$ret_pid= waitpid($pid, &WNOHANG);
last if $pid == $ret_pid;
}
} while ($ret_pid == 0);
# Special processig of return code
# since negative pids are valid
if ($ret_pid == 0 or $ret_pid == -1) {
print STDERR "wait_any, got invalid pid: $ret_pid\n";
return undef;
}
}
else
{
$ret_pid= waitpid(-1, 0);
if ($ret_pid <= 0){
# No more processes to wait for
print STDERR "wait_any, got invalid pid: $ret_pid\n";
return undef;
}
}
# Look it up in "running" table
my $proc= $running{$ret_pid};
unless (defined $proc){
print STDERR "Could not find pid in running list\n";
print STDERR "running: ". join(", ", keys(%running)). "\n";
return undef;
}
$proc->_collect;
return $proc;
}
#
# Overload string operator
# and fallback to default functions if no
# overloaded function is found
#
use overload
'""' => \&self2str,
fallback => 1;
#
# Return the process as a nicely formatted string
#
sub self2str {
my ($self)= @_;
my $pid= $self->{SAFE_PID};
my $winpid= $self->{SAFE_WINPID};
my $name= $self->{SAFE_NAME};
my $exit_status= $self->{EXIT_STATUS};
my $str= "[$name - pid: $pid";
$str.= ", winpid: $winpid" if defined $winpid;
$str.= ", exit: $exit_status" if defined $exit_status;
$str.= "]";
}
1;

View File

@ -0,0 +1,236 @@
# -*- cperl -*-
# Copyright (C) 2004-2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# This is a library file used by the Perl version of mysql-test-run,
# and is part of the translation of the Bourne shell script with the
# same name.
use strict;
package My::SafeProcess::Base;
#
# Utility functions for Process management
#
use Carp;
use IO::Pipe;
use base qw(Exporter);
our @EXPORT= qw(create_process);
sub winpid {
my ($pid)= @_;
return undef unless $^O eq "cygwin";
# The child get a new winpid when the exec takes
# place, wait for that to happen
my $winpid;
my $delay= 0;
do
{
# Yield to the child
select(undef, undef, undef, $delay);
# Increase the delay slightly for each loop
$delay += 0.000001;
$winpid= Cygwin::pid_to_winpid($pid);
} until ($winpid != $pid);
return $winpid;
}
#
# safe_fork
# Retry a couple of times if fork returns EAGAIN
#
sub _safe_fork {
my $retries= 5;
my $pid;
FORK:
{
$pid= fork;
if ( not defined($pid)) {
croak("fork failed after: $!") if (!$retries--);
warn("fork failed sleep 1 second and redo: $!");
sleep(1);
redo FORK;
}
}
return $pid;
};
#
# Decode exit status
#
sub exit_status {
my $self= shift;
my $raw= $self->{EXIT_STATUS};
croak("Can't call exit_status before process has died")
unless defined $raw;
if ($raw & 127)
{
# Killed by signal
my $signal_num= $raw & 127;
my $dumped_core= $raw & 128;
return 1; # Return error code
}
else
{
# Normal process exit
return $raw >> 8;
};
}
#
# Create a new process
# Return pid of the new process
#
sub create_process {
my %opts=
(
@_
);
my $path = delete($opts{'path'}) or die "path required";
my $args = delete($opts{'args'}) or die "args required";
my $input = delete($opts{'input'});
my $output = delete($opts{'output'});
my $error = delete($opts{'error'});
my $open_mode= $opts{append} ? ">>" : ">";
if ($^O eq "MSWin32"){
#printf STDERR "stdin %d, stdout %d, stderr %d\n",
# fileno STDIN, fileno STDOUT, fileno STDERR;
# input output redirect
my ($oldin, $oldout, $olderr);
open $oldin, '<&', \*STDIN or die "Failed to save old stdin: $!";
open $oldout, '>&', \*STDOUT or die "Failed to save old stdout: $!";
open $olderr, '>&', \*STDERR or die "Failed to save old stderr: $!";
if ( $input ) {
if ( ! open(STDIN, "<", $input) ) {
croak("can't redirect STDIN to '$input': $!");
}
}
if ( $output ) {
if ( ! open(STDOUT, $open_mode, $output) ) {
croak("can't redirect STDOUT to '$output': $!");
}
}
if ( $error ) {
if ( $output eq $error ) {
if ( ! open(STDERR, ">&STDOUT") ) {
croak("can't dup STDOUT: $!");
}
}
elsif ( ! open(STDERR, $open_mode, $error) ) {
croak("can't redirect STDERR to '$error': $!");
}
}
# Magic use of 'system(1, @args)' to spawn a process
# and get a proper Win32 pid
unshift (@$args, $path);
my $pid= system(1, @$args);
if ( $pid == 0 ){
print $olderr "create_process failed: $^E\n";
die "create_process failed: $^E";
}
# Retore IO redirects
open STDERR, '>&', $olderr
or croak("unable to reestablish STDERR");
open STDOUT, '>&', $oldout
or croak("unable to reestablish STDOUT");
open STDIN, '<&', $oldin
or croak("unable to reestablish STDIN");
#printf STDERR "stdin %d, stdout %d, stderr %d\n",
# fileno STDIN, fileno STDOUT, fileno STDERR;
return wantarray ? ($pid, $pid) : $pid;
}
local $SIG{PIPE}= sub { print STDERR "Got signal $@\n"; };
my $pipe= IO::Pipe->new();
my $pid= _safe_fork();
if ($pid){
# Parent
$pipe->reader();
my $line= <$pipe>; # Wait for child to say it's ready
return wantarray ? ($pid, winpid($pid)) : $pid;
}
$SIG{INT}= 'DEFAULT';
# Make this process it's own process group to be able to kill
# it and any childs(that hasn't changed group themself)
setpgrp(0,0) if $opts{setpgrp};
if ( $output and !open(STDOUT, $open_mode, $output) ) {
croak("can't redirect STDOUT to '$output': $!");
}
if ( $error ) {
if ( defined $output and $output eq $error ) {
if ( ! open(STDERR, ">&STDOUT") ) {
croak("can't dup STDOUT: $!");
}
}
elsif ( ! open(STDERR, $open_mode, $error) ) {
croak("can't redirect STDERR to '$error': $!");
}
}
if ( $input ) {
if ( ! open(STDIN, "<", $input) ) {
croak("can't redirect STDIN to '$input': $!");
}
}
# Tell parent to continue
$pipe->writer();
print $pipe "ready\n";
if ( !exec($path, @$args) ){
croak("Failed to exec '$path': $!");
}
croak("Should never come here");
}
1;

View File

@ -0,0 +1,17 @@
# Copyright (C) 2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
ADD_EXECUTABLE(my_safe_process safe_process_win.cc)
ADD_EXECUTABLE(my_safe_kill safe_kill_win.cc)

View File

@ -0,0 +1,21 @@
# Copyright (C) 2000-2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
bin_PROGRAMS = my_safe_process
my_safe_process_SOURCES = safe_process.cc
# Don't update the files from bitkeeper
%::SCCS/s.%

View File

@ -0,0 +1,56 @@
/* Copyright (C) 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Utility program used to signal a safe_process it's time to shutdown
Usage:
safe_kill <pid>
*/
#include <windows.h>
#include <stdio.h>
int main(int argc, const char** argv )
{
DWORD pid= -1;
HANDLE shutdown_event;
char safe_process_name[32]= {0};
if (argc != 2) {
fprintf(stderr, "safe_kill <pid>\n");
exit(2);
}
pid= atoi(argv[1]);
_snprintf(safe_process_name, sizeof(safe_process_name), "safe_process[%d]", pid);
/* Open the event to signal */
if ((shutdown_event=
OpenEvent(EVENT_MODIFY_STATE, FALSE, safe_process_name)) == NULL){
fprintf(stderr, "Failed to open shutdown_event\n");
exit(1);
}
if(SetEvent(shutdown_event) == 0) {
fprintf(stderr, "Failed to signal shutdown_event\n");
CloseHandle(shutdown_event);
exit(1);
}
CloseHandle(shutdown_event);
exit(0);
}

View File

@ -0,0 +1,267 @@
/* Copyright (C) 2008 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Utility program that encapsulates process creation, monitoring
and bulletproof process cleanup
Usage:
safe_process [options to safe_process] -- progname arg1 ... argn
To safeguard mysqld you would invoke safe_process with a few options
for safe_process itself followed by a double dash to indicate start
of the command line for the program you really want to start
$> safe_process --output=output.log -- mysqld --datadir=var/data1 ...
This would redirect output to output.log and then start mysqld,
once it has done that it will continue to monitor the child as well
as the parent.
The safe_process then checks the follwing things:
1. Child exits, propagate the childs return code to the parent
by exiting with the same return code as the child.
2. Parent dies, immediately kill the child and exit, thus the
parent does not need to properly cleanup any child, it is handled
automatically.
3. Signal's recieced by the process will trigger same action as 2)
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
int verbose= 0;
int terminated= 0;
pid_t child_pid= -1;
char safe_process_name[32]= {0};
static void message(const char* fmt, ...)
{
if (!verbose)
return;
va_list args;
fprintf(stderr, "%s: ", safe_process_name);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
fflush(stderr);
}
static void die(const char* fmt, ...)
{
va_list args;
fprintf(stderr, "%s: FATAL ERROR, ", safe_process_name);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
if (int last_err= errno)
fprintf(stderr, "error: %d, %s\n", last_err, strerror(last_err));
exit(1);
}
static void kill_child (void)
{
int exit_code= 1;
int status= 0;
message("Killing child: %d", child_pid);
// Terminate whole process group
kill(-child_pid, SIGKILL);
pid_t ret_pid= waitpid(child_pid, &status, 0);
if (ret_pid == child_pid)
{
if (WIFEXITED(status))
{
// Process has exited, collect return status
exit_code= WEXITSTATUS(status);
message("Child exit: %d", exit_code);
// Exit with exit status of the child
exit(exit_code);
}
if (WIFSIGNALED(status))
message("Child killed by signal: %d", WTERMSIG(status));
exit(exit_code);
}
exit(exit_code);
}
static void handle_signal (int sig)
{
message("Got signal %d, child_pid: %d", sig, child_pid);
terminated= 1;
// Ignore further signals
signal(SIGTERM, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
if (child_pid > 0)
kill_child();
// Continune execution, allow the child to be started and
// finally terminated by monitor loop
}
int main(int argc, char* const argv[] )
{
char* const* child_argv= 0;
pid_t own_pid= getpid();
pid_t parent_pid= getppid();
/* Install signal handlers */
signal(SIGTERM, handle_signal);
signal(SIGINT, handle_signal);
signal(SIGCHLD, handle_signal);
sprintf(safe_process_name, "safe_process[%d]", own_pid);
message("Started");
/* Parse arguments */
for (int i= 1; i < argc; i++) {
const char* arg= argv[i];
if (strcmp(arg, "--") == 0 && strlen(arg) == 2) {
/* Got the "--" delimiter */
if (i >= argc)
die("No real args -> nothing to do");
child_argv= &argv[i+1];
break;
} else {
if ( strcmp(arg, "--verbose") == 0 )
verbose++;
else if ( strncmp(arg, "--parent-pid", 10) == 0 )
{
/* Override parent_pid with a value provided by user */
const char* start;
if ((start= strstr(arg, "=")) == NULL)
die("Could not find start of option value in '%s'", arg);
start++; /* Step past = */
if ((parent_pid= atoi(start)) == 0)
die("Invalid value '%s' passed to --parent-id", start);
}
else
die("Unknown option: %s", arg);
}
}
if (!child_argv || *child_argv == 0)
die("nothing to do");
message("parent_pid: %d", parent_pid);
if (parent_pid == own_pid)
die("parent_pid is equal to own pid!");
char buf;
int pfd[2];
if (pipe(pfd) == -1)
die("Failed to create pipe");
/* Create the child process */
while((child_pid= fork()) == -1)
{
message("fork failed");
sleep(1);
}
if (child_pid == 0)
{
close(pfd[0]); // Close unused read end
// Use default signal handlers in child
signal(SIGTERM, SIG_DFL);
signal(SIGINT, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
// Make this process it's own process group to be able to kill
// it and any childs(that hasn't changed group themself)
setpgid(0, 0);
// Signal that child is ready
buf= 37;
write(pfd[1], &buf, 1);
// Close write end
close(pfd[1]);
if (execvp(child_argv[0], child_argv) < 0)
die("Failed to exec child");
}
close(pfd[1]); // Close unused write end
// Wait for child to signal it's ready
read(pfd[0], &buf, 1);
if(buf != 37)
die("Didn't get 37 from pipe");
close(pfd[0]); // Close read end
/* Monitor loop */
message("Started child %d, terminated: %d", child_pid, terminated);
while(!terminated)
{
// Check if parent is still alive
if (kill(parent_pid, 0) != 0){
message("Parent is not alive anymore");
break;
}
// Check if child has exited, normally this wil be
// detected immediately with SIGCHLD handler
int status= 0;
pid_t ret_pid= waitpid(child_pid, &status, WNOHANG);
if (ret_pid == child_pid)
{
int ret_code= 2;
if (WIFEXITED(status))
{
// Process has exited, collect return status
int ret_code= WEXITSTATUS(status);
message("Child exit: %d", ret_code);
// Exit with exit status of the child
exit(ret_code);
}
if (WIFSIGNALED(status))
message("Child killed by signal: %d", WTERMSIG(status));
exit(ret_code);
}
sleep(1);
}
kill_child();
exit(1);
}

View File

@ -0,0 +1,151 @@
#!/usr/bin/perl
# -*- cperl -*-
use strict;
use warnings;
use lib 'lib';
use My::SafeProcess::Base;
use POSIX qw(WNOHANG);
###########################################################################
# Util functions
###########################################################################
#
#Print message to stderr
#
my $verbose= 0;
sub message {
if ($verbose > 0){
use Time::localtime;
my $tm= localtime();
my $timestamp= sprintf("%02d%02d%02d %2d:%02d:%02d",
$tm->year % 100, $tm->mon+1, $tm->mday,
$tm->hour, $tm->min, $tm->sec);
print STDERR $timestamp, " monitor[$$]: ", @_, "\n";
}
}
###########################################################################
# Main program
###########################################################################
my $terminated= 0;
# Protect against being killed in the middle
# of child creation, just set the terminated flag
# to make sure the child will be killed off
# when program is ready to do that
$SIG{TERM}= sub { message("!Got signal @_"); $terminated= 1; };
$SIG{INT}= sub { message("!Got signal @_"); $terminated= 1; };
my $parent_pid= getppid();
my $found_double_dash= 0;
while (my $arg= shift(@ARGV)){
if ($arg =~ /^--$/){
$found_double_dash= 1;
last;
}
elsif ($arg =~ /^--verbose$/){
$verbose= 1;
}
else {
die "Unknown option: $arg";
}
}
my $path= shift(@ARGV); # Executable
die "usage:\n" .
" safe_process.pl [opts] -- <path> [<args> [...<args_n>]]"
unless defined $path || $found_double_dash;
message("started");
#message("path: '$path'");
message("parent: $parent_pid");
# Start process to monitor
my $child_pid=
create_process(
path => $path,
args => \@ARGV,
setpgrp => 1,
);
message("Started child $child_pid");
eval {
sub handle_signal {
$terminated= 1;
message("Got signal @_");
# Ignore all signals
foreach my $name (keys %SIG){
$SIG{$name}= 'IGNORE';
}
die "signaled\n";
};
local $SIG{TERM}= \&handle_signal;
local $SIG{INT}= \&handle_signal;
local $SIG{CHLD}= sub {
message("Got signal @_");
kill(9, -$child_pid);
my $ret= waitpid($child_pid, 0);
if ($? & 127){
exit(65); # Killed by signal
}
exit($? >> 8);
};
# Monitoring loop
while(!$terminated) {
# Check if parent is still alive
if (kill(0, $parent_pid) < 1){
message("Parent is not alive anymore");
last;
}
# Wait for child to terminate but wakeup every
# second to also check that parent is still alive
my $ret_pid;
$ret_pid= waitpid($child_pid, &WNOHANG);
if ($ret_pid == $child_pid) {
# Process has exited, collect return status
my $ret_code= $? >> 8;
message("Child exit: $ret_code");
# Exit with exit status of the child
exit ($ret_code);
}
sleep(1);
}
};
if ( $@ ) {
# The monitoring loop should have been
# broken by handle_signal
warn "Unexpected: $@" unless ( $@ =~ /signaled/ );
}
# Use negative pid in order to kill the whole
# process group
#
my $ret= kill(9, -$child_pid);
message("Killed child: $child_pid, ret: $ret");
if ($ret > 0) {
message("Killed child: $child_pid");
# Wait blocking for the child to return
my $ret_pid= waitpid($child_pid, 0);
if ($ret_pid != $child_pid){
message("unexpected pid $ret_pid returned from waitpid($child_pid)");
}
}
message("DONE!");
exit (1);

View File

@ -0,0 +1,312 @@
/* Copyright (C) 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Utility program that encapsulates process creation, monitoring
and bulletproof process cleanup
Usage:
safe_process [options to safe_process] -- progname arg1 ... argn
To safeguard mysqld you would invoke safe_process with a few options
for safe_process itself followed by a double dash to indicate start
of the command line for the program you really want to start
$> safe_process --output=output.log -- mysqld --datadir=var/data1 ...
This would redirect output to output.log and then start mysqld,
once it has done that it will continue to monitor the child as well
as the parent.
The safe_process then checks the follwing things:
1. Child exits, propagate the childs return code to the parent
by exiting with the same return code as the child.
2. Parent dies, immediately kill the child and exit, thus the
parent does not need to properly cleanup any child, it is handled
automatically.
3. Signal's recieced by the process will trigger same action as 2)
4. The named event "safe_process[pid]" can be signaled and will
trigger same action as 2)
WARNING! Be careful when using ProcessExplorer, since it will open
a handle to each process(and maybe also the Job), the process
spawned by safe_process will not be closed off when safe_process
is killed.
*/
/* Requires Windows 2000 or higher */
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <signal.h>
static int verbose= 0;
static char safe_process_name[32]= {0};
static void message(const char* fmt, ...)
{
if (!verbose)
return;
va_list args;
fprintf(stderr, "%s: ", safe_process_name);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
fflush(stderr);
}
static void die(const char* fmt, ...)
{
va_list args;
fprintf(stderr, "%s: FATAL ERROR, ", safe_process_name);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
if (int last_err= GetLastError())
fprintf(stderr, "error: %d, %s\n", last_err, strerror(last_err));
exit(1);
}
DWORD get_parent_pid(DWORD pid)
{
HANDLE snapshot;
DWORD parent_pid= -1;
PROCESSENTRY32 pe32;
pe32.dwSize= sizeof(PROCESSENTRY32);
snapshot= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE)
die("CreateToolhelp32Snapshot failed");
if (!Process32First(snapshot, &pe32))
{
CloseHandle(snapshot);
die("Process32First failed");
}
do
{
if (pe32.th32ProcessID == pid)
parent_pid= pe32.th32ParentProcessID;
} while(Process32Next( snapshot, &pe32));
CloseHandle(snapshot);
if (parent_pid == -1)
die("Could not find parent pid");
return parent_pid;
}
enum {
PARENT,
CHILD,
EVENT,
NUM_HANDLES
};
HANDLE shutdown_event;
void handle_signal (int signal)
{
message("Got signal: %d", signal);
if(SetEvent(shutdown_event) == 0) {
/* exit safe_process and (hopefully) kill off the child */
die("Failed to SetEvent");
}
}
int main(int argc, const char** argv )
{
char child_args[4096]= {0};
DWORD pid= GetCurrentProcessId();
DWORD parent_pid= get_parent_pid(pid);
HANDLE job_handle;
HANDLE wait_handles[NUM_HANDLES]= {0};
PROCESS_INFORMATION process_info= {0};
sprintf(safe_process_name, "safe_process[%d]", pid);
/* Create an event for the signal handler */
if ((shutdown_event=
CreateEvent(NULL, TRUE, FALSE, safe_process_name)) == NULL)
die("Failed to create shutdown_event");
wait_handles[EVENT]= shutdown_event;
signal(SIGINT, handle_signal);
signal(SIGBREAK, handle_signal);
signal(SIGTERM, handle_signal);
message("Started");
/* Parse arguments */
for (int i= 1; i < argc; i++) {
const char* arg= argv[i];
char* to= child_args;
if (strcmp(arg, "--") == 0 && strlen(arg) == 2) {
/* Got the "--" delimiter */
if (i >= argc)
die("No real args -> nothing to do");
/* Copy the remaining args to child_arg */
for (int j= i+1; j < argc; j++) {
to+= _snprintf(to, child_args + sizeof(child_args) - to, "%s ", argv[j]);
}
break;
} else {
if ( strcmp(arg, "--verbose") == 0 )
verbose++;
else if ( strncmp(arg, "--parent-pid", 10) == 0 )
{
/* Override parent_pid with a value provided by user */
const char* start;
if ((start= strstr(arg, "=")) == NULL)
die("Could not find start of option value in '%s'", arg);
start++; /* Step past = */
if ((parent_pid= atoi(start)) == 0)
die("Invalid value '%s' passed to --parent-id", start);
}
else
die("Unknown option: %s", arg);
}
}
if (*child_args == '\0')
die("nothing to do");
/* Open a handle to the parent process */
message("parent_pid: %d", parent_pid);
if (parent_pid == pid)
die("parent_pid is equal to own pid!");
if ((wait_handles[PARENT]=
OpenProcess(SYNCHRONIZE, FALSE, parent_pid)) == NULL)
die("Failed to open parent process with pid: %d", parent_pid);
/* Create the child process in a job */
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
/*
Create the job object to make it possible to kill the process
and all of it's children in one go
*/
if ((job_handle= CreateJobObject(NULL, NULL)) == NULL)
die("CreateJobObject failed");
/*
Make all processes associated with the job terminate when the
last handle to the job is closed.
*/
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
if (SetInformationJobObject(job_handle, JobObjectExtendedLimitInformation,
&jeli, sizeof(jeli)) == 0)
message("SetInformationJobObject failed, continue anyway...");
#if 0
/* Setup stdin, stdout and stderr redirect */
si.dwFlags= STARTF_USESTDHANDLES;
si.hStdInput= GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput= GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError= GetStdHandle(STD_ERROR_HANDLE);
#endif
/*
Create the process suspended to make sure it's assigned to the
Job before it creates any process of it's own
*/
if (CreateProcess(NULL, (LPSTR)child_args,
NULL,
NULL,
TRUE, /* inherit handles */
CREATE_SUSPENDED,
NULL,
NULL,
&si,
&process_info) == 0)
die("CreateProcess failed");
if (AssignProcessToJobObject(job_handle, process_info.hProcess) == 0)
{
TerminateProcess(process_info.hProcess, 200);
die("AssignProcessToJobObject failed");
}
ResumeThread(process_info.hThread);
CloseHandle(process_info.hThread);
wait_handles[CHILD]= process_info.hProcess;
message("Started child %d", process_info.dwProcessId);
/* Monitor loop */
DWORD child_exit_code= 1;
DWORD wait_res= WaitForMultipleObjects(NUM_HANDLES, wait_handles,
FALSE, INFINITE);
switch (wait_res)
{
case WAIT_OBJECT_0 + PARENT:
message("Parent exit");
break;
case WAIT_OBJECT_0 + CHILD:
if (GetExitCodeProcess(wait_handles[CHILD], &child_exit_code) == 0)
message("Child exit: could not get exit_code");
else
message("Child exit: exit_code: %d", child_exit_code);
break;
case WAIT_OBJECT_0 + EVENT:
message("Wake up from shutdown_event");
break;
default:
message("Unexpected result %d from WaitForMultipleObjects", wait_res);
break;
}
message("Exiting, child: %d", process_info.dwProcessId);
if (TerminateJobObject(job_handle, 201) == 0)
message("TerminateJobObject failed");
CloseHandle(job_handle);
if (wait_res != WAIT_OBJECT_0 + CHILD)
{
/* The child has not yet returned, wait for it */
message("waiting for child to exit");
if ((wait_res= WaitForSingleObject(wait_handles[CHILD], INFINITE)) != WAIT_OBJECT_0)
{
message("child wait failed: %d", wait_res);
}
else
{
message("child wait succeeded");
}
/* Child's exit code should now be 201, no need to get it */
}
for (int i= 0; i < NUM_HANDLES; i++)
CloseHandle(wait_handles[i]);
exit(child_exit_code);
}

View File

@ -1,960 +0,0 @@
# -*- cperl -*-
# Copyright (C) 2005-2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# This is a library file used by the Perl version of mysql-test-run,
# and is part of the translation of the Bourne shell script with the
# same name.
use File::Basename;
use IO::File();
use strict;
use My::Config;
sub collect_test_cases ($);
sub collect_one_suite ($);
sub collect_one_test_case ($$$$$$$$$);
sub mtr_options_from_test_file($$);
my $do_test;
my $skip_test;
sub init_pattern {
my ($from, $what)= @_;
if ( $from =~ /^[a-z0-9]$/ ) {
# Does not contain any regex, make the pattern match
# beginning of string
$from= "^$from";
}
# Check that pattern is a valid regex
eval { "" =~/$from/; 1 } or
mtr_error("Invalid regex '$from' passed to $what\nPerl says: $@");
return $from;
}
##############################################################################
#
# Collect information about test cases we are to run
#
##############################################################################
sub collect_test_cases ($) {
$do_test= init_pattern($::opt_do_test, "--do-test");
$skip_test= init_pattern($::opt_skip_test, "--skip-test");
my $suites= shift; # Semicolon separated list of test suites
my $cases = []; # Array of hash
foreach my $suite (split(",", $suites))
{
push(@$cases, collect_one_suite($suite));
}
if ( @::opt_cases )
{
# Check that the tests specified was found
# in at least one suite
foreach my $test_name_spec ( @::opt_cases )
{
my $found= 0;
my ($sname, $tname, $extension)= split_testname($test_name_spec);
foreach my $test ( @$cases )
{
# test->{name} is always in suite.name format
if ( $test->{name} =~ /.*\.$tname/ )
{
$found= 1;
}
}
if ( not $found )
{
mtr_error("Could not find $tname in any suite");
}
}
}
if ( $::opt_reorder )
{
# Reorder the test cases in an order that will make them faster to run
my %sort_criteria;
# Make a mapping of test name to a string that represents how that test
# should be sorted among the other tests. Put the most important criterion
# first, then a sub-criterion, then sub-sub-criterion, et c.
foreach my $tinfo (@$cases)
{
my @criteria = ();
# Look for tests that muct be in run in a defined order
# that is defined by test having the same name except for
# the ending digit
# Put variables into hash
my $test_name= $tinfo->{'name'};
my $depend_on_test_name;
if ( $test_name =~ /^([\D]+)([0-9]{1})$/ )
{
my $base_name= $1;
my $idx= $2;
mtr_verbose("$test_name => $base_name idx=$idx");
if ( $idx > 1 )
{
$idx-= 1;
$base_name= "$base_name$idx";
mtr_verbose("New basename $base_name");
}
foreach my $tinfo2 (@$cases)
{
if ( $tinfo2->{'name'} eq $base_name )
{
mtr_verbose("found dependent test $tinfo2->{'name'}");
$depend_on_test_name=$base_name;
}
}
}
if ( defined $depend_on_test_name )
{
mtr_verbose("Giving $test_name same critera as $depend_on_test_name");
$sort_criteria{$test_name} = $sort_criteria{$depend_on_test_name};
}
else
{
#
# Append the criteria for sorting, in order of importance.
#
push(@criteria, "ndb=" . ($tinfo->{'ndb_test'} ? "1" : "0"));
# Group test with equal options together.
# Ending with "~" makes empty sort later than filled
push(@criteria, join("!", sort @{$tinfo->{'master_opt'}}) . "~");
$sort_criteria{$test_name} = join(" ", @criteria);
}
}
@$cases = sort {
$sort_criteria{$a->{'name'}} . $a->{'name'} cmp
$sort_criteria{$b->{'name'}} . $b->{'name'}; } @$cases;
if ( $::opt_script_debug )
{
# For debugging the sort-order
foreach my $tinfo (@$cases)
{
print("$sort_criteria{$tinfo->{'name'}} -> \t$tinfo->{'name'}\n");
}
}
}
return $cases;
}
# Valid extensions and their corresonding component id
my %exts = ( 'test' => 'mysqld',
'imtest' => 'im'
);
# Returns (suitename, testname, extension)
sub split_testname {
my ($test_name)= @_;
# Get rid of directory part and split name on .'s
my @parts= split(/\./, basename($test_name));
if (@parts == 1){
# Only testname given, ex: alias
return (undef , $parts[0], undef);
} elsif (@parts == 2) {
# Either testname.test or suite.testname given
# Ex. main.alias or alias.test
if (defined $exts{$parts[1]})
{
return (undef , $parts[0], $parts[1]);
}
else
{
return ($parts[0], $parts[1], undef);
}
} elsif (@parts == 3) {
# Fully specified suitename.testname.test
# ex main.alias.test
return ( $parts[0], $parts[1], $parts[2]);
}
mtr_error("Illegal format of test name: $test_name");
}
sub collect_one_suite($)
{
my $suite= shift; # Test suite name
my @cases; # Array of hash
mtr_verbose("Collecting: $suite");
my $suitedir= "$::glob_mysql_test_dir"; # Default
if ( $suite ne "main" )
{
$suitedir= mtr_path_exists("$suitedir/suite/$suite",
"$suitedir/$suite");
mtr_verbose("suitedir: $suitedir");
}
my $testdir= "$suitedir/t";
my $resdir= "$suitedir/r";
# ----------------------------------------------------------------------
# Build a hash of disabled testcases for this suite
# ----------------------------------------------------------------------
my %disabled;
if ( open(DISABLED, "$testdir/disabled.def" ) )
{
while ( <DISABLED> )
{
chomp;
if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
{
$disabled{$1}= $2;
}
}
close DISABLED;
}
# Read suite.opt file
my $suite_opt_file= "$testdir/suite.opt";
my $suite_opts= [];
if ( -f $suite_opt_file )
{
$suite_opts= mtr_get_opts_from_file($suite_opt_file);
}
if ( @::opt_cases )
{
# Collect in specified order
foreach my $test_name_spec ( @::opt_cases )
{
my ($sname, $tname, $extension)= split_testname($test_name_spec);
# The test name parts have now been defined
#print " suite_name: $sname\n";
#print " tname: $tname\n";
#print " extension: $extension\n";
# Check cirrect suite if suitename is defined
next if (defined $sname and $suite ne $sname);
my $component_id;
if ( defined $extension )
{
my $full_name= "$testdir/$tname.$extension";
# Extension was specified, check if the test exists
if ( ! -f $full_name)
{
# This is only an error if suite was specified, otherwise it
# could exist in another suite
mtr_error("Test '$full_name' was not found in suite '$sname'")
if $sname;
next;
}
$component_id= $exts{$extension};
}
else
{
# No extension was specified
my ($ext, $component);
while (($ext, $component)= each %exts) {
my $full_name= "$testdir/$tname.$ext";
if ( ! -f $full_name ) {
next;
}
$component_id= $component;
$extension= $ext;
}
# Test not found here, could exist in other suite
next unless $component_id;
}
collect_one_test_case($testdir,$resdir,$suite,$tname,
"$tname.$extension",\@cases,\%disabled,
$component_id,$suite_opts);
}
}
else
{
opendir(TESTDIR, $testdir) or mtr_error("Can't open dir \"$testdir\": $!");
foreach my $elem ( sort readdir(TESTDIR) )
{
my $component_id= undef;
my $tname= undef;
if ($tname= mtr_match_extension($elem, 'test'))
{
$component_id = 'mysqld';
}
elsif ($tname= mtr_match_extension($elem, 'imtest'))
{
$component_id = 'im';
}
else
{
next;
}
# Skip tests that does not match the --do-test= filter
next if ($do_test and not $tname =~ /$do_test/o);
collect_one_test_case($testdir,$resdir,$suite,$tname,
$elem,\@cases,\%disabled,$component_id,
$suite_opts);
}
closedir TESTDIR;
}
# Return empty list if no testcases found
return if (@cases == 0);
# ----------------------------------------------------------------------
# Read combinations for this suite and build testcases x combinations
# if any combinations exists
# ----------------------------------------------------------------------
if ( ! $::opt_skip_combination )
{
my @combinations;
my $combination_file= "$suitedir/combinations";
#print "combination_file: $combination_file\n";
if (@::opt_combinations)
{
# take the combination from command-line
mtr_verbose("Take the combination from command line");
foreach my $combination (@::opt_combinations) {
my $comb= {};
$comb->{name}= $combination;
push(@{$comb->{comb_opt}}, $combination);
push(@combinations, $comb);
}
}
elsif (-f $combination_file )
{
# Read combinations file in my.cnf format
mtr_verbose("Read combinations file");
my $config= My::Config->new($combination_file);
foreach my $group ($config->groups()) {
my $comb= {};
$comb->{name}= $group->name();
foreach my $option ( $group->options() ) {
push(@{$comb->{comb_opt}}, $option->name()."=".$option->value());
}
push(@combinations, $comb);
}
}
if (@combinations)
{
print " - adding combinations\n";
#print_testcases(@cases);
my @new_cases;
foreach my $comb (@combinations)
{
foreach my $test (@cases)
{
#print $test->{name}, " ", $comb, "\n";
my $new_test= {};
while (my ($key, $value) = each(%$test)) {
if (ref $value eq "ARRAY") {
push(@{$new_test->{$key}}, @$value);
} else {
$new_test->{$key}= $value;
}
}
# Append the combination options to master_opt and slave_opt
push(@{$new_test->{master_opt}}, @{$comb->{comb_opt}});
push(@{$new_test->{slave_opt}}, @{$comb->{comb_opt}});
# Add combination name shrt name
$new_test->{combination}= $comb->{name};
# Add the new test to new test cases list
push(@new_cases, $new_test);
}
}
#print_testcases(@new_cases);
@cases= @new_cases;
#print_testcases(@cases);
}
}
optimize_cases(\@cases);
#print_testcases(@cases);
return @cases;
}
#
# Loop through all test cases
# - optimize which test to run by skipping unnecessary ones
# - update settings if necessary
#
sub optimize_cases {
my ($cases)= @_;
foreach my $tinfo ( @$cases )
{
# Skip processing if already marked as skipped
next if $tinfo->{skip};
# Replication test needs an adjustment of binlog format
if (mtr_match_prefix($tinfo->{'name'}, "rpl"))
{
# =======================================================
# Get binlog-format used by this test from master_opt
# =======================================================
my $test_binlog_format;
foreach my $opt ( @{$tinfo->{master_opt}} ) {
$test_binlog_format= $test_binlog_format ||
mtr_match_prefix($opt, "--binlog-format=");
}
# print $tinfo->{name}." uses ".$test_binlog_format."\n";
# =======================================================
# If a special binlog format was selected with
# --mysqld=--binlog-format=x, skip all test with different
# binlog-format
# =======================================================
if (defined $::used_binlog_format and
$test_binlog_format and
$::used_binlog_format ne $test_binlog_format)
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "Requires --binlog-format='$test_binlog_format'";
next;
}
# =======================================================
# Check that testcase supports the designated binlog-format
# =======================================================
if ($test_binlog_format and defined $tinfo->{'sup_binlog_formats'} )
{
my $supported=
grep { $_ eq $test_binlog_format } @{$tinfo->{'sup_binlog_formats'}};
if ( !$supported )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}=
"Doesn't support --binlog-format='$test_binlog_format'";
next;
}
}
# =======================================================
# Use dynamic switching of binlog-format if mtr started
# w/o --mysqld=--binlog-format=xxx and combinations.
# =======================================================
if (!defined $tinfo->{'combination'} and
!defined $::used_binlog_format)
{
$test_binlog_format= $tinfo->{'sup_binlog_formats'}->[0];
}
# Save binlog format for dynamic switching
$tinfo->{binlog_format}= $test_binlog_format;
}
}
}
##############################################################################
#
# Collect information about a single test case
#
##############################################################################
sub collect_one_test_case($$$$$$$$$) {
my $testdir= shift;
my $resdir= shift;
my $suite= shift;
my $tname= shift;
my $elem= shift;
my $cases= shift;
my $disabled=shift;
my $component_id= shift;
my $suite_opts= shift;
my $path= "$testdir/$elem";
# ----------------------------------------------------------------------
# Skip some tests silently
# ----------------------------------------------------------------------
if ( $::opt_start_from and $tname lt $::opt_start_from )
{
return;
}
my $tinfo= {};
$tinfo->{'name'}= basename($suite) . ".$tname";
$tinfo->{'result_file'}= "$resdir/$tname.result";
$tinfo->{'component_id'} = $component_id;
push(@$cases, $tinfo);
# ----------------------------------------------------------------------
# Skip some tests but include in list, just mark them to skip
# ----------------------------------------------------------------------
if ( $skip_test and $tname =~ /$skip_test/o )
{
$tinfo->{'skip'}= 1;
return;
}
# ----------------------------------------------------------------------
# Collect information about test case
# ----------------------------------------------------------------------
$tinfo->{'path'}= $path;
$tinfo->{'timezone'}= "GMT-3"; # for UNIX_TIMESTAMP tests to work
$tinfo->{'slave_num'}= 0; # Default, no slave
$tinfo->{'master_num'}= 1; # Default, 1 master
if ( defined mtr_match_prefix($tname,"rpl") )
{
if ( $::opt_skip_rpl )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "No replication tests(--skip-rpl)";
return;
}
$tinfo->{'slave_num'}= 1; # Default for rpl* tests, use one slave
}
if ( defined mtr_match_prefix($tname,"federated") )
{
# Default, federated uses the first slave as it's federated database
$tinfo->{'slave_num'}= 1;
}
my $master_opt_file= "$testdir/$tname-master.opt";
my $slave_opt_file= "$testdir/$tname-slave.opt";
my $slave_mi_file= "$testdir/$tname.slave-mi";
my $master_sh= "$testdir/$tname-master.sh";
my $slave_sh= "$testdir/$tname-slave.sh";
my $disabled_file= "$testdir/$tname.disabled";
my $im_opt_file= "$testdir/$tname-im.opt";
$tinfo->{'master_opt'}= [];
$tinfo->{'slave_opt'}= [];
$tinfo->{'slave_mi'}= [];
# Add suite opts
foreach my $opt ( @$suite_opts )
{
mtr_verbose($opt);
push(@{$tinfo->{'master_opt'}}, $opt);
push(@{$tinfo->{'slave_opt'}}, $opt);
}
# Add master opts
if ( -f $master_opt_file )
{
my $master_opt= mtr_get_opts_from_file($master_opt_file);
foreach my $opt ( @$master_opt )
{
my $value;
# The opt file is used both to send special options to the mysqld
# as well as pass special test case specific options to this
# script
$value= mtr_match_prefix($opt, "--timezone=");
if ( defined $value )
{
$tinfo->{'timezone'}= $value;
next;
}
$value= mtr_match_prefix($opt, "--slave-num=");
if ( defined $value )
{
$tinfo->{'slave_num'}= $value;
next;
}
$value= mtr_match_prefix($opt, "--result-file=");
if ( defined $value )
{
# Specifies the file mysqltest should compare
# output against
$tinfo->{'result_file'}= "r/$value.result";
next;
}
# If we set default time zone, remove the one we have
$value= mtr_match_prefix($opt, "--default-time-zone=");
if ( defined $value )
{
# Set timezone for this test case to something different
$tinfo->{'timezone'}= "GMT-8";
# Fallthrough, add the --default-time-zone option
}
# The --restart option forces a restart even if no special
# option is set. If the options are the same as next testcase
# there is no need to restart after the testcase
# has completed
if ( $opt eq "--force-restart" )
{
$tinfo->{'force_restart'}= 1;
next;
}
# Ok, this was a real option, add it
push(@{$tinfo->{'master_opt'}}, $opt);
}
}
# Add slave opts
if ( -f $slave_opt_file )
{
my $slave_opt= mtr_get_opts_from_file($slave_opt_file);
foreach my $opt ( @$slave_opt )
{
# If we set default time zone, remove the one we have
my $value= mtr_match_prefix($opt, "--default-time-zone=");
$tinfo->{'slave_opt'}= [] if defined $value;
}
push(@{$tinfo->{'slave_opt'}}, @$slave_opt);
}
if ( -f $slave_mi_file )
{
$tinfo->{'slave_mi'}= mtr_get_opts_from_file($slave_mi_file);
}
if ( -f $master_sh )
{
if ( $::glob_win32_perl )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "No tests with sh scripts on Windows";
return;
}
else
{
$tinfo->{'master_sh'}= $master_sh;
}
}
if ( -f $slave_sh )
{
if ( $::glob_win32_perl )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "No tests with sh scripts on Windows";
return;
}
else
{
$tinfo->{'slave_sh'}= $slave_sh;
}
}
if ( -f $im_opt_file )
{
$tinfo->{'im_opts'} = mtr_get_opts_from_file($im_opt_file);
}
else
{
$tinfo->{'im_opts'} = [];
}
# FIXME why this late?
my $marked_as_disabled= 0;
if ( $disabled->{$tname} )
{
$marked_as_disabled= 1;
$tinfo->{'comment'}= $disabled->{$tname};
}
if ( -f $disabled_file )
{
$marked_as_disabled= 1;
$tinfo->{'comment'}= mtr_fromfile($disabled_file);
}
# If test was marked as disabled, either opt_enable_disabled is off and then
# we skip this test, or it is on and then we run this test but warn
if ( $marked_as_disabled )
{
if ( $::opt_enable_disabled )
{
$tinfo->{'dont_skip_though_disabled'}= 1;
}
else
{
$tinfo->{'skip'}= 1;
$tinfo->{'disable'}= 1; # Sub type of 'skip'
return;
}
}
if ( $component_id eq 'im' )
{
if ( $::glob_use_embedded_server )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "No IM with embedded server";
return;
}
elsif ( $::opt_ps_protocol )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "No IM with --ps-protocol";
return;
}
elsif ( $::opt_skip_im )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "No IM tests(--skip-im)";
return;
}
}
else
{
mtr_options_from_test_file($tinfo,"$testdir/${tname}.test");
if ( defined $::used_default_engine )
{
# Different default engine is used
# tag test to require that engine
$tinfo->{'ndb_test'}= 1
if ( $::used_default_engine =~ /^ndb/i );
$tinfo->{'innodb_test'}= 1
if ( $::used_default_engine =~ /^innodb/i );
}
if ( $tinfo->{'big_test'} and ! $::opt_big_test )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "Test need 'big-test' option";
return;
}
if ( $tinfo->{'ndb_extra'} and ! $::opt_ndb_extra_test )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "Test need 'ndb_extra' option";
return;
}
if ( $tinfo->{'require_manager'} )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "Test need the _old_ manager(to be removed)";
return;
}
if ( $tinfo->{'need_debug'} && ! $::debug_compiled_binaries )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "Test need debug binaries";
return;
}
if ( $tinfo->{'ndb_test'} )
{
# This is a NDB test
if ( ! $::glob_ndbcluster_supported )
{
# Ndb is not supported, skip it
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "No ndbcluster support";
return;
}
elsif ( $::opt_skip_ndbcluster )
{
# All ndb test's should be skipped
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "No ndbcluster tests(--skip-ndbcluster)";
return;
}
# Ndb tests run with two mysqld masters
$tinfo->{'master_num'}= 2;
}
else
{
# This is not a ndb test
if ( $::opt_with_ndbcluster_only )
{
# Only the ndb test should be run, all other should be skipped
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "Only ndbcluster tests(--with-ndbcluster-only)";
return;
}
}
if ( $tinfo->{'innodb_test'} )
{
# This is a test that need innodb
if ( $::mysqld_variables{'innodb'} ne "TRUE" )
{
# innodb is not supported, skip it
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "No innodb support";
return;
}
}
if ( $tinfo->{'need_binlog'} )
{
if (grep(/^--skip-log-bin/, @::opt_extra_mysqld_opt) )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "Test need binlog";
return;
}
}
else
{
if ( $::mysql_version_id >= 50100 )
{
# Test does not need binlog, add --skip-binlog to
# the options used when starting it
push(@{$tinfo->{'master_opt'}}, "--skip-log-bin");
}
}
}
}
# List of tags in the .test files that if found should set
# the specified value in "tinfo"
our @tags=
(
["include/have_innodb.inc", "innodb_test", 1],
["include/have_binlog_format_row.inc", "sup_binlog_formats", ["row"]],
["include/have_log_bin.inc", "need_binlog", 1],
["include/have_binlog_format_statement.inc",
"sup_binlog_formats", ["statement"]],
["include/have_binlog_format_mixed.inc", "sup_binlog_formats", ["mixed"]],
["include/have_binlog_format_mixed_or_row.inc",
"sup_binlog_formats", ["mixed","row"]],
["include/have_binlog_format_mixed_or_statement.inc",
"sup_binlog_formats", ["mixed","statement"]],
["include/have_binlog_format_row_or_statement.inc",
"sup_binlog_formats", ["row","statement"]],
["include/big_test.inc", "big_test", 1],
["include/have_debug.inc", "need_debug", 1],
["include/have_ndb.inc", "ndb_test", 1],
["include/have_multi_ndb.inc", "ndb_test", 1],
["include/have_ndb_extra.inc", "ndb_extra", 1],
["include/ndb_master-slave.inc", "ndb_test", 1],
["require_manager", "require_manager", 1],
);
sub mtr_options_from_test_file($$) {
my $tinfo= shift;
my $file= shift;
#mtr_verbose("$file");
my $F= IO::File->new($file) or mtr_error("can't open file \"$file\": $!");
while ( my $line= <$F> )
{
# Skip line if it start's with #
next if ( $line =~ /^#/ );
# Match this line against tag in "tags" array
foreach my $tag (@tags)
{
if ( index($line, $tag->[0]) >= 0 )
{
# Tag matched, assign value to "tinfo"
$tinfo->{"$tag->[1]"}= $tag->[2];
}
}
# If test sources another file, open it as well
if ( $line =~ /^\-\-([[:space:]]*)source(.*)$/ or
$line =~ /^([[:space:]]*)source(.*);$/ )
{
my $value= $2;
$value =~ s/^\s+//; # Remove leading space
$value =~ s/[[:space:]]+$//; # Remove ending space
my $sourced_file= "$::glob_mysql_test_dir/$value";
if ( -f $sourced_file )
{
# Only source the file if it exists, we may get
# false positives in the regexes above if someone
# writes "source nnnn;" in a test case(such as mysqltest.test)
mtr_options_from_test_file($tinfo, $sourced_file);
}
}
}
}
sub print_testcases {
my (@cases)= @_;
print "=" x 60, "\n";
foreach my $test (@cases){
print "[", $test->{name}, "]", "\n";
while ((my ($key, $value)) = each(%$test)) {
print " ", $key, "=";
if (ref $value eq "ARRAY") {
print join(", ", @$value);
} else {
print $value;
}
print "\n";
}
print "\n";
}
print "=" x 60, "\n";
}
1;

1112
mysql-test/lib/mtr_cases.pm Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,297 +0,0 @@
# -*- cperl -*-
# Copyright (C) 2005 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# This is a library file used by the Perl version of mysql-test-run,
# and is part of the translation of the Bourne shell script with the
# same name.
#use Data::Dumper;
use strict;
# $Data::Dumper::Indent= 1;
sub mtr_diff($$);
##############################################################################
#
# This is a simplified unified diff, with some special handling
# of unsorted result sets
#
##############################################################################
# FIXME replace die with mtr_error
#require "mtr_report.pl";
#mtr_diff("a.txt","b.txt");
sub mtr_diff ($$) {
my $file1 = shift;
my $file2 = shift;
# ----------------------------------------------------------------------
# We read in all of the files at once
# ----------------------------------------------------------------------
unless ( open(FILE1, $file1) )
{
mtr_warning("can't open \"$file1\": $!");
return;
}
unless ( open(FILE2, $file2) )
{
mtr_warning("can't open \"$file2\": $!");
return;
}
my $lines1= collect_lines(<FILE1>);
my $lines2= collect_lines(<FILE2>);
close FILE1;
close FILE2;
# print Dumper($lines1);
# print Dumper($lines2);
# ----------------------------------------------------------------------
# We compare line by line, but don't shift off elements until we know
# what to do. This way we use the "restart" method, do simple change
# and restart by entering the diff loop from the beginning again.
# ----------------------------------------------------------------------
my @context;
my @info; # Collect information, and output later
my $lno1= 1;
my $lno2= 1;
while ( @$lines1 or @$lines2 )
{
unless ( @$lines1 )
{
push(@info, map {['+',$lno1,$lno2++,$_]} @$lines2);
last;
}
unless ( @$lines2 )
{
push(@info, map {['-',$lno1++,$lno2,$_]} @$lines1);
last;
}
# ----------------------------------------------------------------------
# We know both have lines
# ----------------------------------------------------------------------
if ( $lines1->[0] eq $lines2->[0] )
{
# Simple case, first line match and all is well
push(@info, ['',$lno1++,$lno2++,$lines1->[0]]);
shift @$lines1;
shift @$lines2;
next;
}
# ----------------------------------------------------------------------
# Now, we know they differ
# ----------------------------------------------------------------------
# How far in the other one, is there a match?
my $idx2= find_next_match($lines1->[0], $lines2);
my $idx1= find_next_match($lines2->[0], $lines1);
# Here we could test "if ( !defined $idx2 or !defined $idx1 )" and
# use a more complicated diff algorithm in the case both contains
# each others lines, just dislocated. But for this application, there
# should be no need.
if ( !defined $idx2 )
{
push(@info, ['-',$lno1++,$lno2,$lines1->[0]]);
shift @$lines1;
}
else
{
push(@info, ['+',$lno1,$lno2++,$lines2->[0]]);
shift @$lines2;
}
}
# ----------------------------------------------------------------------
# Try to output nicely
# ----------------------------------------------------------------------
# print Dumper(\@info);
# We divide into "chunks" to output
# We want at least three lines of context
my @chunks;
my @chunk;
my $state= 'pre'; # 'pre', 'in' and 'post' difference
my $post_count= 0;
foreach my $info ( @info )
{
if ( $info->[0] eq '' and $state eq 'pre' )
{
# Collect no more than three lines of context before diff
push(@chunk, $info);
shift(@chunk) if @chunk > 3;
next;
}
if ( $info->[0] =~ /(\+|\-)/ and $state =~ /(pre|in)/ )
{
# Start/continue collecting diff
$state= 'in';
push(@chunk, $info);
next;
}
if ( $info->[0] eq '' and $state eq 'in' )
{
# Stop collecting diff, and collect context after diff
$state= 'post';
$post_count= 1;
push(@chunk, $info);
next;
}
if ( $info->[0] eq '' and $state eq 'post' and $post_count < 6 )
{
# We might find a new diff sequence soon, continue to collect
# non diffs but five up on 6.
$post_count++;
push(@chunk, $info);
next;
}
if ( $info->[0] eq '' and $state eq 'post' )
{
# We put an end to this, giving three non diff lines to
# the old chunk, and three to the new one.
my @left= splice(@chunk, -3, 3);
push(@chunks, [@chunk]);
$state= 'pre';
$post_count= 0;
@chunk= @left;
next;
}
if ( $info->[0] =~ /(\+|\-)/ and $state eq 'post' )
{
# We didn't split, continue collect diff
$state= 'in';
push(@chunk, $info);
next;
}
}
if ( $post_count > 3 )
{
$post_count -= 3;
splice(@chunk, -$post_count, $post_count);
}
push(@chunks, [@chunk]) if @chunk and $state ne 'pre';
foreach my $chunk ( @chunks )
{
my $from_file_start= $chunk->[0]->[1];
my $to_file_start= $chunk->[0]->[2];
my $from_file_offset= $chunk->[$#$chunk]->[1] - $from_file_start;
my $to_file_offset= $chunk->[$#$chunk]->[2] - $to_file_start;
print "\@\@ -$from_file_start,$from_file_offset ",
"+$to_file_start,$to_file_offset \@\@\n";
foreach my $info ( @$chunk )
{
if ( $info->[0] eq '' )
{
print " $info->[3]\n";
}
elsif ( $info->[0] eq '-' )
{
print "- $info->[3]\n";
}
elsif ( $info->[0] eq '+' )
{
print "+ $info->[3]\n";
}
}
}
# print Dumper(\@chunks);
}
##############################################################################
# Find if the string is found in the array, return the index if found,
# if not found, return "undef"
##############################################################################
sub find_next_match {
my $line= shift;
my $lines= shift;
for ( my $idx= 0; $idx < @$lines; $idx++ )
{
return $idx if $lines->[$idx] eq $line;
}
return undef; # No match found
}
##############################################################################
# Just read the lines, but handle "sets" of lines that are unordered
##############################################################################
sub collect_lines {
my @recordset;
my @lines;
while (@_)
{
my $line= shift @_;
chomp($line);
if ( $line =~ /^\Q%unordered%\E\t/ )
{
push(@recordset, $line);
}
elsif ( @recordset )
{
push(@lines, sort @recordset);
@recordset= (); # Clear it
}
else
{
push(@lines, $line);
}
}
if ( @recordset )
{
push(@lines, sort @recordset);
@recordset= (); # Clear it
}
return \@lines;
}
1;

View File

@ -1,775 +0,0 @@
# -*- cperl -*-
# Copyright (C) 2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# This is a library file used by the Perl version of mysql-test-run,
# and is part of the translation of the Bourne shell script with the
# same name.
use strict;
# Private IM-related operations.
sub mtr_im_kill_process ($$$$);
sub mtr_im_load_pids ($);
sub mtr_im_terminate ($);
sub mtr_im_check_alive ($);
sub mtr_im_check_main_alive ($);
sub mtr_im_check_angel_alive ($);
sub mtr_im_check_mysqlds_alive ($);
sub mtr_im_check_mysqld_alive ($);
sub mtr_im_cleanup ($);
sub mtr_im_rm_file ($);
sub mtr_im_errlog ($);
sub mtr_im_kill ($);
sub mtr_im_wait_for_connection ($$$);
sub mtr_im_wait_for_mysqld($$$);
# Public IM-related operations.
sub mtr_im_start ($$);
sub mtr_im_stop ($);
##############################################################################
#
# Private operations.
#
##############################################################################
sub mtr_im_kill_process ($$$$) {
my $pid_lst= shift;
my $signal= shift;
my $total_retries= shift;
my $timeout= shift;
my %pids;
foreach my $pid ( @{$pid_lst} )
{
$pids{$pid}= 1;
}
for ( my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt )
{
foreach my $pid ( keys %pids )
{
mtr_debug("Sending $signal to $pid...");
kill($signal, $pid);
unless ( kill (0, $pid) )
{
mtr_debug("Process $pid died.");
delete $pids{$pid};
}
}
return if scalar keys %pids == 0;
mtr_debug("Sleeping $timeout second(s) waiting for processes to die...");
sleep($timeout);
}
mtr_debug("Process(es) " .
join(' ', keys %pids) .
" is still alive after $total_retries " .
"of sending signal $signal.");
}
###########################################################################
sub mtr_im_load_pids($) {
my $im= shift;
mtr_debug("Loading PID files...");
# Obtain mysqld-process pids.
my $instances = $im->{'instances'};
for ( my $idx= 0; $idx < 2; ++$idx )
{
mtr_debug("IM-guarded mysqld[$idx] PID file: '" .
$instances->[$idx]->{'path_pid'} . "'.");
my $mysqld_pid;
if ( -r $instances->[$idx]->{'path_pid'} )
{
$mysqld_pid= mtr_get_pid_from_file($instances->[$idx]->{'path_pid'});
mtr_debug("IM-guarded mysqld[$idx] PID: $mysqld_pid.");
}
else
{
$mysqld_pid= undef;
mtr_debug("IM-guarded mysqld[$idx]: no PID file.");
}
$instances->[$idx]->{'pid'}= $mysqld_pid;
}
# Re-read Instance Manager PIDs from the file, since during tests Instance
# Manager could have been restarted, so its PIDs could have been changed.
# - IM-main
mtr_debug("IM-main PID file: '$im->{path_pid}'.");
if ( -f $im->{'path_pid'} )
{
$im->{'pid'} =
mtr_get_pid_from_file($im->{'path_pid'});
mtr_debug("IM-main PID: $im->{pid}.");
}
else
{
mtr_debug("IM-main: no PID file.");
$im->{'pid'}= undef;
}
# - IM-angel
mtr_debug("IM-angel PID file: '$im->{path_angel_pid}'.");
if ( -f $im->{'path_angel_pid'} )
{
$im->{'angel_pid'} =
mtr_get_pid_from_file($im->{'path_angel_pid'});
mtr_debug("IM-angel PID: $im->{'angel_pid'}.");
}
else
{
mtr_debug("IM-angel: no PID file.");
$im->{'angel_pid'} = undef;
}
}
###########################################################################
sub mtr_im_terminate($) {
my $im= shift;
# Load pids from pid-files. We should do it first of all, because IM deletes
# them on shutdown.
mtr_im_load_pids($im);
mtr_debug("Shutting Instance Manager down...");
# Ignoring SIGCHLD so that all children could rest in peace.
start_reap_all();
# Send SIGTERM to IM-main.
if ( defined $im->{'pid'} )
{
mtr_debug("IM-main pid: $im->{pid}.");
mtr_debug("Stopping IM-main...");
mtr_im_kill_process([ $im->{'pid'} ], 'TERM', 10, 1);
}
else
{
mtr_debug("IM-main pid: n/a.");
}
# If IM-angel was alive, wait for it to die.
if ( defined $im->{'angel_pid'} )
{
mtr_debug("IM-angel pid: $im->{'angel_pid'}.");
mtr_debug("Waiting for IM-angel to die...");
my $total_attempts= 10;
for ( my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt )
{
unless ( kill (0, $im->{'angel_pid'}) )
{
mtr_debug("IM-angel died.");
last;
}
sleep(1);
}
}
else
{
mtr_debug("IM-angel pid: n/a.");
}
stop_reap_all();
# Re-load PIDs.
mtr_im_load_pids($im);
}
###########################################################################
sub mtr_im_check_alive($) {
my $im= shift;
mtr_debug("Checking whether IM-components are alive...");
return 1 if mtr_im_check_main_alive($im);
return 1 if mtr_im_check_angel_alive($im);
return 1 if mtr_im_check_mysqlds_alive($im);
return 0;
}
###########################################################################
sub mtr_im_check_main_alive($) {
my $im= shift;
# Check that the process, that we know to be IM's, is dead.
if ( defined $im->{'pid'} )
{
if ( kill (0, $im->{'pid'}) )
{
mtr_debug("IM-main (PID: $im->{pid}) is alive.");
return 1;
}
else
{
mtr_debug("IM-main (PID: $im->{pid}) is dead.");
}
}
else
{
mtr_debug("No PID file for IM-main.");
}
# Check that IM does not accept client connections.
if ( mtr_ping_port($im->{'port'}) )
{
mtr_debug("IM-main (port: $im->{port}) " .
"is accepting connections.");
mtr_im_errlog("IM-main is accepting connections on port " .
"$im->{port}, but there is no " .
"process information.");
return 1;
}
else
{
mtr_debug("IM-main (port: $im->{port}) " .
"does not accept connections.");
return 0;
}
}
###########################################################################
sub mtr_im_check_angel_alive($) {
my $im= shift;
# Check that the process, that we know to be the Angel, is dead.
if ( defined $im->{'angel_pid'} )
{
if ( kill (0, $im->{'angel_pid'}) )
{
mtr_debug("IM-angel (PID: $im->{angel_pid}) is alive.");
return 1;
}
else
{
mtr_debug("IM-angel (PID: $im->{angel_pid}) is dead.");
return 0;
}
}
else
{
mtr_debug("No PID file for IM-angel.");
return 0;
}
}
###########################################################################
sub mtr_im_check_mysqlds_alive($) {
my $im= shift;
mtr_debug("Checking for IM-guarded mysqld instances...");
my $instances = $im->{'instances'};
for ( my $idx= 0; $idx < 2; ++$idx )
{
mtr_debug("Checking mysqld[$idx]...");
return 1
if mtr_im_check_mysqld_alive($instances->[$idx]);
}
}
###########################################################################
sub mtr_im_check_mysqld_alive($) {
my $mysqld_instance= shift;
# Check that the process is dead.
if ( defined $mysqld_instance->{'pid'} )
{
if ( kill (0, $mysqld_instance->{'pid'}) )
{
mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive.");
return 1;
}
else
{
mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is dead.");
}
}
else
{
mtr_debug("No PID file for mysqld instance.");
}
# Check that mysqld does not accept client connections.
if ( mtr_ping_port($mysqld_instance->{'port'}) )
{
mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " .
"is accepting connections.");
mtr_im_errlog("Mysqld is accepting connections on port " .
"$mysqld_instance->{port}, but there is no " .
"process information.");
return 1;
}
else
{
mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " .
"does not accept connections.");
return 0;
}
}
###########################################################################
sub mtr_im_cleanup($) {
my $im= shift;
mtr_im_rm_file($im->{'path_pid'});
mtr_im_rm_file($im->{'path_sock'});
mtr_im_rm_file($im->{'path_angel_pid'});
for ( my $idx= 0; $idx < 2; ++$idx )
{
mtr_im_rm_file($im->{'instances'}->[$idx]->{'path_pid'});
mtr_im_rm_file($im->{'instances'}->[$idx]->{'path_sock'});
}
}
###########################################################################
sub mtr_im_rm_file($)
{
my $file_path= shift;
if ( -f $file_path )
{
mtr_debug("Removing '$file_path'...");
unless ( unlink($file_path) )
{
mtr_warning("Can not remove '$file_path'.")
}
}
else
{
mtr_debug("File '$file_path' does not exist already.");
}
}
###########################################################################
sub mtr_im_errlog($) {
my $msg= shift;
# Complain in error log so that a warning will be shown.
#
# TODO: unless BUG#20761 is fixed, we will print the warning to stdout, so
# that it can be seen on console and does not produce pushbuild error.
# my $errlog= "$opt_vardir/log/mysql-test-run.pl.err";
#
# open (ERRLOG, ">>$errlog") ||
# mtr_error("Can not open error log ($errlog)");
#
# my $ts= localtime();
# print ERRLOG
# "Warning: [$ts] $msg\n";
#
# close ERRLOG;
my $ts= localtime();
print "Warning: [$ts] $msg\n";
}
###########################################################################
sub mtr_im_kill($) {
my $im= shift;
# Re-load PIDs. That can be useful because some processes could have been
# restarted.
mtr_im_load_pids($im);
# Ignoring SIGCHLD so that all children could rest in peace.
start_reap_all();
# Kill IM-angel first of all.
if ( defined $im->{'angel_pid'} )
{
mtr_debug("Killing IM-angel (PID: $im->{angel_pid})...");
mtr_im_kill_process([ $im->{'angel_pid'} ], 'KILL', 10, 1)
}
else
{
mtr_debug("IM-angel is dead.");
}
# Re-load PIDs again.
mtr_im_load_pids($im);
# Kill IM-main.
if ( defined $im->{'pid'} )
{
mtr_debug("Killing IM-main (PID: $im->pid})...");
mtr_im_kill_process([ $im->{'pid'} ], 'KILL', 10, 1);
}
else
{
mtr_debug("IM-main is dead.");
}
# Re-load PIDs again.
mtr_im_load_pids($im);
# Kill guarded mysqld instances.
my @mysqld_pids;
mtr_debug("Collecting PIDs of mysqld instances to kill...");
for ( my $idx= 0; $idx < 2; ++$idx )
{
my $pid= $im->{'instances'}->[$idx]->{'pid'};
unless ( defined $pid )
{
next;
}
mtr_debug(" - IM-guarded mysqld[$idx] PID: $pid.");
push (@mysqld_pids, $pid);
}
if ( scalar @mysqld_pids > 0 )
{
mtr_debug("Killing IM-guarded mysqld instances...");
mtr_im_kill_process(\@mysqld_pids, 'KILL', 10, 1);
}
# That's all.
stop_reap_all();
}
##############################################################################
sub mtr_im_wait_for_connection($$$) {
my $im= shift;
my $total_attempts= shift;
my $connect_timeout= shift;
mtr_debug("Waiting for IM on port $im->{port} " .
"to start accepting connections...");
for ( my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt )
{
mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)...");
if ( mtr_ping_port($im->{'port'}) )
{
mtr_debug("IM is accepting connections " .
"on port $im->{port}.");
return 1;
}
mtr_debug("Sleeping $connect_timeout...");
sleep($connect_timeout);
}
mtr_debug("IM does not accept connections " .
"on port $im->{port} after " .
($total_attempts * $connect_timeout) . " seconds.");
return 0;
}
##############################################################################
sub mtr_im_wait_for_mysqld($$$) {
my $mysqld= shift;
my $total_attempts= shift;
my $connect_timeout= shift;
mtr_debug("Waiting for IM-guarded mysqld on port $mysqld->{port} " .
"to start accepting connections...");
for ( my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt )
{
mtr_debug("Trying to connect to mysqld " .
"($cur_attempt of $total_attempts)...");
if ( mtr_ping_port($mysqld->{'port'}) )
{
mtr_debug("Mysqld is accepting connections " .
"on port $mysqld->{port}.");
return 1;
}
mtr_debug("Sleeping $connect_timeout...");
sleep($connect_timeout);
}
mtr_debug("Mysqld does not accept connections " .
"on port $mysqld->{port} after " .
($total_attempts * $connect_timeout) . " seconds.");
return 0;
}
##############################################################################
#
# Public operations.
#
##############################################################################
sub mtr_im_start($$) {
my $im = shift;
my $opts = shift;
mtr_debug("Starting Instance Manager...");
my $args;
mtr_init_args(\$args);
mtr_add_arg($args, "--defaults-file=%s", $im->{'defaults_file'});
foreach my $opt ( @{$opts} )
{
mtr_add_arg($args, $opt);
}
$im->{'spawner_pid'} =
mtr_spawn(
$::exe_im, # path to the executable
$args, # cmd-line args
'', # stdin
$im->{'path_log'}, # stdout
$im->{'path_err'}, # stderr
'', # pid file path (not used)
{ append_log_file => 1 } # append log files
);
unless ( $im->{'spawner_pid'} )
{
mtr_error('Could not start Instance Manager.')
}
# Instance Manager can be run in daemon mode. In this case, it creates
# several processes and the parent process, created by mtr_spawn(), exits just
# after start. So, we have to obtain Instance Manager PID from the PID file.
mtr_debug("Waiting for IM to create PID file (" .
"path: '$im->{path_pid}'; " .
"timeout: $im->{start_timeout})...");
unless ( sleep_until_file_created($im->{'path_pid'},
$im->{'start_timeout'},
-1) ) # real PID is still unknown
{
mtr_debug("IM has not created PID file in $im->{start_timeout} secs.");
mtr_debug("Aborting test suite...");
mtr_kill_leftovers();
mtr_report("IM has not created PID file in $im->{start_timeout} secs.");
return 0;
}
$im->{'pid'}= mtr_get_pid_from_file($im->{'path_pid'});
mtr_debug("Instance Manager started. PID: $im->{pid}.");
# Wait until we can connect to IM.
my $IM_CONNECT_TIMEOUT= 30;
unless ( mtr_im_wait_for_connection($im,
$IM_CONNECT_TIMEOUT, 1) )
{
mtr_debug("Can not connect to Instance Manager " .
"in $IM_CONNECT_TIMEOUT seconds after start.");
mtr_debug("Aborting test suite...");
mtr_kill_leftovers();
mtr_report("Can not connect to Instance Manager " .
"in $IM_CONNECT_TIMEOUT seconds after start.");
return 0;
}
# Wait for IM to start guarded instances:
# - wait for PID files;
mtr_debug("Waiting for guarded mysqlds instances to create PID files...");
for ( my $idx= 0; $idx < 2; ++$idx )
{
my $mysqld= $im->{'instances'}->[$idx];
if ( exists $mysqld->{'nonguarded'} )
{
next;
}
mtr_debug("Waiting for mysqld[$idx] to create PID file (" .
"path: '$mysqld->{path_pid}'; " .
"timeout: $mysqld->{start_timeout})...");
unless ( sleep_until_file_created($mysqld->{'path_pid'},
$mysqld->{'start_timeout'},
-1) ) # real PID is still unknown
{
mtr_debug("mysqld[$idx] has not created PID file in " .
"$mysqld->{start_timeout} secs.");
mtr_debug("Aborting test suite...");
mtr_kill_leftovers();
mtr_report("mysqld[$idx] has not created PID file in " .
"$mysqld->{start_timeout} secs.");
return 0;
}
mtr_debug("PID file for mysqld[$idx] ($mysqld->{path_pid} created.");
}
# Wait until we can connect to guarded mysqld-instances
# (in other words -- wait for IM to start guarded instances).
mtr_debug("Waiting for guarded mysqlds to start accepting connections...");
for ( my $idx= 0; $idx < 2; ++$idx )
{
my $mysqld= $im->{'instances'}->[$idx];
if ( exists $mysqld->{'nonguarded'} )
{
next;
}
mtr_debug("Waiting for mysqld[$idx] to accept connection...");
unless ( mtr_im_wait_for_mysqld($mysqld, 30, 1) )
{
mtr_debug("Can not connect to mysqld[$idx] " .
"in $IM_CONNECT_TIMEOUT seconds after start.");
mtr_debug("Aborting test suite...");
mtr_kill_leftovers();
mtr_report("Can not connect to mysqld[$idx] " .
"in $IM_CONNECT_TIMEOUT seconds after start.");
return 0;
}
mtr_debug("mysqld[$idx] started.");
}
mtr_debug("Instance Manager and its components are up and running.");
return 1;
}
##############################################################################
sub mtr_im_stop($) {
my $im= shift;
mtr_debug("Stopping Instance Manager...");
# Try graceful shutdown.
mtr_im_terminate($im);
# Check that all processes died.
unless ( mtr_im_check_alive($im) )
{
mtr_debug("Instance Manager has been stopped successfully.");
mtr_im_cleanup($im);
return 1;
}
# Instance Manager don't want to die. We should kill it.
mtr_im_errlog("Instance Manager did not shutdown gracefully.");
mtr_im_kill($im);
# Check again that all IM-related processes have been killed.
my $im_is_alive= mtr_im_check_alive($im);
mtr_im_cleanup($im);
if ( $im_is_alive )
{
mtr_debug("Can not kill Instance Manager or its children.");
return 0;
}
mtr_debug("Instance Manager has been killed successfully.");
return 1;
}
###########################################################################
1;

View File

@ -20,135 +20,14 @@
use strict;
sub mtr_get_pid_from_file ($);
sub mtr_get_opts_from_file ($);
sub mtr_fromfile ($);
sub mtr_tofile ($@);
sub mtr_tonewfile($@);
sub mtr_lastlinefromfile($);
sub mtr_appendfile_to_file ($$);
sub mtr_grab_file($);
sub mtr_printfile($);
##############################################################################
#
#
#
##############################################################################
sub mtr_get_pid_from_file ($) {
my $pid_file_path= shift;
my $TOTAL_ATTEMPTS= 30;
my $timeout= 1;
# We should read from the file until we get correct pid. As it is
# stated in BUG#21884, pid file can be empty at some moment. So, we should
# read it until we get valid data.
for (my $cur_attempt= 1; $cur_attempt <= $TOTAL_ATTEMPTS; ++$cur_attempt)
{
mtr_debug("Reading pid file '$pid_file_path' " .
"($cur_attempt of $TOTAL_ATTEMPTS)...");
open(FILE, '<', $pid_file_path)
or mtr_error("can't open file \"$pid_file_path\": $!");
# Read pid number from file
my $pid= <FILE>;
chomp $pid;
close FILE;
return $pid if $pid=~ /^(\d+)/;
mtr_debug("Pid file '$pid_file_path' does not yet contain pid number.\n" .
"Sleeping $timeout second(s) more...");
sleep($timeout);
}
mtr_error("Pid file '$pid_file_path' is corrupted. " .
"Can not retrieve PID in " .
($timeout * $TOTAL_ATTEMPTS) . " seconds.");
}
sub mtr_get_opts_from_file ($) {
my $file= shift;
open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!");
my @args;
while ( <FILE> )
{
chomp;
# --set-variable=init_connect=set @a='a\\0c'
s/^\s+//; # Remove leading space
s/\s+$//; # Remove ending space
# This is strange, but we need to fill whitespace inside
# quotes with something, to remove later. We do this to
# be able to split on space. Else, we have trouble with
# options like
#
# --someopt="--insideopt1 --insideopt2"
#
# But still with this, we are not 100% sure it is right,
# we need a shell to do it right.
# print STDERR "\n";
# print STDERR "AAA: $_\n";
s/\'([^\'\"]*)\'/unspace($1,"\x0a")/ge;
s/\"([^\'\"]*)\"/unspace($1,"\x0b")/ge;
s/\'([^\'\"]*)\'/unspace($1,"\x0a")/ge;
s/\"([^\'\"]*)\"/unspace($1,"\x0b")/ge;
# print STDERR "BBB: $_\n";
# foreach my $arg (/(--?\w.*?)(?=\s+--?\w|$)/)
# FIXME ENV vars should be expanded!!!!
foreach my $arg (split(/[ \t]+/))
{
$arg =~ tr/\x11\x0a\x0b/ \'\"/; # Put back real chars
# The outermost quotes has to go
$arg =~ s/^([^\'\"]*)\'(.*)\'([^\'\"]*)$/$1$2$3/
or $arg =~ s/^([^\'\"]*)\"(.*)\"([^\'\"]*)$/$1$2$3/;
$arg =~ s/\\\\/\\/g;
$arg =~ s/\$\{(\w+)\}/envsubst($1)/ge;
$arg =~ s/\$(\w+)/envsubst($1)/ge;
# print STDERR "ARG: $arg\n";
# Do not pass empty string since my_getopt is not capable to handle it.
if (length($arg))
{
push(@args, $arg)
}
}
}
close FILE;
return \@args;
}
sub envsubst {
my $string= shift;
if ( ! defined $ENV{$string} )
{
mtr_error("opt file referense \$$string that is unknown");
}
return $ENV{$string};
}
sub unspace {
my $string= shift;
my $quote= shift;
$string =~ s/[ \t]/\x11/g;
return "$quote$string$quote";
}
# Read a whole file, stripping leading and trailing whitespace.
sub mtr_fromfile ($) {
my $file= shift;
@ -161,19 +40,6 @@ sub mtr_fromfile ($) {
return $text;
}
sub mtr_lastlinefromfile ($) {
my $file= shift;
my $text;
open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!");
while (my $line= <FILE>)
{
$text= $line;
}
close FILE;
return $text;
}
sub mtr_tofile ($@) {
my $file= shift;
@ -183,6 +49,7 @@ sub mtr_tofile ($@) {
close FILE;
}
sub mtr_tonewfile ($@) {
my $file= shift;
@ -191,6 +58,7 @@ sub mtr_tonewfile ($@) {
close FILE;
}
sub mtr_appendfile_to_file ($$) {
my $from_file= shift;
my $to_file= shift;
@ -203,6 +71,7 @@ sub mtr_appendfile_to_file ($$) {
close TOFILE;
}
# Read a whole file verbatim.
sub mtr_grab_file($) {
my $file= shift;
@ -215,4 +84,15 @@ sub mtr_grab_file($) {
}
# Print the file to STDOUT
sub mtr_printfile($) {
my $file= shift;
open(FILE, '<', $file)
or warn $!;
print while(<FILE>);
close FILE;
return;
}
1;

View File

@ -19,45 +19,25 @@
# same name.
use strict;
use File::Find;
sub mtr_native_path($);
use My::Platform;
sub mtr_init_args ($);
sub mtr_add_arg ($$@);
sub mtr_args2str($@);
sub mtr_path_exists(@);
sub mtr_script_exists(@);
sub mtr_file_exists(@);
sub mtr_exe_exists(@);
sub mtr_exe_maybe_exists(@);
sub mtr_copy_dir($$);
sub mtr_rmtree($);
sub mtr_same_opts($$);
sub mtr_cmp_opts($$);
##############################################################################
#
# Misc
# Args
#
##############################################################################
# Convert path to OS native format
sub mtr_native_path($)
{
my $path= shift;
# MySQL version before 5.0 still use cygwin, no need
# to convert path
return $path
if ($::mysql_version_id < 50000);
$path=~ s/\//\\/g
if ($::glob_win32);
return $path;
}
# FIXME move to own lib
sub mtr_init_args ($) {
my $args = shift;
$$args = []; # Empty list
@ -68,9 +48,18 @@ sub mtr_add_arg ($$@) {
my $format= shift;
my @fargs = @_;
# Quote args if args contain space
$format= "\"$format\""
if (IS_WINDOWS and grep(/\s/, @fargs));
push(@$args, sprintf($format, @fargs));
}
sub mtr_args2str($@) {
my $exe= shift or die;
return join(" ", native_path($exe), @_);
}
##############################################################################
#
@ -100,7 +89,7 @@ sub mtr_path_exists (@) {
sub mtr_script_exists (@) {
foreach my $path ( @_ )
{
if($::glob_win32)
if(IS_WINDOWS)
{
return $path if -f $path;
}
@ -140,11 +129,10 @@ sub mtr_file_exists (@) {
sub mtr_exe_maybe_exists (@) {
my @path= @_;
map {$_.= ".exe"} @path if $::glob_win32;
map {$_.= ".nlm"} @path if $::glob_netware;
map {$_.= ".exe"} @path if IS_WINDOWS;
foreach my $path ( @path )
{
if($::glob_win32)
if(IS_WINDOWS)
{
return $path if -f $path;
}
@ -179,134 +167,11 @@ sub mtr_exe_exists (@) {
}
sub mtr_copy_dir($$) {
my $from_dir= shift;
my $to_dir= shift;
sub mtr_milli_sleep {
die "usage: mtr_milli_sleep(milliseconds)" unless @_ == 1;
my ($millis)= @_;
# mtr_verbose("Copying from $from_dir to $to_dir");
mkpath("$to_dir");
opendir(DIR, "$from_dir")
or mtr_error("Can't find $from_dir$!");
for(readdir(DIR)) {
next if "$_" eq "." or "$_" eq "..";
if ( -d "$from_dir/$_" )
{
mtr_copy_dir("$from_dir/$_", "$to_dir/$_");
next;
}
copy("$from_dir/$_", "$to_dir/$_");
}
closedir(DIR);
}
sub mtr_rmtree($) {
my ($dir)= @_;
mtr_verbose("mtr_rmtree: $dir");
# Try to use File::Path::rmtree. Recent versions
# handles removal of directories and files that don't
# have full permissions, while older versions
# may have a problem with that and we use our own version
eval { rmtree($dir); };
if ( $@ ) {
mtr_warning("rmtree($dir) failed, trying with File::Find...");
my $errors= 0;
# chmod
find( {
no_chdir => 1,
wanted => sub {
chmod(0777, $_)
or mtr_warning("couldn't chmod(0777, $_): $!") and $errors++;
}
},
$dir
);
# rm
finddepth( {
no_chdir => 1,
wanted => sub {
my $file= $_;
# Use special underscore (_) filehandle, caches stat info
if (!-l $file and -d _ ) {
rmdir($file) or
mtr_warning("couldn't rmdir($file): $!") and $errors++;
} else {
unlink($file)
or mtr_warning("couldn't unlink($file): $!") and $errors++;
}
}
},
$dir
);
mtr_error("Failed to remove '$dir'") if $errors;
mtr_report("OK, that worked!");
}
}
sub mtr_same_opts ($$) {
my $l1= shift;
my $l2= shift;
return mtr_cmp_opts($l1,$l2) == 0;
}
sub mtr_cmp_opts ($$) {
my $l1= shift;
my $l2= shift;
my @l1= @$l1;
my @l2= @$l2;
return -1 if @l1 < @l2;
return 1 if @l1 > @l2;
while ( @l1 ) # Same length
{
my $e1= shift @l1;
my $e2= shift @l2;
my $cmp= ($e1 cmp $e2);
return $cmp if $cmp != 0;
}
return 0; # They are the same
}
#
# Compare two arrays and put all unequal elements into a new one
#
sub mtr_diff_opts ($$) {
my $l1= shift;
my $l2= shift;
my $f;
my $l= [];
foreach my $e1 (@$l1)
{
$f= undef;
foreach my $e2 (@$l2)
{
$f= 1 unless ($e1 ne $e2);
}
push(@$l, $e1) unless (defined $f);
}
foreach my $e2 (@$l2)
{
$f= undef;
foreach my $e1 (@$l1)
{
$f= 1 unless ($e1 ne $e2);
}
push(@$l, $e2) unless (defined $f);
}
return $l;
select(undef, undef, undef, ($millis/1000));
}
1;

File diff suppressed because it is too large Load Diff

View File

@ -18,49 +18,53 @@
# and is part of the translation of the Bourne shell script with the
# same name.
package mtr_report;
use strict;
use warnings;
sub mtr_report_test_name($);
sub mtr_report_test_passed($);
sub mtr_report_test_failed($);
sub mtr_report_test_skipped($);
sub mtr_report_test_not_skipped_though_disabled($);
use base qw(Exporter);
our @EXPORT= qw(report_option mtr_print_line mtr_print_thick_line
mtr_print_header mtr_report mtr_report_stats
mtr_warning mtr_error mtr_debug mtr_verbose
mtr_verbose_restart mtr_report_test_passed
mtr_report_test_failed mtr_report_test_skipped
mtr_report_stats);
sub mtr_report_stats ($);
sub mtr_print_line ();
sub mtr_print_thick_line ();
sub mtr_print_header ();
sub mtr_report (@);
sub mtr_warning (@);
sub mtr_error (@);
sub mtr_child_error (@);
sub mtr_debug (@);
sub mtr_verbose (@);
require "mtr_io.pl";
my $tot_real_time= 0;
our $timestamp= 0;
sub report_option {
my ($opt, $value)= @_;
##############################################################################
#
#
#
##############################################################################
# Convert - to _ in option name
$opt =~ s/-/_/;
no strict 'refs';
${$opt}= $value;
}
sub mtr_report_test_name ($) {
sub SHOW_SUITE_NAME() { return 1; };
sub _mtr_report_test_name ($) {
my $tinfo= shift;
my $tname= $tinfo->{name};
# Remove suite part of name
$tname =~ s/.*\.// unless SHOW_SUITE_NAME;
# Add combination name if any
$tname.= " '$tinfo->{combination}'"
if defined $tinfo->{combination};
_mtr_log($tname);
print _timestamp();
printf "%-30s ", $tname;
}
sub mtr_report_test_skipped ($) {
my $tinfo= shift;
_mtr_report_test_name($tinfo);
$tinfo->{'result'}= 'MTR_RES_SKIPPED';
if ( $tinfo->{'disable'} )
@ -69,49 +73,48 @@ sub mtr_report_test_skipped ($) {
}
elsif ( $tinfo->{'comment'} )
{
mtr_report("[ skipped ] $tinfo->{'comment'}");
if ( $tinfo->{skip_detected_by_test} )
{
mtr_report("[ skip.] $tinfo->{'comment'}");
}
else
{
mtr_report("[ skip ] $tinfo->{'comment'}");
}
}
else
{
mtr_report("[ skipped ]");
mtr_report("[ skip ]");
}
}
sub mtr_report_tests_not_skipped_though_disabled ($) {
my $tests= shift;
if ( $::opt_enable_disabled )
{
my @disabled_tests= grep {$_->{'dont_skip_though_disabled'}} @$tests;
if ( @disabled_tests )
{
print "\nTest(s) which will be run though they are marked as disabled:\n";
foreach my $tinfo ( sort {$a->{'name'} cmp $b->{'name'}} @disabled_tests )
{
printf " %-20s : %s\n", $tinfo->{'name'}, $tinfo->{'comment'};
}
}
}
}
sub mtr_report_test_passed ($) {
my $tinfo= shift;
sub mtr_report_test_passed ($$) {
my ($tinfo, $use_timer)= @_;
_mtr_report_test_name($tinfo);
my $timer= "";
if ( $::opt_timer and -f "$::opt_vardir/log/timer" )
if ( $use_timer and -f "$::opt_vardir/log/timer" )
{
$timer= mtr_fromfile("$::opt_vardir/log/timer");
$tot_real_time += ($timer/1000);
$timer= sprintf "%12s", $timer;
}
$tinfo->{'result'}= 'MTR_RES_PASSED';
# Set as passed unless already set
if ( not defined $tinfo->{'result'} ){
$tinfo->{'result'}= 'MTR_RES_PASSED';
}
mtr_report("[ pass ] $timer");
}
sub mtr_report_test_failed ($) {
my $tinfo= shift;
sub mtr_report_test_failed ($$) {
my ($tinfo, $logfile)= @_;
_mtr_report_test_name($tinfo);
$tinfo->{'result'}= 'MTR_RES_FAILED';
my $test_failures= $tinfo->{'failures'} || 0;
$tinfo->{'failures'}= $test_failures + 1;
if ( defined $tinfo->{'timeout'} )
{
mtr_report("[ fail ] timeout");
@ -129,12 +132,12 @@ sub mtr_report_test_failed ($) {
# failing the test is saved in "comment"
mtr_report("\nERROR: $tinfo->{'comment'}");
}
elsif ( -f $::path_timefile )
elsif ( defined $logfile and -f $logfile )
{
# Test failure was detected by test tool and it's report
# Test failure was detected by test tool and its report
# about what failed has been saved to file. Display the report.
print "\n";
print mtr_fromfile($::path_timefile); # FIXME print_file() instead
mtr_printfile($logfile);
print "\n";
}
else
@ -145,6 +148,7 @@ sub mtr_report_test_failed ($) {
}
}
sub mtr_report_stats ($) {
my $tests= shift;
@ -184,28 +188,7 @@ sub mtr_report_stats ($) {
# ----------------------------------------------------------------------
# Print out a summary report to screen
# ----------------------------------------------------------------------
if ( ! $tot_failed )
{
print "All $tot_tests tests were successful.\n";
}
else
{
my $ratio= $tot_passed * 100 / $tot_tests;
print "Failed $tot_failed/$tot_tests tests, ";
printf("%.2f", $ratio);
print "\% were successful.\n\n";
print
"The log files in var/log may give you some hint\n",
"of what went wrong.\n",
"If you want to report this error, please read first ",
"the documentation at\n",
"http://dev.mysql.com/doc/mysql/en/mysql-test-suite.html\n";
}
if (!$::opt_extern)
{
print "The servers were restarted $tot_restarts times\n";
}
print "The servers were restarted $tot_restarts times\n";
if ( $::opt_timer )
{
@ -220,7 +203,7 @@ sub mtr_report_stats ($) {
# the "var/log/*.err" files. We save this info in "var/log/warnings"
# ----------------------------------------------------------------------
if ( ! $::glob_use_running_server )
if ( $::opt_warnings )
{
# Save and report if there was any fatal warnings/errors in err logs
@ -433,23 +416,6 @@ sub mtr_report_stats ($) {
print "\n";
# Print a list of testcases that failed
if ( $tot_failed != 0 )
{
my $test_mode= join(" ", @::glob_test_mode) || "default";
print "mysql-test-run in $test_mode mode: *** Failing the test(s):";
foreach my $tinfo (@$tests)
{
if ( $tinfo->{'result'} eq 'MTR_RES_FAILED' )
{
print " $tinfo->{'name'}";
}
}
print "\n";
}
# Print a list of check_testcases that failed(if any)
if ( $::opt_check_testcases )
{
@ -471,12 +437,47 @@ sub mtr_report_stats ($) {
}
}
# Print a list of testcases that failed
if ( $tot_failed != 0 )
{
my $ratio= $tot_passed * 100 / $tot_tests;
print "Failed $tot_failed/$tot_tests tests, ";
printf("%.2f", $ratio);
print "\% were successful.\n\n";
# Print the list of test that failed in a format
# that can be copy pasted to rerun only failing tests
print "Failing test(s):";
foreach my $tinfo (@$tests)
{
if ( $tinfo->{'result'} eq 'MTR_RES_FAILED' )
{
print " $tinfo->{'name'}";
}
}
print "\n\n";
# Print info about reporting the error
print
"The log files in var/log may give you some hint of what went wrong.\n\n",
"If you want to report this error, please read first ",
"the documentation\n",
"at http://dev.mysql.com/doc/mysql/en/mysql-test-suite.html\n\n";
}
else
{
print "All $tot_tests tests were successful.\n";
}
if ( $tot_failed != 0 || $found_problems)
{
mtr_error("there were failing test cases");
}
}
##############################################################################
#
# Text formatting
@ -484,22 +485,25 @@ sub mtr_report_stats ($) {
##############################################################################
sub mtr_print_line () {
print '-' x 55, "\n";
print '-' x 60, "\n";
}
sub mtr_print_thick_line () {
print '=' x 55, "\n";
sub mtr_print_thick_line {
my $char= shift || '=';
print $char x 60, "\n";
}
sub mtr_print_header () {
print "\n";
if ( $::opt_timer )
{
print "TEST RESULT TIME (ms)\n";
print "TEST RESULT TIME (ms)\n";
}
else
{
print "TEST RESULT\n";
print "TEST RESULT\n";
}
mtr_print_line();
print "\n";
@ -512,66 +516,61 @@ sub mtr_print_header () {
#
##############################################################################
use IO::File;
use Time::localtime;
my $log_file_ref= undef;
sub _timestamp {
return "" unless $timestamp;
sub mtr_log_init ($) {
my ($filename)= @_;
mtr_error("Log is already open") if defined $log_file_ref;
$log_file_ref= IO::File->new($filename, "a") or
mtr_warning("Could not create logfile $filename: $!");
my $tm= localtime();
return sprintf("%02d%02d%02d %2d:%02d:%02d ",
$tm->year % 100, $tm->mon+1, $tm->mday,
$tm->hour, $tm->min, $tm->sec);
}
sub _mtr_log (@) {
print $log_file_ref join(" ", @_),"\n"
if defined $log_file_ref;
}
# Print message to screen
sub mtr_report (@) {
# Print message to screen and log
_mtr_log(@_);
print join(" ", @_),"\n";
print join(" ", @_), "\n";
}
# Print warning to screen
sub mtr_warning (@) {
# Print message to screen and log
_mtr_log("WARNING: ", @_);
print STDERR "mysql-test-run: WARNING: ",join(" ", @_),"\n";
print STDERR _timestamp(), "mysql-test-run: WARNING: ", join(" ", @_), "\n";
}
# Print error to screen and then exit
sub mtr_error (@) {
# Print message to screen and log
_mtr_log("ERROR: ", @_);
print STDERR "mysql-test-run: *** ERROR: ",join(" ", @_),"\n";
mtr_exit(1);
}
sub mtr_child_error (@) {
# Print message to screen and log
_mtr_log("ERROR(child): ", @_);
print STDERR "mysql-test-run: *** ERROR(child): ",join(" ", @_),"\n";
print STDERR _timestamp(), "mysql-test-run: *** ERROR: ", join(" ", @_), "\n";
exit(1);
}
sub mtr_debug (@) {
# Only print if --script-debug is used
if ( $::opt_script_debug )
if ( $::opt_verbose > 1 )
{
_mtr_log("###: ", @_);
print STDERR "####: ",join(" ", @_),"\n";
print STDERR _timestamp(), "####: ", join(" ", @_), "\n";
}
}
sub mtr_verbose (@) {
# Always print to log, print to screen only when --verbose is used
_mtr_log("> ",@_);
if ( $::opt_verbose )
{
print STDERR "> ",join(" ", @_),"\n";
print STDERR _timestamp(), "> ",join(" ", @_),"\n";
}
}
sub mtr_verbose_restart (@) {
my ($server, @args)= @_;
my $proc= $server->{proc};
if ( $::opt_verbose_restart )
{
print STDERR _timestamp(), "> Restart $proc - ",join(" ", @args),"\n";
}
}
1;

View File

@ -135,7 +135,7 @@ sub run_stress_test ()
}
mtr_init_args(\$args);
mtr_add_args($args, "$::glob_mysql_test_dir/mysql-stress-test.pl");
mtr_add_arg($args, "--server-socket=%s", $::master->[0]->{'path_sock'});
mtr_add_arg($args, "--server-user=%s", $::opt_user);
mtr_add_arg($args, "--server-database=%s", "test");
@ -181,7 +181,13 @@ sub run_stress_test ()
}
#Run stress test
mtr_run("$::glob_mysql_test_dir/mysql-stress-test.pl", $args, "", "", "", "");
My::SafeProcess->run
(
name => "stress test",
path => $^X,
args => \$args,
);
if ( ! $::glob_use_embedded_server )
{
stop_all_servers();

View File

@ -1,158 +0,0 @@
# -*- cperl -*-
# Copyright (C) 2005-2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# This is a library file used by the Perl version of mysql-test-run,
# and is part of the translation of the Bourne shell script with the
# same name.
use Errno;
use strict;
sub mtr_init_timers ();
sub mtr_timer_start($$$);
sub mtr_timer_stop($$);
sub mtr_timer_stop_all($);
##############################################################################
#
# Initiate the structure shared by all timers
#
##############################################################################
sub mtr_init_timers () {
my $timers = { timers => {}, pids => {}};
return $timers;
}
##############################################################################
#
# Start, stop and poll a timer
#
# As alarm() isn't portable to Windows, we use separate processes to
# implement timers.
#
##############################################################################
sub mtr_timer_start($$$) {
my ($timers,$name,$duration)= @_;
if ( exists $timers->{'timers'}->{$name} )
{
# We have an old running timer, kill it
mtr_warning("There is an old timer running");
mtr_timer_stop($timers,$name);
}
FORK:
{
my $tpid= fork();
if ( ! defined $tpid )
{
if ( $! == $!{EAGAIN} ) # See "perldoc Errno"
{
mtr_warning("Got EAGAIN from fork(), sleep 1 second and redo");
sleep(1);
redo FORK;
}
else
{
mtr_error("can't fork timer, error: $!");
}
}
if ( $tpid )
{
# Parent, record the information
mtr_verbose("Starting timer for '$name',",
"duration: $duration, pid: $tpid");
$timers->{'timers'}->{$name}->{'pid'}= $tpid;
$timers->{'timers'}->{$name}->{'duration'}= $duration;
$timers->{'pids'}->{$tpid}= $name;
}
else
{
# Child, install signal handlers and sleep for "duration"
# Don't do the ^C cleanup in the timeout child processes!
# There is actually a race here, if we get ^C after fork(), but before
# clearing the signal handler.
$SIG{INT}= 'DEFAULT';
$SIG{TERM}= sub {
mtr_verbose("timer $$ woke up, exiting!");
exit(0);
};
$0= "mtr_timer(timers,$name,$duration)";
sleep($duration);
mtr_verbose("timer $$ expired after $duration seconds");
exit(0);
}
}
}
sub mtr_timer_stop ($$) {
my ($timers,$name)= @_;
if ( exists $timers->{'timers'}->{$name} )
{
my $tpid= $timers->{'timers'}->{$name}->{'pid'};
mtr_verbose("Stopping timer for '$name' with pid $tpid");
# FIXME as Cygwin reuses pids fast, maybe check that is
# the expected process somehow?!
kill(15, $tpid);
# As the timers are so simple programs, we trust them to terminate,
# and use blocking wait for it. We wait just to avoid a zombie.
waitpid($tpid,0);
delete $timers->{'timers'}->{$name}; # Remove the timer information
delete $timers->{'pids'}->{$tpid}; # and PID reference
return 1;
}
mtr_error("Asked to stop timer '$name' not started");
}
sub mtr_timer_stop_all ($) {
my $timers= shift;
foreach my $name ( keys %{$timers->{'timers'}} )
{
mtr_timer_stop($timers, $name);
}
return 1;
}
sub mtr_timer_timeout ($$) {
my ($timers,$pid)= @_;
return "" unless exists $timers->{'pids'}->{$pid};
# Got a timeout(the process with $pid is recorded as being a timer)
# return the name of the timer
return $timers->{'pids'}->{$pid};
}
1;

27
mysql-test/lib/t/Base.t Normal file
View File

@ -0,0 +1,27 @@
# -*- cperl -*-
use Test::More qw(no_plan);
use strict;
use_ok ("My::SafeProcess::Base");
my $count= 0;
for (1..100){
my $pid= My::SafeProcess::Base::_safe_fork();
exit unless $pid;
(waitpid($pid, 0) == $pid) and $count++;
}
ok($count == 100, "safe_fork");
# A nice little forkbomb
SKIP: {
skip("forkbomb", 1);
eval {
while(1){
my $pid= My::SafeProcess::Base::_safe_fork();
exit unless $pid;
}
};
ok($@, "forkbomb");
}

33
mysql-test/lib/t/Find.t Normal file
View File

@ -0,0 +1,33 @@
# -*- cperl -*-
use Test::More qw(no_plan);
use strict;
use_ok ("My::Find");
my $basedir= "../..";
print "=" x 40, "\n";
my $mysqld_exe= my_find_bin($basedir,
["sql", "bin"],
["mysqld", "mysqld-debug"]);
print "mysqld_exe: $mysqld_exe\n";
print "=" x 40, "\n";
my $mysql_exe= my_find_bin($basedir,
["client", "bin"],
"mysql");
print "mysql_exe: $mysql_exe\n";
print "=" x 40, "\n";
my $mtr_build_dir= $ENV{MTR_BUILD_DIR};
$ENV{MTR_BUILD_DIR}= "debug";
my $mysql_exe= my_find_bin($basedir,
["client", "bin"],
"mysql");
print "mysql_exe: $mysql_exe\n";
$ENV{MTR_BUILD_DIR}= $mtr_build_dir;
print "=" x 40, "\n";
my $charset_dir= my_find_dir($basedir,
["share/mysql", "sql/share", "share"],
"charsets");
print "charset_dir: $charset_dir\n";
print "=" x 40, "\n";

127
mysql-test/lib/t/Options.t Normal file
View File

@ -0,0 +1,127 @@
# -*- cperl -*-
use Test::More qw(no_plan);
use strict;
use_ok("My::Options");
my @tests=
(
[
['--binlog-format=row', '--loose-skip-innodb', '--binlog-format=ms'],
['--binlog-format=row', '--loose-skip-innodb', '--binlog-format=statement'],
['--binlog-format=statement']
],
[
['--binlog-format=row', '--loose-skip-innodb', '--binlog-format=statement'],
['--binlog-format=row', '--loose-skip-innodb', '--binlog-format=mixed'],
['--binlog-format=mixed']
],
[
['--binlog-format=row', '--loose-skip-innodb', '--binlog-format=mixed'],
['--binlog-format=row', '--loose-skip-innodb', '--binlog-format=statement'],
['--binlog-format=statement']
],
[
['--binlog-format=mixed', '--loose-skip-innodb', '--binlog-format=row'],
['--binlog-format=statement', '--loose-skip-innodb', '--binlog-format=row'],
[ ]
],
[
['--binlog-format=row'],
[ ],
['--binlog-format=default']
],
[
[ ],
['--binlog-format=row'],
['--binlog-format=row']
],
[
[ ],
['-O', 'max_binlog_size=1' ],
['--max_binlog_size=1' ]
],
[
['-O', 'max_binlog_size=1' ],
['-O', 'max_binlog_size=1' ],
[ ],
],
[
['-O', 'max_binlog_size=1' ],
[ ],
['--max_binlog_size=default' ]
],
[
[ ],
['-O', 'max_binlog_size=1', '--binlog-format=row' ],
['--max_binlog_size=1', '--binlog-format=row' ]
],
[
['--binlog-format=statement' ],
['-O', 'max_binlog_size=1', '--binlog-format=row' ],
['--max_binlog_size=1', '--binlog-format=row']
],
[
[ '--binlog-format=statement' ],
['-O', 'max_binlog_size=1', '--binlog-format=statement' ],
['--max_binlog_size=1' ]
],
[
[ '--binlog-format=statement' ],
['-O', 'max_binlog_size=1', '--binlog-format=statement' ],
['--max_binlog_size=1' ]
],
[
[ '--binlog-format=statement' ],
['--relay-log=/path/to/a/relay-log', '--binlog-format=row'],
['--relay-log=/path/to/a/relay-log', '--binlog-format=row' ]
],
[
[ '--binlog-format=statement' ],
['--relay-log=/path/to/a/relay-log', '-O', 'max_binlog_size=1'],
['--max_binlog_size=1', '--relay-log=/path/to/a/relay-log', '--binlog-format=default' ]
],
[
[ '--slow-query-log=0' ],
[ '--slow-query-log' ],
[ '--slow-query-log' ]
],
);
my $test_no= 0;
foreach my $test (@tests){
print "test", $test_no++, "\n";
foreach my $opts (@$test){
print My::Options::toStr("", @$opts);
}
my $from= $test->[0];
my $to= $test->[1];
my @result= My::Options::diff($from, $to);
ok(My::Options::same(\@result, $test->[2]));
if (!My::Options::same(\@result, $test->[2])){
print "failed\n";
print My::Options::toStr("result", @result);
print My::Options::toStr("expect", @{$test->[2]});
}
print My::Options::toSQL(@result), "\n";
print "\n";
}

View File

@ -0,0 +1,18 @@
# -*- cperl -*-
use Test::More qw(no_plan);
use strict;
use_ok ("My::Platform");
use My::Platform;
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
print "Running on Windows\n" if (IS_WINDOWS);
print "Using ActiveState perl\n" if (IS_WIN32PERL);
print "Using cygwin perl\n" if (IS_CYGWIN);
print "dir: '$dir'\n";
print "native: '".native_path($dir)."'\n";
print "mixed: '".mixed_path($dir)."'\n";
print "posix: '".posix_path($dir)."'\n";

View File

@ -0,0 +1,102 @@
# -*- cperl -*-
use strict;
use FindBin;
use IO::File;
use Test::More qw(no_plan);
use_ok ("My::SafeProcess");
my $perl_path= $^X;
{
# Test exit codes
my $count= 32;
my $ok_count= 0;
for my $code (0..$count-1) {
my $args= [ "$FindBin::Bin/test_child.pl", "--exit-code=$code" ];
my $proc= My::SafeProcess->new
(
path => $perl_path,
args => \$args,
output => "/dev/null",
error => "/dev/null",
);
# Wait max 10 seconds for the process to finish
$ok_count++ if ($proc->wait_one(10) == 0 and
$proc->exit_status() == $code);
}
ok($count == $ok_count, "check exit_status, $ok_count");
}
{
# spawn a number of concurrent processes
my $count= 16;
my $ok_count= 0;
my %procs;
for my $code (0..$count-1) {
my $args= [ "$FindBin::Bin/test_child.pl", "--exit-code=$code" ];
$procs{$code}= My::SafeProcess->new
(
path => $perl_path,
args => \$args,
output => "/dev/null",
error => "/dev/null",
);
}
for my $code (0..$count-1) {
$ok_count++ if ($procs{$code}->wait_one(10) == 0 and
$procs{$code}->exit_status() == $code);
}
ok($count == $ok_count, "concurrent, $ok_count");
}
#
# Test stdout, stderr
#
{
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
my $args= [ "$FindBin::Bin/test_child.pl" ];
my $proc= My::SafeProcess->new
(
path => $perl_path,
args => \$args,
output => "$dir/output.txt",
error => "$dir/error.txt",
);
$proc->wait_one(2); # Wait max 2 seconds for the process to finish
my $fh= IO::File->new("$dir/output.txt");
my @text= <$fh>;
ok(grep(/Hello stdout/, @text), "check stdout");
$fh= IO::File->new("$dir/error.txt");
my @text= <$fh>;
ok(grep(/Hello stderr/, @text), "check stderr");
# To same file
$proc= My::SafeProcess->new
(
path => $perl_path,
args => \$args,
output => "$dir/output.txt",
error => "$dir/output.txt",
debug => 1,
);
$proc->wait_one(2); # Wait max 2 seconds for the process to finish
my $fh= IO::File->new("$dir/output.txt");
my @text= <$fh>;
ok((grep(/Hello stdout/, @text) and grep(/Hello stderr/, @text)),
"check stdout and stderr");
}

View File

@ -0,0 +1,149 @@
#!/usr/bin/perl
# -*- cperl -*-
use strict;
use FindBin;
use My::SafeProcess;
#
# Test longterm running of SafeProcess
#
my $perl_path= $^X;
my $verbose= 0;
my $loops= 100;
print "kill one and wait for one\n";
for (1...$loops){
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
my @procs;
for (1..10){
my $args= [ "$FindBin::Bin/dummyd.pl", "--vardir=$dir" ];
my $proc= My::SafeProcess->new
(
path => $perl_path,
args => \$args,
verbose => $verbose,
);
push(@procs, $proc);
}
foreach my $proc (@procs) {
$proc->kill();
# dummyd will always be killed and thus
# exit_status should have been set to 1
die "oops, exit_status: ", $proc->exit_status()
unless $proc->exit_status() == 1;
}
print "=" x 60, "\n";
}
print "With 1 second sleep in dummyd\n";
for (1...$loops){
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
my @procs;
for (1..10){
my $args= [ "$FindBin::Bin/dummyd.pl",
"--vardir=$dir",
"--sleep=1" ];
my $proc= My::SafeProcess->new
(
path => $perl_path,
args => \$args,
verbose => $verbose,
);
push(@procs, $proc);
}
foreach my $proc (@procs) {
$proc->kill();
}
print "=" x 60, "\n";
}
print "kill all and wait for one\n";
for (1...$loops){
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
my @procs;
for (1..10){
my $args= [ "$FindBin::Bin/dummyd.pl", "--vardir=$dir" ];
my $proc= My::SafeProcess->new
(
path => $perl_path,
args => \$args,
verbose => $verbose,
);
push(@procs, $proc);
}
foreach my $proc (@procs) {
$proc->start_kill();
}
foreach my $proc (@procs) {
$proc->wait_one();
}
print "=" x 60, "\n";
}
print "kill all using shutdown without callback\n";
for (1...$loops){
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
my @procs;
for (1..10){
my $args= [ "$FindBin::Bin/dummyd.pl", "--vardir=$dir" ];
my $proc= My::SafeProcess->new
(
path => $perl_path,
args => \$args,
verbose => $verbose,
);
push(@procs, $proc);
}
My::SafeProcess::shutdown(2, @procs);
print "=" x 60, "\n";
}
print "kill all using shutdown\n";
for (1...$loops){
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
my @procs;
for (1..10){
my $args= [ "$FindBin::Bin/dummyd.pl", "--vardir=$dir" ];
my $proc= My::SafeProcess->new
(
path => $perl_path,
args => \$args,
verbose => $verbose,
shutdown => sub { }, # Does nothing
);
push(@procs, $proc);
}
My::SafeProcess::shutdown(2, @procs);
print "=" x 60, "\n";
}
exit(0);

View File

@ -0,0 +1,34 @@
#!/usr/bin/perl
# -*- cperl -*-
use strict;
use My::File::Path;
use Test::Simple tests => 7;
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
my $testdir="$dir/test";
my $test_todir="$dir/to";
my $subdir= "$testdir/test1/test2/test3";
#
# 1. Create, copy and remove a directory structure
#
mkpath($subdir);
ok( -d $subdir, "Check '$subdir' is created");
copytree($testdir, $test_todir);
ok( -d $test_todir, "Check '$test_todir' is created");
ok( -d "$test_todir/test1", "Check 'test1' is created");
ok( -d "$test_todir/test1/test2", "Check 'test2' is created");
ok( -d "$test_todir/test1/test2/test3", "Check 'test3' is created");
rmtree($testdir);
ok( ! -d $testdir, "Check '$testdir' is gone");
rmtree($test_todir);
ok( ! -d $test_todir, "Check '$test_todir' is gone");

View File

@ -0,0 +1,38 @@
#!/usr/bin/perl
# -*- cperl -*-
use strict;
use Getopt::Long;
use IO::File;
my $vardir;
my $randie= 0;
my $sleep= 0;
GetOptions
(
# Directory where to write files
'vardir=s' => \$vardir,
'die-randomly' => \$randie,
'sleep=i' => \$sleep,
);
die("invalid vardir ") unless defined $vardir and -d $vardir;
my $pid= $$;
while(1){
for my $i (1..64){
# Write to file
my $name= "$vardir/$pid.$i.tmp";
my $F= IO::File->new($name, "w")
or warn "$$, Could not open $name: $!" and next;
print $F rand($.) for (1..1000);
$F->close();
sleep($sleep);
die "ooops!" if $randie and rand() < 0.0001
}
}
exit (0);

52
mysql-test/lib/t/rmtree.t Normal file
View File

@ -0,0 +1,52 @@
#!/usr/bin/perl
# -*- cperl -*-
use strict;
use My::File::Path;
use Test::Simple tests => 8;
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
my $testdir="$dir/test";
my $subdir= "$testdir/test1/test2/test3";
#
# 1. Create and remove a directory structure
#
mkpath($subdir);
ok( -d $subdir, "Check '$subdir' is created");
rmtree($testdir);
ok( ! -d $testdir, "Check '$testdir' is gone");
#
# 2. Create and remove a directory structure
# where one directory is chmod to 0000
#
mkpath($subdir);
ok( -d $subdir, "Check '$subdir' is created");
ok( chmod(0000, $subdir) == 1 , "Check one dir was chmoded");
rmtree($testdir);
ok( ! -d $testdir, "Check '$testdir' is gone");
#
# 3. Create and remove a directory structure
# where one file is chmod to 0000
#
mkpath($subdir);
ok( -d $subdir, "Check '$subdir' is created");
my $testfile= "$subdir/test.file";
open(F, ">", $testfile) or die;
print F "hello\n";
close(F);
ok( chmod(0000, $testfile) == 1 , "Check one file was chmoded");
rmtree($testdir);
ok( ! -d $testdir, "Check '$testdir' is gone");

131
mysql-test/lib/t/testMyConfig.t Executable file
View File

@ -0,0 +1,131 @@
#!/usr/bin/perl
# -*- cperl -*-
use strict;
use warnings;
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
use Test::More qw(no_plan);
BEGIN { use_ok ( "My::Config" ) };
my $test_cnf= "$dir/test.cnf";
# Write test config file
open(OUT, ">", $test_cnf) or die;
print $test_cnf, "\n";
print OUT <<EOF
[mysqld]
# Comment
option1=values2
option2= value4
option4
basedir=thebasedir
[mysqld_1]
[mysqld_2]
[mysqld.9]
[client]
socket =\tasocketpath
EOF
;
close OUT;
my $config= My::Config->new($test_cnf);
isa_ok( $config, "My::Config" );
print $config;
ok ( $config->group("mysqld_2"), "group mysqld_2 exists");
ok ( $config->group("mysqld_1"), "group mysqld_1 exists");
ok ( $config->group("mysqld.9"), "group mysqld.9 exists");
ok ( $config->group("mysqld.9")->suffix() eq ".9", "group mysqld.9 has suffix .9");
ok ( $config->group("mysqld"), "group mysqld exists");
ok ( $config->group("client"), "group client exists");
ok ( !$config->group("mysqld_3"), "group mysqld_3 does not exist");
ok ( $config->options_in_group("mysqld") == 4, "options in [mysqld] is 4");
ok ( $config->options_in_group("nonexist") == 0, "options in [nonexist] is 0");
{
my @groups= $config->groups();
ok(@groups == 5, "5 groups");
my $idx= 0;
foreach my $name ('mysqld', 'mysqld_1', 'mysqld_2', 'mysqld.9', 'client') {
is($groups[$idx++]->name(), $name, "checking groups $idx");
}
}
{
my @groups= $config->like("mysqld");
ok(@groups == 4, "4 groups like mysqld");
my $idx= 0;
foreach my $name ('mysqld', 'mysqld_1', 'mysqld_2', 'mysqld.9') {
is($groups[$idx++]->name(), $name, "checking like(\"mysqld\") $idx");
}
}
{
my @groups= $config->like("not");
ok(@groups == 0, "checking like(\"not\")");
}
is($config->first_like("mysqld_")->name(), "mysqld_1", "first_like");
is( $config->value('mysqld', 'option4'), undef,
"mysqld_option4 exists, does not have a value");
ok( $config->exists('mysqld', 'option4'),
"mysqld_option4 exists");
ok( $config->exists('mysqld', 'option2'),
"mysqld_option2 exists");
ok( !$config->exists('mysqld', 'option5'),
"mysqld_option5 does not exists");
# Save the config to file
my $test2_cnf= "$dir/test2.cnf";
$config->save($test2_cnf);
# read it back and check it's the same
my $config2= My::Config->new($test2_cnf);
isa_ok( $config2, "My::Config" );
is_deeply( \$config, \$config2, "test.cnf is equal to test2.cnf");
my $test_include_cnf= "$dir/test_include.cnf";
# Write test config file that includes test.cnf
open(OUT, ">", $test_include_cnf) or die;
print OUT <<EOF
[mysqld]
!include test.cnf
# Comment
option1=values3
basedir=anotherbasedir
EOF
;
close OUT;
# Read the config file
my $config3= My::Config->new($test_include_cnf);
isa_ok( $config3, "My::Config" );
print $config3;
is( $config3->value('mysqld', 'basedir'), 'anotherbasedir',
"mysqld_basedir has been overriden by value in test_include.cnf");
is( $config3->value('mysqld', 'option1'), 'values3',
"mysqld_option1 has been overriden by value in test_include.cnf");
is( $config3->value('mysqld', 'option2'), 'value4',
"mysqld_option2 is from included file");
is( $config3->value('client', 'socket'), 'asocketpath',
"client.socket is from included file");
is( $config3->value('mysqld', 'option4'), undef,
"mysqld_option4 exists, does not have a value");
print "$config3\n";

View File

@ -0,0 +1,98 @@
#!/usr/bin/perl
# -*- cperl -*-
use strict;
use warnings;
use File::Temp qw / tempdir /;
my $dir = tempdir( CLEANUP => 1 );
use Test::More qw(no_plan);
BEGIN { use_ok ( "My::ConfigFactory" ) };
my $gen1_cnf= "$dir/gen1.cnf";
open(OUT, ">", $gen1_cnf) or die;
print OUT <<EOF
[mysqld.master]
# Comment
option1=value1
basedir=abasedir
[mysqld.1]
# Comment
option1=value1
option2=value2
[ENV]
MASTER_MY_PORT=\@mysqld.master.port
EOF
;
close OUT;
my $basedir= "../..";
my $config= My::ConfigFactory->new_config
(
{
basedir => $basedir,
template_path => $gen1_cnf,
vardir => "/path/to/var",
baseport => 10987,
#hosts => [ 'host1', 'host2' ],
}
);
print $config;
ok ( $config->group("mysqld.master"), "group mysqld.master exists");
ok ( $config->group("mysqld.1"), "group mysqld.1 exists");
ok ( $config->group("client"), "group client exists");
ok ( !$config->group("mysqld.3"), "group mysqld.3 does not exist");
ok ( $config->first_like("mysqld"), "group like 'mysqld' exists");
is( $config->value('mysqld.1', '#host'), 'localhost',
"mysqld.1.#host has been generated");
is( $config->value('client', 'host'), 'localhost',
"client.host has been generated");
is( $config->value('client', 'host'),
$config->value('mysqld.master', '#host'),
"client.host is same as mysqld.master.host");
ok ( $config->value("mysqld.1", 'character-sets-dir') =~ /$basedir.*charsets$/,
"'character-sets-dir' generated");
ok ( $config->value("mysqld.1", 'language') =~ /$basedir.*english$/,
"'language' generated");
ok ( $config->value("ENV", 'MASTER_MY_PORT') =~ /\d/,
"'language' generated");
my $gen2_cnf= "$dir/gen2.cnf";
open(OUT, ">", $gen2_cnf) or die;
print OUT <<EOF
[mysqld.master]
EOF
;
close OUT;
my $config2= My::ConfigFactory->new_config
(
{
basedir => $basedir,
template_path => $gen2_cnf,
vardir => "/path/to/var",
baseport => 10987,
#hosts => [ 'host1', 'host2' ],
}
);
print $config2;
ok ( $config2->first_like("mysqld"), "group like 'mysqld' exists");

21
mysql-test/lib/t/test_child.pl Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/perl
# -*- cperl -*-
use strict;
use Getopt::Long;
my $opt_exit_code= 0;
GetOptions
(
# Exit with the specified exit code
'exit-code=i' => \$opt_exit_code
);
print "Hello stdout\n";
print STDERR "Hello stderr\n";
exit ($opt_exit_code);

View File

@ -1,4 +0,0 @@
kill -9 `cat var/run/master.pid`
# The kill may fail if process has already gone away,
# so don't use the exit code of the kill. Use 0.
exit 0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +0,0 @@
benchdir_root= $(prefix)
testdir = $(benchdir_root)/mysql-test/ndb
EXTRA_DIST = ndbcluster.sh
CLEANFILES = ndbcluster
dist_test_DATA = ndb_config_2_node.ini ndb_config_1_node.ini
test_SCRIPTS = ndbcluster
SUFFIXES = .sh
.sh:
@RM@ -f $@ $@-t
@SED@ \
-e 's!@''ndb_port''@!$(ndb_port)!g' \
-e 's!@''ndbbindir''@!$(ndbbindir)!g' \
-e 's!@''ndbtoolsdir''@!$(ndbtoolsdir)!g' \
$< > $@-t
@CHMOD@ +x $@-t
@MV@ $@-t $@
# Don't update the files from bitkeeper
%::SCCS/s.%

View File

@ -1,69 +0,0 @@
-- NDB Cluster -- Management Client --
---------------------------------------------------------------------------
NDB Cluster -- Management Client -- Help
---------------------------------------------------------------------------
HELP Print help text
HELP SHOW Help for SHOW command
HELP DEBUG Help for debug compiled version
SHOW Print information about cluster
START BACKUP [NOWAIT | WAIT STARTED | WAIT COMPLETED]
Start backup (default WAIT COMPLETED)
ABORT BACKUP <backup id> Abort backup
SHUTDOWN Shutdown all processes in cluster
CLUSTERLOG ON [<severity>] ... Enable Cluster logging
CLUSTERLOG OFF [<severity>] ... Disable Cluster logging
CLUSTERLOG TOGGLE [<severity>] ... Toggle severity filter on/off
CLUSTERLOG INFO Print cluster log information
<id> START Start DB node (started with -n)
<id> RESTART [-n] [-i] Restart DB node
<id> STOP Stop DB node
ENTER SINGLE USER MODE <api-node> Enter single user mode
EXIT SINGLE USER MODE Exit single user mode
<id> STATUS Print status
<id> CLUSTERLOG {<category>=<level>}+ Set log level for cluster log
PURGE STALE SESSIONS Reset reserved nodeid's in the mgmt server
CONNECT [<connectstring>] Connect to management server (reconnect if already connected)
QUIT Quit management client
<severity> = ALERT | CRITICAL | ERROR | WARNING | INFO | DEBUG
<category> = STARTUP | SHUTDOWN | STATISTICS | CHECKPOINT | NODERESTART | CONNECTION | INFO | ERROR | CONGESTION | DEBUG | BACKUP
<level> = 0 - 15
<id> = ALL | Any database node id
Connected to Management Server at: localhost:1186
Node 1: started (Version 5.0.3)
Node 2: started (Version 5.0.3)
Node 1: started (Version 5.0.3)
Node 2: started (Version 5.0.3)
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
Cluster logging is disabled
Cluster logging is enabled.
Cluster logging is disabled
ALL disabled
ALL enabled

View File

@ -1,17 +0,0 @@
help
all status
1 status
2 status
all clusterlog connection=8
all clusterlog startup=7
all clusterlog checkpoint=7
all clusterlog noderestart=15
all clusterlog statistics=7
all clusterlog error=7
all clusterlog info=7
all clusterlog backup=15
clusterlog off
clusterlog toggle
clusterlog off
clusterlog off all
clusterlog on all

View File

@ -1,47 +0,0 @@
[ndbd default]
NoOfReplicas= 1
MaxNoOfConcurrentTransactions= 64
MaxNoOfConcurrentOperations= CHOOSE_MaxNoOfConcurrentOperations
DataMemory= CHOOSE_DataMemory
IndexMemory= CHOOSE_IndexMemory
Diskless= CHOOSE_Diskless
TimeBetweenWatchDogCheck= 30000
DataDir= CHOOSE_FILESYSTEM
MaxNoOfOrderedIndexes= CHOOSE_MaxNoOfOrderedIndexes
MaxNoOfAttributes= CHOOSE_MaxNoOfAttributes
TimeBetweenGlobalCheckpoints= 500
NoOfFragmentLogFiles= 8
FragmentLogFileSize= 6M
DiskPageBufferMemory= CHOOSE_DiskPageBufferMemory
#
# Increase timeouts to cater for slow test-machines
# (possibly running several tests in parallell)
#
HeartbeatIntervalDbDb= 30000
HeartbeatIntervalDbApi= 30000
#TransactionDeadlockDetectionTimeout= 7500
[ndbd]
HostName= CHOOSE_HOSTNAME_1 # hostname is a valid network adress
[ndb_mgmd]
HostName= CHOOSE_HOSTNAME_1 # hostname is a valid network adress
DataDir= CHOOSE_FILESYSTEM #
PortNumber= CHOOSE_PORT_MGM
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]

View File

@ -1,55 +0,0 @@
[ndbd default]
NoOfReplicas= 2
MaxNoOfConcurrentTransactions= 64
MaxNoOfConcurrentOperations= CHOOSE_MaxNoOfConcurrentOperations
DataMemory= CHOOSE_DataMemory
IndexMemory= CHOOSE_IndexMemory
Diskless= CHOOSE_Diskless
TimeBetweenWatchDogCheck= 30000
DataDir= CHOOSE_FILESYSTEM
MaxNoOfOrderedIndexes= CHOOSE_MaxNoOfOrderedIndexes
MaxNoOfAttributes= CHOOSE_MaxNoOfAttributes
TimeBetweenGlobalCheckpoints= 500
NoOfFragmentLogFiles= 4
FragmentLogFileSize=12M
DiskPageBufferMemory= CHOOSE_DiskPageBufferMemory
# O_DIRECT has issues on 2.4 whach have not been handled, Bug #29612
#ODirect= 1
# the following parametes just function as a small regression
# test that the parameter exists
InitialNoOfOpenFiles= 27
#
# Increase timeouts to cater for slow test-machines
# (possibly running several tests in parallell)
#
HeartbeatIntervalDbDb= 30000
HeartbeatIntervalDbApi= 30000
#TransactionDeadlockDetectionTimeout= 7500
[ndbd]
HostName= CHOOSE_HOSTNAME_1 # hostname is a valid network adress
[ndbd]
HostName= CHOOSE_HOSTNAME_2 # hostname is a valid network adress
[ndb_mgmd]
HostName= CHOOSE_HOSTNAME_1 # hostname is a valid network adress
DataDir= CHOOSE_FILESYSTEM #
PortNumber= CHOOSE_PORT_MGM
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]

View File

@ -1,55 +0,0 @@
[ndbd default]
NoOfReplicas= 2
MaxNoOfConcurrentTransactions= 64
MaxNoOfConcurrentOperations= CHOOSE_MaxNoOfConcurrentOperations
DataMemory= CHOOSE_DataMemory
IndexMemory= CHOOSE_IndexMemory
Diskless= CHOOSE_Diskless
TimeBetweenWatchDogCheck= 30000
DataDir= CHOOSE_FILESYSTEM
MaxNoOfOrderedIndexes= CHOOSE_MaxNoOfOrderedIndexes
MaxNoOfAttributes= CHOOSE_MaxNoOfAttributes
TimeBetweenGlobalCheckpoints= 500
NoOfFragmentLogFiles= 3
DiskPageBufferMemory= CHOOSE_DiskPageBufferMemory
#
# Increase timeouts to cater for slow test-machines
# (possibly running several tests in parallell)
#
HeartbeatIntervalDbDb= 30000
HeartbeatIntervalDbApi= 30000
#TransactionDeadlockDetectionTimeout= 7500
[ndbd]
HostName= CHOOSE_HOSTNAME_1 # hostname is a valid network adress
[ndbd]
HostName= CHOOSE_HOSTNAME_2 # hostname is a valid network adress
[ndbd]
HostName= CHOOSE_HOSTNAME_3 # hostname is a valid network adress
[ndbd]
HostName= CHOOSE_HOSTNAME_4 # hostname is a valid network adress
[ndb_mgmd]
HostName= CHOOSE_HOSTNAME_1 # hostname is a valid network adress
DataDir= CHOOSE_FILESYSTEM #
PortNumber= CHOOSE_PORT_MGM
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]
[mysqld]

View File

@ -1,414 +0,0 @@
#!/bin/sh
# Copyright (C) 2004 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# This scripts starts the table handler ndbcluster
# configurable parameters, make sure to change in mysqlcluterd as well
port=@ndb_port@
fsdir=`pwd`
# end configurable parameters
#BASEDIR is always one above mysql-test directory
CWD=`pwd`
cd ..
BASEDIR=`pwd`
cd $CWD
# Are we using a source or a binary distribution?
if [ -d ../sql ] ; then
SOURCE_DIST=1
ndbtop=$BASEDIR/storage/ndb
exec_ndb=$ndbtop/src/kernel/ndbd
exec_mgmtsrvr=$ndbtop/src/mgmsrv/ndb_mgmd
exec_waiter=$ndbtop/tools/ndb_waiter
exec_test=$ndbtop/tools/ndb_test_platform
exec_test_ndberror=$ndbtop/src/ndbapi/ndberror_check
exec_mgmtclient=$ndbtop/src/mgmclient/ndb_mgm
else
BINARY_DIST=1
if test -x "$BASEDIR/libexec/ndbd"
then
exec_ndb=$BASEDIR/libexec/ndbd
exec_mgmtsrvr=$BASEDIR/libexec/ndb_mgmd
else
exec_ndb=$BASEDIR/bin/ndbd
exec_mgmtsrvr=$BASEDIR/bin/ndb_mgmd
fi
exec_waiter=$BASEDIR/bin/ndb_waiter
exec_test=$BASEDIR/bin/ndb_test_platform
exec_test_ndberror=
exec_mgmtclient=$BASEDIR/bin/ndb_mgm
fi
if $exec_test ; then :; else
echo "ndb not correctly compiled to support this platform"
exit 1
fi
if [ $exec_test_ndberror ] ; then
if $exec_test_ndberror ; then :; else
echo "please fix in ndberror.c"
exit 1
fi
fi
pidfile=ndbcluster.pid
cfgfile=Ndb.cfg
test_ndb=
stop_ndb=
initial_ndb=
status_ndb=
ndb_diskless=0
ndbd_nodes=2
relative_config_data_dir=
opt_core=
ndb_no_ord=512
ndb_no_attr=2048
ndb_con_op=105000
ndb_dmem=80M
ndb_imem=24M
ndb_pbmem=32M
VERBOSE=100
NDB_MGM_EXTRA_OPTS=
NDB_MGMD_EXTRA_OPTS=
NDBD_EXTRA_OPTS=
CHARSETSDIR=
while test $# -gt 0; do
case "$1" in
--test)
test_ndb=1
;;
--stop)
stop_ndb=1
;;
--initial)
flags_ndb="$flags_ndb --initial"
initial_ndb=1
;;
--debug*)
flags_ndb="$flags_ndb $1"
;;
--ndbd-nodes=*)
ndbd_nodes=`echo "$1" | sed -e "s;--ndbd-nodes=;;"`
;;
--status)
status_ndb=1
;;
--small)
ndb_no_ord=32
ndb_con_op=5000
ndb_dmem=20M
ndb_imem=1M
ndb_pbmem=4M
;;
--diskless)
ndb_diskless=1
;;
--data-dir=*)
fsdir=`echo "$1" | sed -e "s;--data-dir=;;"`
;;
--relative-config-data-dir)
relative_config_data_dir=1
;;
--port=*)
port=`echo "$1" | sed -e "s;--port=;;"`
;;
--port-base=*)
$ECHO "--port-base option depricated. Ignored."
;;
--ndb_mgm-extra-opts=*)
NDB_MGM_EXTRA_OPTS=`echo "$1" | sed -e "s;--ndb_mgm-extra-opts=;;"`
;;
--ndb_mgmd-extra-opts=*)
NDB_MGMD_EXTRA_OPTS=`echo "$1" | sed -e "s;--ndb_mgmd-extra-opts=;;"`
;;
--ndbd-extra-opts=*)
NDBD_EXTRA_OPTS=`echo "$1" | sed -e "s;--ndbd-extra-opts=;;"`
;;
--character-sets-dir=*)
CHARSETSDIR=`echo "$1" | sed -e "s;--character-sets-dir=;;"`
;;
--core)
opt_core="--core"
;;
--verbose=*)
VERBOSE=`echo "$1" | sed -e "s;--verbose=;;"`
;;
-- ) shift; break ;;
--* ) $ECHO "Unrecognized option: $1"; exit 1 ;;
* ) break ;;
esac
shift
done
fs_ndb="$fsdir/ndbcluster-$port"
config_ini=ndb/ndb_config_${ndbd_nodes}_node.ini
NDB_HOME=
if [ ! -d "$fsdir" ]; then
echo "$fsdir missing"
exit 1
fi
if [ ! -x "$exec_ndb" ]; then
echo "$exec_ndb missing"
exit 1
fi
if [ ! -x "$exec_mgmtsrvr" ]; then
echo "$exec_mgmtsrvr missing"
exit 1
fi
if [ ! -x "$exec_waiter" ]; then
echo "$exec_waiter missing"
exit 1
fi
if [ ! -f "$config_ini" ]; then
echo "$config_ini missing, unsupported number of nodes"
exit 1
fi
exec_mgmtclient="$exec_mgmtclient --no-defaults $opt_core $NDB_MGM_EXTRA_OPTS"
exec_mgmtsrvr="$exec_mgmtsrvr --no-defaults $opt_core $NDB_MGMD_EXTRA_OPTS"
exec_ndb="$exec_ndb --no-defaults $opt_core $NDBD_EXTRA_OPTS --character-sets-dir=$CHARSETSDIR"
exec_waiter="$exec_waiter --no-defaults $opt_core"
ndb_host="localhost"
ndb_mgmd_port=$port
NDB_CONNECTSTRING="host=$ndb_host:$ndb_mgmd_port"
export NDB_CONNECTSTRING
sleep_until_file_created () {
file=$1
loop=$2
org_time=$2
message=$3
while (test $loop -gt 0)
do
if [ -r $file ]
then
return 0
fi
sleep 1
loop=`expr $loop - 1`
done
if [ $message ]
then
echo $message
fi
echo "ERROR: $file was not created in $org_time seconds; Aborting"
return 1;
}
start_default_ndbcluster() {
# do some checks
if [ "$initial_ndb" ] ; then
[ -d "$fs_ndb" ] || mkdir "$fs_ndb"
fi
if [ -d "$fs_ndb" ]; then :; else
echo "$fs_ndb filesystem directory does not exist"
exit 1
fi
# Start management server as deamon
# Edit file system path and ports in config file
if [ $relative_config_data_dir ] ; then
config_fs_ndb="."
else
config_fs_ndb=$fs_ndb
fi
if [ $initial_ndb ] ; then
rm -rf $fs_ndb/ndb_* 2>&1 | cat > /dev/null
sed \
-e s,"CHOOSE_MaxNoOfAttributes","$ndb_no_attr",g \
-e s,"CHOOSE_MaxNoOfOrderedIndexes","$ndb_no_ord",g \
-e s,"CHOOSE_MaxNoOfConcurrentOperations","$ndb_con_op",g \
-e s,"CHOOSE_DataMemory","$ndb_dmem",g \
-e s,"CHOOSE_IndexMemory","$ndb_imem",g \
-e s,"CHOOSE_Diskless","$ndb_diskless",g \
-e s,"CHOOSE_HOSTNAME_".*,"$ndb_host",g \
-e s,"CHOOSE_FILESYSTEM","$config_fs_ndb",g \
-e s,"CHOOSE_PORT_MGM","$ndb_mgmd_port",g \
-e s,"CHOOSE_DiskPageBufferMemory","$ndb_pbmem",g \
< "$config_ini" \
> "$fs_ndb/config.ini"
fi
rm -f "$cfgfile" 2>&1 | cat > /dev/null
rm -f "$fs_ndb/$cfgfile" 2>&1 | cat > /dev/null
if ( cd "$fs_ndb" ; $exec_mgmtsrvr -f config.ini ) ; then :; else
echo "Unable to start $exec_mgmtsrvr from `pwd`"
exit 1
fi
if sleep_until_file_created $fs_ndb/ndb_`expr $ndbd_nodes + 1`.pid 120
then :; else
exit 1
fi
cat `find "$fs_ndb" -name 'ndb_*.pid'` > "$fs_ndb/$pidfile"
# Start database node
id=1
while [ $id -le $ndbd_nodes ]
do
if [ `expr $VERBOSE \> 1` = 1 ] ; then
echo "Starting ndbd $id($ndbd_nodes)"
fi
( cd "$fs_ndb" ; $exec_ndb $flags_ndb & )
if sleep_until_file_created $fs_ndb/ndb_${id}.pid 120
then :; else
stop_default_ndbcluster
exit 1
fi
cat `find "$fs_ndb" -name 'ndb_*.pid'` > "$fs_ndb/$pidfile"
id=`expr $id + 1`
done
# test if Ndb Cluster starts properly
if [ `expr $VERBOSE \> 1` = 1 ] ; then
echo "Waiting for NDB data nodes to start..."
fi
if ( $exec_waiter ) | grep "NDBT_ProgramExit: 0 - OK" > /dev/null 2>&1 ; then :; else
if [ `expr $VERBOSE \> 0` = 1 ] ; then
echo "Ndbcluster startup failed"
fi
stop_default_ndbcluster
exit 1
fi
if [ `expr $VERBOSE \> 1` = 1 ] ; then
echo "Ok"
fi
cat `find "$fs_ndb" -name 'ndb_*.pid'` > $fs_ndb/$pidfile
if [ `expr $VERBOSE \> 2` = 1 ] ; then
status_ndbcluster
fi
}
status_ndbcluster() {
# Start management client
$exec_mgmtclient -e show
}
stop_default_ndbcluster() {
# Start management client
exec_mgmtclient="$exec_mgmtclient --try-reconnect=1"
$exec_mgmtclient -e shutdown 2>&1 | cat > /dev/null
if [ -f "$fs_ndb/$pidfile" ] ; then
kill_pids=`cat "$fs_ndb/$pidfile"`
attempt=0
while [ $attempt -lt 10 ] ; do
new_kill_pid=""
kill_pids2=""
for p in $kill_pids ; do
kill -0 $p 2> /dev/null
if [ $? -eq 0 ] ; then
new_kill_pid="$p $new_kill_pid"
kill_pids2="-$p $kill_pids2"
fi
done
kill_pids=$new_kill_pid
if [ -z "$kill_pids" ] ; then
break
fi
sleep 1
attempt=`expr $attempt + 1`
done
if [ "$kill_pids2" != "" ] ; then
echo "Failed to shutdown ndbcluster, executing kill "$kill_pids2
kill -9 -- $kill_pids2 2> /dev/null
/bin/kill -9 -- $kill_pids2 2> /dev/null
/usr/bin/kill -9 -- $kill_pids2 2> /dev/null
kill -9 $kill_pids2 2> /dev/null
/bin/kill -9 $kill_pids2 2> /dev/null
/usr/bin/kill -9 $kill_pids2 2> /dev/null
fi
rm "$fs_ndb/$pidfile"
fi
}
initialize_ndb_test ()
{
fs_result=$fs_ndb/r
rm -rf $fs_result
mkdir $fs_result
echo ------------------
echo starting ndb tests
echo ------------------
}
do_ndb_test ()
{
test_name=$1
clusterlog=$fs_ndb/ndb_3_cluster.log
test_log_result=$fs_result/${test_name}_log.result
test_log_reject=$fs_result/${test_name}_log.reject
test_result=$fs_result/${test_name}.result
test_reject=$fs_result/${test_name}.reject
clean_log='s/.*\[MgmSrvr\]//'
cat $clusterlog ndb/${test_name}_log.result | sed -e $clean_log > $test_log_result
cp ndb/${test_name}.result $test_result
cat ndb/${test_name}.test | $exec_mgmtclient > $test_reject
cat $clusterlog | sed -e $clean_log > $test_log_reject
t="pass"
diff -C 5 $test_result $test_reject || t="fail"
printf "ndb_mgm output %20s [%s]\n" $test_name $t
t="pass"
diff -C 5 $test_log_result $test_log_reject || t="fail"
printf "clusterlog output %20s [%s]\n" $test_name $t
}
if [ $status_ndb ] ; then
status_ndbcluster
exit 0
fi
if [ $stop_ndb ] ; then
stop_default_ndbcluster
else
start_default_ndbcluster
fi
if [ $test_ndb ] ; then
initialize_ndb_test
all_tests=`ls ndb/*.test | sed "s#ndb/##" | sed "s#.test##"`
for a in $all_tests ; do
do_ndb_test $a
done
echo ------------------
echo shutting down cluster
stop_default_ndbcluster
fi
exit 0

View File

@ -1,16 +0,0 @@
-- NDB Cluster -- Management Client --
Connected to Management Server at: localhost:1186
ALL disabled
Cluster logging is enabled.
ALERT enabled
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
Node 1 is being restarted.
Executing CLUSTERLOG on node 1 OK!
Executing CLUSTERLOG on node 2 OK!
Node 1 is being restarted.
ALL enabled

View File

@ -1,12 +0,0 @@
clusterlog off all
clusterlog on
clusterlog on alert
all clusterlog connection=0
sleep 1
1 restart
sleep 5
all clusterlog connection=8
sleep 1
1 restart
sleep 10
clusterlog on all

View File

@ -1,20 +0,0 @@
ALERT -- Node 2: Network partitioning - arbitration required
ALERT -- Node 2: Arbitration won - positive reply from node 3
ALERT -- Node 2: Node 1 has failed. The Node state at failure was 0
ALERT -- Node 2: Node failure of 1 DBLQH completed
ALERT -- Node 2: Node failure of 1 DBDICT completed
ALERT -- Node 2: Node failure of 1 DBDIH completed
ALERT -- Node 2: Node failure of 1 DBTC completed
ALERT -- Node 2: Node 2 completed failure of Node 1
ALERT -- Node 2: All nodes completed failure of Node 1
ALERT -- Node 3: Node 1 Disconnected
ALERT -- Node 2: Node 1 Disconnected
ALERT -- Node 2: Network partitioning - arbitration required
ALERT -- Node 2: Arbitration won - positive reply from node 3
ALERT -- Node 2: Node 1 has failed. The Node state at failure was 0
ALERT -- Node 2: Node failure of 1 DBLQH completed
ALERT -- Node 2: Node failure of 1 DBDICT completed
ALERT -- Node 2: Node failure of 1 DBDIH completed
ALERT -- Node 2: Node failure of 1 DBTC completed
ALERT -- Node 2: Node 2 completed failure of Node 1
ALERT -- Node 2: All nodes completed failure of Node 1

View File

@ -1,24 +1,24 @@
set SQL_LOG_BIN=0;
drop table if exists t1, t2, t3, t4;
create table t4(n int);
backup table t4 to '../bogus';
backup table t4 to '../../bogus';
Table Op Msg_type Msg_text
test.t4 backup error Failed copying .frm file (errno: X)
test.t4 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t4 backup Error Can't create/write to file 'MYSQLTEST_VARDIR/bogus/t4.frm' (Errcode: X)
test.t4 backup status Operation failed
backup table t4 to '../tmp';
backup table t4 to '../../tmp';
Table Op Msg_type Msg_text
test.t4 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t4 backup status OK
backup table t4 to '../tmp';
backup table t4 to '../../tmp';
Table Op Msg_type Msg_text
test.t4 backup error Failed copying .frm file (errno: X)
test.t4 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t4 backup Error Can't create/write to file 'MYSQLTEST_VARDIR/tmp/t4.frm' (Errcode: X)
test.t4 backup status Operation failed
drop table t4;
restore table t4 from '../tmp';
restore table t4 from '../../tmp';
Table Op Msg_type Msg_text
test.t4 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t4 restore status OK
@ -27,18 +27,18 @@ count(*)
0
create table t1(n int);
insert into t1 values (23),(45),(67);
backup table t1 to '../tmp';
backup table t1 to '../../tmp';
Table Op Msg_type Msg_text
test.t1 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t1 backup status OK
drop table t1;
restore table t1 from '../bogus';
restore table t1 from '../../bogus';
Table Op Msg_type Msg_text
t1 restore error Failed copying .frm file
Warnings:
Warning 1287 The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
Error 29 File 'MYSQLTEST_VARDIR/bogus/t1.frm' not found (Errcode: X)
restore table t1 from '../tmp';
restore table t1 from '../../tmp';
Table Op Msg_type Msg_text
test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t1 restore status OK
@ -51,13 +51,13 @@ create table t2(m int not null primary key);
create table t3(k int not null primary key);
insert into t2 values (123),(145),(167);
insert into t3 values (223),(245),(267);
backup table t2,t3 to '../tmp';
backup table t2,t3 to '../../tmp';
Table Op Msg_type Msg_text
test.t2 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t2 backup status OK
test.t3 backup status OK
drop table t1,t2,t3;
restore table t1,t2,t3 from '../tmp';
restore table t1,t2,t3 from '../../tmp';
Table Op Msg_type Msg_text
test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t1 restore status OK
@ -79,13 +79,13 @@ k
245
267
drop table t1,t2,t3,t4;
restore table t1 from '../tmp';
restore table t1 from '../../tmp';
Table Op Msg_type Msg_text
test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t1 restore status OK
rename table t1 to t5;
lock tables t5 write;
backup table t5 to '../tmp';
backup table t5 to '../../tmp';
unlock tables;
Table Op Msg_type Msg_text
test.t5 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
@ -94,12 +94,12 @@ drop table t5;
DROP TABLE IF EXISTS `t+1`;
CREATE TABLE `t+1` (c1 INT);
INSERT INTO `t+1` VALUES (1), (2), (3);
BACKUP TABLE `t+1` TO '../tmp';
BACKUP TABLE `t+1` TO '../../tmp';
Table Op Msg_type Msg_text
test.t+1 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t+1 backup status OK
DROP TABLE `t+1`;
RESTORE TABLE `t+1` FROM '../tmp';
RESTORE TABLE `t+1` FROM '../../tmp';
Table Op Msg_type Msg_text
test.t+1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead
test.t+1 restore status OK

View File

@ -249,8 +249,8 @@ create table t1 (a blob);
insert into t1 values (0xEE00);
select * into outfile 'test/t1.txt' from t1;
delete from t1;
select hex(load_file('MYSQLTEST_VARDIR/master-data/test/t1.txt'));;
hex(load_file('MYSQLTEST_VARDIR/master-data/test/t1.txt'))
select hex(load_file('MYSQLD_DATADIR/test/t1.txt'));;
hex(load_file('MYSQLD_DATADIR/test/t1.txt'))
5CEE5C300A
load data infile 't1.txt' into table t1;
select hex(a) from t1;

View File

@ -685,7 +685,7 @@ asbinary(g)
drop table t1;
create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b));
alter table t1 disable keys;
load data infile '../std_data_ln/bad_gis_data.dat' into table t1;
load data infile '../../std_data/bad_gis_data.dat' into table t1;
ERROR 22004: Column set to default value; NULL supplied to NOT NULL column 'b' at row 1
alter table t1 enable keys;
drop table t1;

View File

@ -1,2 +0,0 @@
have_bug25714_exe
1

View File

@ -1,6 +1,6 @@
drop table if exists t1, t2;
create table t1 (a date, b date, c date not null, d date);
load data infile '../std_data_ln/loaddata1.dat' into table t1 fields terminated by ',';
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',';
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
Warning 1265 Data truncated for column 'c' at row 1
@ -8,7 +8,7 @@ Warning 1265 Data truncated for column 'd' at row 1
Warning 1265 Data truncated for column 'a' at row 2
Warning 1265 Data truncated for column 'b' at row 2
Warning 1265 Data truncated for column 'd' at row 2
load data infile '../std_data_ln/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES;
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES;
SELECT * from t1;
a b c d
0000-00-00 NULL 0000-00-00 0000-00-00
@ -16,7 +16,7 @@ a b c d
2003-03-03 2003-03-03 2003-03-03 NULL
2003-03-03 2003-03-03 2003-03-03 NULL
truncate table t1;
load data infile '../std_data_ln/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d);
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d);
Warnings:
Warning 1265 Data truncated for column 'c' at row 1
Warning 1265 Data truncated for column 'd' at row 1
@ -29,7 +29,7 @@ NULL 0000-00-00 0000-00-00 0000-00-00
NULL 2003-03-03 2003-03-03 NULL
drop table t1;
create table t1 (a text, b text);
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
Warnings:
Warning 1261 Row 3 doesn't contain data for all columns
select concat('|',a,'|'), concat('|',b,'|') from t1;
@ -41,7 +41,7 @@ Field 3,'Field 4|
|Field 6| | 'Field 7'|
drop table t1;
create table t1 (a int, b char(10));
load data infile '../std_data_ln/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines;
load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines;
Warnings:
Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3
Warning 1262 Row 3 was truncated; it contained more data than there were input columns
@ -55,7 +55,7 @@ a b
3 row 3
0 1234567890
truncate table t1;
load data infile '../std_data_ln/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines;
load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines;
Warnings:
Warning 1366 Incorrect integer value: '
' for column 'a' at row 4
@ -79,7 +79,7 @@ id
SET @@SQL_MODE=@OLD_SQL_MODE;
drop table t1;
create table t1 (a varchar(20), b varchar(20));
load data infile '../std_data_ln/loaddata_dq.dat' into table t1 fields terminated by ',' enclosed by '"' escaped by '"' (a,b);
load data infile '../../std_data/loaddata_dq.dat' into table t1 fields terminated by ',' enclosed by '"' escaped by '"' (a,b);
select * from t1;
a b
field1 field2
@ -141,25 +141,25 @@ SELECT t1.id, c1, c2 FROM t1 RIGHT JOIN t2 ON t1.id=t2.id WHERE c1 != c2;
id c1 c2
DROP TABLE t1,t2;
create table t1 (a int default 100, b int, c varchar(60));
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1 (a, @b) set b=@b+10, c=concat("b=",@b);
load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set b=@b+10, c=concat("b=",@b);
select * from t1;
a b c
NULL 20 b=10
NULL 25 b=15
truncate table t1;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1 (a, @b) set c= if(a is null,"oops",a);
load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set c= if(a is null,"oops",a);
select * from t1;
a b c
NULL NULL oops
NULL NULL oops
truncate table t1;
set @c:=123;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1 (@a, b) set c= if(@a is null,@c,b);
load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, b) set c= if(@a is null,@c,b);
select * from t1;
a b c
100 10 123
100 15 123
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1 (@a, @b);
load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, @b);
select * from t1;
a b c
100 10 123
@ -170,7 +170,7 @@ select @a, @b;
@a @b
NULL 15
truncate table t1;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1 set c=b;
load data infile '../../std_data/rpl_loaddata.dat' into table t1 set c=b;
Warnings:
Warning 1261 Row 1 doesn't contain data for all columns
Warning 1261 Row 2 doesn't contain data for all columns
@ -179,25 +179,25 @@ a b c
NULL 10 10
NULL 15 15
truncate table t1;
load data infile '../std_data_ln/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, b) set c="Wow";
load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, b) set c="Wow";
select * from t1;
a b c
1 2 Wow
3 4 Wow
5 6 Wow
truncate table t1;
load data infile '../std_data_ln/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, b) set c=concat(a,"+",b,"+",@c,"+",b,"+",if(c is null,"NIL",c));
load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, b) set c=concat(a,"+",b,"+",@c,"+",b,"+",if(c is null,"NIL",c));
select * from t1;
a b c
1 2 1+2+123+2+NIL
3 4 3+4+123+4+NIL
5 6 5+6+123+6+NIL
load data infile '../std_data_ln/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, @b);
load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, @b);
ERROR HY000: Can't load value from file with fixed size rows to variable
create table t2 (num int primary key, str varchar(10));
insert into t2 values (10,'Ten'), (15,'Fifteen');
truncate table t1;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1 (@dummy,@n) set a= @n, c= (select str from t2 where num=@n);
load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@dummy,@n) set a= @n, c= (select str from t2 where num=@n);
select * from t1;
a b c
10 NULL Ten

View File

@ -2,7 +2,7 @@ SET SESSION STORAGE_ENGINE = InnoDB;
drop table if exists t1;
create table t1 (id int unsigned not null auto_increment primary key, a text, b text);
start transaction;
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''' (a, b);
load data infile 'LOAD_FILE' into table t1 fields terminated by ',' enclosed by '''' (a, b);
Warnings:
Warning 1261 Row 3 doesn't contain data for all columns
commit;
@ -11,7 +11,7 @@ count(*)
4
truncate table t1;
start transaction;
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''' (a, b);
load data infile 'LOAD_FILE' into table t1 fields terminated by ',' enclosed by '''' (a, b);
Warnings:
Warning 1261 Row 3 doesn't contain data for all columns
rollback;

View File

@ -1,14 +1,15 @@
reset master;
set timestamp=1000000000;
drop table if exists t1,t2,t3,t4,t5,t03,t04;
create table t1 (word varchar(20));
create table t2 (id int auto_increment not null primary key);
insert into t1 values ("abirvalg");
insert into t2 values ();
load data infile '../std_data_ln/words.dat' into table t1;
load data infile '../std_data_ln/words.dat' into table t1;
load data infile '../std_data_ln/words.dat' into table t1;
load data infile '../std_data_ln/words.dat' into table t1;
load data infile '../std_data_ln/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
load data infile '../../std_data/words.dat' into table t1;
insert into t1 values ("Alas");
flush logs;
@ -284,17 +285,17 @@ call p1();
drop procedure p1;
flush logs;
create table t1 (a varchar(64) character set utf8);
load data infile '../std_data_ln/loaddata6.dat' into table t1;
load data infile '../../std_data/loaddata6.dat' into table t1;
set character_set_database=koi8r;
load data infile '../std_data_ln/loaddata6.dat' into table t1;
load data infile '../../std_data/loaddata6.dat' into table t1;
set character_set_database=latin1;
load data infile '../std_data_ln/loaddata6.dat' into table t1;
load data infile '../std_data_ln/loaddata6.dat' into table t1;
load data infile '../../std_data/loaddata6.dat' into table t1;
load data infile '../../std_data/loaddata6.dat' into table t1;
set character_set_database=koi8r;
load data infile '../std_data_ln/loaddata6.dat' into table t1;
load data infile '../../std_data/loaddata6.dat' into table t1;
set character_set_database=latin1;
load data infile '../std_data_ln/loaddata6.dat' into table t1;
load data infile '../std_data_ln/loaddata6.dat' into table t1 character set koi8r;
load data infile '../../std_data/loaddata6.dat' into table t1;
load data infile '../../std_data/loaddata6.dat' into table t1 character set koi8r;
select hex(a) from t1;
hex(a)
C3BF

View File

@ -5,7 +5,7 @@ insert into t1 values (3);
update t1 set a=a+2 where a=2;
update t1 set a=a+2 where a=3;
create table t2 (word varchar(20));
load data infile '../std_data_ln/words.dat' into table t2;
load data infile '../../std_data/words.dat' into table t2;
flush logs;
drop table t1;
drop table t2;
@ -89,7 +89,7 @@ aberration
flush logs;
drop table t2;
create table t2 (word varchar(20));
load data infile '../std_data_ln/words.dat' into table t2;
load data infile '../../std_data/words.dat' into table t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;

Binary file not shown.

View File

@ -74,8 +74,8 @@ partitions 3
partition x2 tablespace ts2,
partition x3 tablespace ts3);
ERROR HY000: Field in list of fields for partition function not found in table
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -151,8 +151,8 @@ partitions 2
(partition x1 values less than (4),
partition x2 values less than (5));
ERROR HY000: Only RANGE PARTITIONING can use VALUES LESS THAN in partition definition
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -164,8 +164,8 @@ partitions 2
(partition x1 values in (4),
partition x2 values in (5));
ERROR HY000: Only LIST PARTITIONING can use VALUES IN in partition definition
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -177,8 +177,8 @@ partitions 2
(partition x1 values in (4,6),
partition x2 values in (5,7));
ERROR HY000: Only LIST PARTITIONING can use VALUES IN in partition definition
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -188,8 +188,8 @@ primary key (a,b))
partition by key (a)
subpartition by key (b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -199,8 +199,8 @@ primary key (a,b))
partition by key (a)
subpartition by key (a, b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -210,8 +210,8 @@ primary key (a,b))
partition by key (a)
subpartition by hash (a+b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -221,8 +221,8 @@ primary key (a,b))
partition by key (a)
subpartition by key (b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -232,8 +232,8 @@ primary key (a,b))
partition by key (a)
subpartition by key (a, b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -243,8 +243,8 @@ primary key (a,b))
partition by key (a)
subpartition by hash (a+b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -264,8 +264,8 @@ subpartition by hash (sin(a+b))
(partition x1 (subpartition x11, subpartition x12),
partition x2 (subpartition x21, subpartition x22));
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -289,8 +289,8 @@ subpartition by key (a,d)
(partition x1 values less than (1) (subpartition x11, subpartition x12),
partition x2 values less than (2) (subpartition x21, subpartition x22));
ERROR HY000: Field in list of fields for partition function not found in table
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,
@ -317,8 +317,8 @@ c int not null,
primary key(a,b))
partition by range (a);
ERROR HY000: For RANGE partitions each partition must be defined
select load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par');
load_file('$MYSQLTEST_VARDIR/master-data/test/t1.par')
select load_file('$MYSQLD_DATADIR/test/t1.par');
load_file('$MYSQLD_DATADIR/test/t1.par')
NULL
CREATE TABLE t1 (
a int not null,

View File

@ -1,13 +1,13 @@
create table t1 (a int) engine myisam
partition by range (a)
subpartition by hash (a)
(partition p0 VALUES LESS THAN (1) DATA DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpdata' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpinx'
(partition p0 VALUES LESS THAN (1) DATA DIRECTORY = 'MYSQLD_DATADIR/tmpdata' INDEX DIRECTORY = 'MYSQLD_DATADIR/tmpinx'
(SUBPARTITION subpart00, SUBPARTITION subpart01));
Checking if file exists before alter
ALTER TABLE t1 REORGANIZE PARTITION p0 INTO
(partition p1 VALUES LESS THAN (1) DATA DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpdata' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpinx'
(partition p1 VALUES LESS THAN (1) DATA DIRECTORY = 'MYSQLD_DATADIR/tmpdata' INDEX DIRECTORY = 'MYSQLD_DATADIR/tmpinx'
(SUBPARTITION subpart10, SUBPARTITION subpart11),
partition p2 VALUES LESS THAN (2) DATA DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpdata' INDEX DIRECTORY = 'MYSQLTEST_VARDIR/master-data/tmpinx'
partition p2 VALUES LESS THAN (2) DATA DIRECTORY = 'MYSQLD_DATADIR/tmpdata' INDEX DIRECTORY = 'MYSQLD_DATADIR/tmpinx'
(SUBPARTITION subpart20, SUBPARTITION subpart21));
Checking if file exists after alter
drop table t1;

View File

@ -13,11 +13,11 @@ USE test;
CREATE TABLE t1 (a INT)
PARTITION BY LIST (a) (
PARTITION p0 VALUES IN (0)
DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2'
INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2',
DATA DIRECTORY 'MYSQLD_DATADIR/mysqltest2'
INDEX DIRECTORY 'MYSQLD_DATADIR/mysqltest2',
PARTITION p1 VALUES IN (1)
DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test'
INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test',
DATA DIRECTORY 'MYSQLD_DATADIR/test'
INDEX DIRECTORY 'MYSQLD_DATADIR/test',
PARTITION p2 VALUES IN (2)
);
# without the patch for bug#32091 this would create
@ -49,32 +49,32 @@ USE mysqltest2;
CREATE TABLE t1 (a INT)
PARTITION BY LIST (a) (
PARTITION p0 VALUES IN (0)
DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2'
INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2',
DATA DIRECTORY 'MYSQLD_DATADIR/mysqltest2'
INDEX DIRECTORY 'MYSQLD_DATADIR/mysqltest2',
PARTITION p1 VALUES IN (1)
DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test'
INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test'
DATA DIRECTORY 'MYSQLD_DATADIR/test'
INDEX DIRECTORY 'MYSQLD_DATADIR/test'
);
# user mysqltest_1:
USE test;
CREATE TABLE t1 (a INT)
PARTITION BY LIST (a) (
PARTITION p0 VALUES IN (0)
DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2'
INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2',
DATA DIRECTORY 'MYSQLD_DATADIR/mysqltest2'
INDEX DIRECTORY 'MYSQLD_DATADIR/mysqltest2',
PARTITION p1 VALUES IN (1)
DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test'
INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test'
DATA DIRECTORY 'MYSQLD_DATADIR/test'
INDEX DIRECTORY 'MYSQLD_DATADIR/test'
);
Got one of the listed errors
CREATE TABLE t1 (a INT)
PARTITION BY LIST (a) (
PARTITION p0 VALUES IN (0)
DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test'
INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test',
DATA DIRECTORY 'MYSQLD_DATADIR/test'
INDEX DIRECTORY 'MYSQLD_DATADIR/test',
PARTITION p1 VALUES IN (1)
DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2'
INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2'
DATA DIRECTORY 'MYSQLD_DATADIR/mysqltest2'
INDEX DIRECTORY 'MYSQLD_DATADIR/mysqltest2'
);
Got one of the listed errors
# user root (cleanup):

View File

@ -669,7 +669,7 @@ word
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
load data infile 'MYSQLTEST_VARDIR/std_data_ln/words.dat' into table t1;
load data infile 'MYSQLTEST_VARDIR/std_data/words.dat' into table t1;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0

View File

@ -544,7 +544,7 @@ drop procedure if exists into_outfile|
create procedure into_outfile(x char(16), y int)
begin
insert into test.t1 values (x, y);
select * into outfile "../tmp/spout" from test.t1;
select * into outfile "MYSQLTEST_VARDIR/tmp/spout" from test.t1;
insert into test.t1 values (concat(x, "2"), y+2);
end|
call into_outfile("ofile", 1)|
@ -554,7 +554,7 @@ drop procedure if exists into_dumpfile|
create procedure into_dumpfile(x char(16), y int)
begin
insert into test.t1 values (x, y);
select * into dumpfile "../tmp/spdump" from test.t1 limit 1;
select * into dumpfile "MYSQLTEST_VARDIR/tmp/spdump" from test.t1 limit 1;
insert into test.t1 values (concat(x, "2"), y+2);
end|
call into_dumpfile("dfile", 1)|
@ -4401,9 +4401,9 @@ drop procedure if exists bug13012|
create procedure bug13012()
BEGIN
REPAIR TABLE t1;
BACKUP TABLE t1 to '../tmp';
BACKUP TABLE t1 to '../../tmp';
DROP TABLE t1;
RESTORE TABLE t1 FROM '../tmp';
RESTORE TABLE t1 FROM '../../tmp';
END|
call bug13012()|
Table Op Msg_type Msg_text

Some files were not shown because too many files have changed in this diff Show More