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:
17
.bzrignore
17
.bzrignore
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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.%
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 */;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 #
|
||||
|
@ -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;
|
||||
|
||||
#
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
25
mysql-test/include/default_my.cnf
Normal file
25
mysql-test/include/default_my.cnf
Normal 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
|
21
mysql-test/include/default_mysqld.cnf
Normal file
21
mysql-test/include/default_mysqld.cnf
Normal 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
|
||||
|
27
mysql-test/include/default_ndbd.cnf
Normal file
27
mysql-test/include/default_ndbd.cnf
Normal 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
|
@ -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;
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
@ -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;
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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;
|
||||
|
621
mysql-test/lib/My/ConfigFactory.pm
Normal file
621
mysql-test/lib/My/ConfigFactory.pm
Normal 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;
|
||||
|
83
mysql-test/lib/My/File/Path.pm
Normal file
83
mysql-test/lib/My/File/Path.pm
Normal 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
190
mysql-test/lib/My/Find.pm
Normal 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;
|
196
mysql-test/lib/My/Options.pm
Normal file
196
mysql-test/lib/My/Options.pm
Normal 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;
|
||||
|
95
mysql-test/lib/My/Platform.pm
Normal file
95
mysql-test/lib/My/Platform.pm
Normal 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;
|
512
mysql-test/lib/My/SafeProcess.pm
Normal file
512
mysql-test/lib/My/SafeProcess.pm
Normal 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;
|
236
mysql-test/lib/My/SafeProcess/Base.pm
Normal file
236
mysql-test/lib/My/SafeProcess/Base.pm
Normal 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;
|
||||
|
17
mysql-test/lib/My/SafeProcess/CMakeLists.txt
Normal file
17
mysql-test/lib/My/SafeProcess/CMakeLists.txt
Normal 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)
|
21
mysql-test/lib/My/SafeProcess/Makefile.am
Normal file
21
mysql-test/lib/My/SafeProcess/Makefile.am
Normal 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.%
|
56
mysql-test/lib/My/SafeProcess/safe_kill_win.cc
Executable file
56
mysql-test/lib/My/SafeProcess/safe_kill_win.cc
Executable 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);
|
||||
}
|
||||
|
267
mysql-test/lib/My/SafeProcess/safe_process.cc
Normal file
267
mysql-test/lib/My/SafeProcess/safe_process.cc
Normal 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);
|
||||
}
|
||||
|
151
mysql-test/lib/My/SafeProcess/safe_process.pl
Normal file
151
mysql-test/lib/My/SafeProcess/safe_process.pl
Normal 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);
|
||||
|
||||
|
312
mysql-test/lib/My/SafeProcess/safe_process_win.cc
Executable file
312
mysql-test/lib/My/SafeProcess/safe_process_win.cc
Executable 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);
|
||||
}
|
||||
|
@ -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
1112
mysql-test/lib/mtr_cases.pm
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
@ -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;
|
@ -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;
|
||||
|
@ -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
@ -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;
|
@ -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();
|
||||
|
@ -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
27
mysql-test/lib/t/Base.t
Normal 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
33
mysql-test/lib/t/Find.t
Normal 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
127
mysql-test/lib/t/Options.t
Normal 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";
|
||||
}
|
18
mysql-test/lib/t/Platform.t
Normal file
18
mysql-test/lib/t/Platform.t
Normal 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";
|
102
mysql-test/lib/t/SafeProcess.t
Normal file
102
mysql-test/lib/t/SafeProcess.t
Normal 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");
|
||||
|
||||
}
|
149
mysql-test/lib/t/SafeProcessStress.pl
Executable file
149
mysql-test/lib/t/SafeProcessStress.pl
Executable 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);
|
34
mysql-test/lib/t/copytree.t
Normal file
34
mysql-test/lib/t/copytree.t
Normal 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");
|
||||
|
38
mysql-test/lib/t/dummyd.pl
Normal file
38
mysql-test/lib/t/dummyd.pl
Normal 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
52
mysql-test/lib/t/rmtree.t
Normal 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
131
mysql-test/lib/t/testMyConfig.t
Executable 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";
|
||||
|
98
mysql-test/lib/t/testMyConfigFactory.t
Executable file
98
mysql-test/lib/t/testMyConfigFactory.t
Executable 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
21
mysql-test/lib/t/test_child.pl
Executable 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);
|
||||
|
||||
|
@ -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
@ -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.%
|
@ -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
|
@ -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
|
@ -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]
|
@ -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]
|
@ -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]
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -1,2 +0,0 @@
|
||||
have_bug25714_exe
|
||||
1
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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.
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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
Reference in New Issue
Block a user