summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--README65
-rw-r--r--client/mysqltest.c3
-rw-r--r--configure.in99
-rw-r--r--include/my_global.h3
-rw-r--r--include/my_pthread.h5
-rw-r--r--include/violite.h4
-rw-r--r--mysql-test/r/analyse.result6
-rw-r--r--mysql-test/r/connect.result6
-rw-r--r--mysql-test/r/create.result28
-rw-r--r--mysql-test/r/group_by.result9
-rw-r--r--mysql-test/r/innodb.result11
-rw-r--r--mysql-test/r/insert_select.result10
-rw-r--r--mysql-test/r/ndb_autodiscover.result2
-rw-r--r--mysql-test/r/olap.result13
-rw-r--r--mysql-test/r/ps_1general.result12
-rw-r--r--mysql-test/r/ps_2myisam.result6
-rw-r--r--mysql-test/r/ps_3innodb.result6
-rw-r--r--mysql-test/r/ps_4heap.result6
-rw-r--r--mysql-test/r/ps_5merge.result12
-rw-r--r--mysql-test/r/ps_6bdb.result6
-rw-r--r--mysql-test/r/ps_7ndb.result6
-rw-r--r--mysql-test/r/rpl_slave_status.result2
-rw-r--r--mysql-test/r/temp_table.result2
-rw-r--r--mysql-test/r/warnings.result4
-rw-r--r--mysql-test/t/analyse.test9
-rw-r--r--mysql-test/t/connect.test18
-rw-r--r--mysql-test/t/create.test13
-rw-r--r--mysql-test/t/group_by.test10
-rw-r--r--mysql-test/t/innodb.test10
-rw-r--r--mysql-test/t/insert_select.test10
-rw-r--r--mysql-test/t/olap.test13
-rw-r--r--mysql-test/t/rpl_slave_status.test4
-rw-r--r--ndb/include/kernel/signaldata/BackupImpl.hpp9
-rw-r--r--ndb/include/kernel/signaldata/BackupSignalData.hpp5
-rw-r--r--ndb/include/kernel/signaldata/NFCompleteRep.hpp18
-rw-r--r--ndb/include/kernel/signaldata/NodeFailRep.hpp28
-rw-r--r--ndb/include/util/Parser.hpp2
-rw-r--r--ndb/src/common/portlib/NdbThread.c10
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.cpp104
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.hpp3
-rw-r--r--ndb/src/kernel/blocks/dblqh/Dblqh.hpp22
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhMain.cpp140
-rw-r--r--ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp11
-rw-r--r--ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp11
-rw-r--r--ndb/src/kernel/main.cpp2
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp3
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp265
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.hpp3
-rw-r--r--ndb/src/ndbapi/Makefile.am3
-rw-r--r--ndb/src/ndbapi/NdbConnection.cpp26
-rw-r--r--ndb/src/ndbapi/SignalSender.cpp280
-rw-r--r--ndb/src/ndbapi/SignalSender.hpp83
-rw-r--r--ndb/test/include/NDBT_Test.hpp3
-rw-r--r--ndb/test/ndbapi/Makefile.am5
-rw-r--r--ndb/test/ndbapi/bank/Bank.cpp168
-rw-r--r--ndb/test/ndbapi/bank/Bank.hpp2
-rw-r--r--ndb/test/ndbapi/testSRBank.cpp246
-rw-r--r--ndb/test/src/NDBT_Test.cpp9
-rw-r--r--ndb/test/src/NdbBackup.cpp9
-rw-r--r--ndb/test/src/UtilTransactions.cpp22
-rw-r--r--sql-common/client.c2
-rw-r--r--sql/examples/ha_archive.cc2
-rw-r--r--sql/filesort.cc2
-rw-r--r--sql/item.cc9
-rw-r--r--sql/item_cmpfunc.cc20
-rw-r--r--sql/item_cmpfunc.h2
-rw-r--r--sql/net_serv.cc2
-rw-r--r--sql/sql_analyse.cc13
-rw-r--r--sql/sql_class.cc4
-rw-r--r--sql/sql_db.cc6
-rw-r--r--sql/sql_parse.cc3
-rw-r--r--sql/sql_select.cc17
-rw-r--r--sql/sql_show.cc34
-rw-r--r--sql/sql_table.cc28
-rw-r--r--tests/mysql_client_test.c6
-rw-r--r--vio/vio.c4
-rw-r--r--vio/vio_priv.h2
-rw-r--r--vio/viosocket.c9
-rw-r--r--vio/viossl.c9
80 files changed, 1450 insertions, 630 deletions
diff --git a/.bzrignore b/.bzrignore
index f9f9c146692..ce63dcaf5a9 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -1056,3 +1056,4 @@ vio/viotest-ssl
ndb/tools/ndb_config
support-files/MacOSX/postflight
support-files/MacOSX/preflight
+ndb/test/ndbapi/testSRBank
diff --git a/README b/README
index 29851358765..88cdaaf67d4 100644
--- a/README
+++ b/README
@@ -1,52 +1,35 @@
-This is a release of MySQL, a GPL (free) SQL database server (more
-licence information in the PUBLIC file and in the reference manual).
+This is a release of MySQL, a dual-license SQL database server.
+MySQL is brought to you by the MySQL team at MySQL AB.
-Please read the "Upgrading from..." section in the manual first, if you are
-migrating from older versions of MySQL!
+License information can be found in these files:
+- For GPL (free) distributions, see the COPYING file.
+- For commercial distributions, see the MySQLEULA.txt file.
-The latest information about MySQL can be found at:
-http://www.mysql.com
-To see what it can do take a look at the features section in the
-manual.
+For further information about MySQL or additional documentation, see:
+- The latest information about MySQL: http://www.mysql.com
+- The current MySQL documentation: http:/dev.mysql.com/doc
-For installation instructions see the Installation chapter in the
-manual.
+Some manual sections of special interest:
-For future plans see the TODO appendix in the manual.
+- If you are migrating from an older version of MySQL, please read the
+ "Upgrading from..." section first!
+- To see what MySQL can do, take a look at the features section.
+- For installation instructions, see the Installation chapter.
+- For future plans, see the TODO appendix.
+- For the new features/bugfix history, see the News appendix.
+- For the currently known bugs/misfeatures (known errors) see the problems
+ appendix.
+- For a list of developers and other contributors, see the Credits
+ appendix.
-New features/bug fixes history is in the news appendix in the manual.
-
-For the currently known bugs/misfeatures (known errors) see the bugs
-appendix in the manual.
-
-For examples of SQL and benchmarking information see the bench
-directory.
-
-The manual mentioned above can be found in the Docs directory. The
-manual is available in the following formats: as plain ASCII text in
-Docs/manual.txt, in HTML format in Docs/manual_toc.html, as GNU Info in
-Docs/mysql.info and as PostScript in Docs/manual.ps.
-
-MySQL is brought to you by the MySQL team at MySQL AB
-
-For a list of developers and other contributors, see the Credits appendix
-in the manual.
+A local copy of the MySQL Reference Manual can be found in the Docs
+directory in GNU Info format. You can also browse the manual online or
+download it in any of several formats at the URL given earlier in this
+file.
************************************************************
IMPORTANT:
-Send bug (error) reports, questions and comments to the mailing list
-at mysql@lists.mysql.com
-
-Please use the 'mysqlbug' script when posting bug reports or questions
-about MySQL. mysqlbug will gather some information about your system
-and start your editor with a form in which you can describe your
-problem. Bug reports might be silently ignored by the MySQL
-maintainers if there is not a good reason included in the report as to
-why mysqlbug has not been used. A report that says 'MySQL does not
-work for me. Why?' is not considered a valid bug report.
-
-The mysqlbug script can be found in the 'scripts' directory of the
-distribution, that is '<where-you-installed-mysql>/scripts'.
+Bug or error reports should be sent to http://bugs.mysql.com.
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 3e2cde92aa9..374f0cb1336 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -2170,7 +2170,8 @@ int read_line(char *buf, int size)
if (feof(cur_file->file))
{
found_eof:
- if (cur_file->file != stdin){
+ if (cur_file->file != stdin)
+ {
my_fclose(cur_file->file, MYF(0));
cur_file->file= 0;
}
diff --git a/configure.in b/configure.in
index f3840e6f1a8..97eb0cb0edf 100644
--- a/configure.in
+++ b/configure.in
@@ -381,19 +381,19 @@ case "$target_os" in
;;
esac
;;
- sysv5UnixWare*)
+ sysv5UnixWare* | sysv5OpenUNIX8*)
if test "$GCC" != "yes"; then
- # We are using built-in inline function
+ # Use the built-in alloca()
CFLAGS="$CFLAGS -Kalloca"
fi
CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA"
;;
- sysv5OpenUNIX8*)
+ sysv5SCO_SV6.0.0*)
if test "$GCC" != "yes"; then
- # We are using built-in inline function
+ # Use the built-in alloca()
CFLAGS="$CFLAGS -Kalloca"
+ CXXFLAGS="$CFLAGS -Kalloca"
fi
- CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA"
;;
esac
AC_SUBST(CC)
@@ -1128,6 +1128,15 @@ case $SYSTEM_TYPE in
MAX_C_OPTIMIZE="-O"
fi
;;
+ *darwin9*)
+ if test "$ac_cv_prog_gcc" = "yes"
+ then
+ FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT"
+ CFLAGS="$CFLAGS $FLAGS"
+ CXXFLAGS="$CXXFLAGS $FLAGS"
+ MAX_C_OPTIMIZE="-O"
+ fi
+ ;;
*freebsd*)
echo "Adding fix for interrupted reads"
OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
@@ -1440,8 +1449,6 @@ then
if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
then
AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1])
- else
- AC_DEFINE(HAVE_UNIXWARE7_POSIX, [1])
fi
AC_MSG_RESULT("yes")
# We must have cc
@@ -1467,87 +1474,41 @@ then
AC_MSG_RESULT("no")
fi
fi
-# Hack for SCO UnixWare7
+
+#
+# Check for SCO threading libraries
#
if test "$with_named_thread" = "no"
then
- AC_MSG_CHECKING("SCO UnixWare7 native threads")
- if expr "$SYSTEM_TYPE" : ".*UnixWare*" > /dev/null
+ AC_MSG_CHECKING([SCO OpenServer 6, UnixWare 7 or OpenUNIX 8 native threads])
+ if expr "$SYSTEM_TYPE" : ".*UnixWare.*" > /dev/null || \
+ expr "$SYSTEM_TYPE" : ".*SCO_SV6.*" > /dev/null || \
+ expr "$SYSTEM_TYPE" : ".*OpenUNIX.*" > /dev/null
then
if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
then
MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
- if expr "$CC" : ".*gcc.*"
- then
- with_named_thread="-pthread -lsocket -lnsl"
- else
- with_named_thread="-Kthread -lsocket -lnsl"
- fi
- if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
- then
- AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1])
- else
- AC_DEFINE(HAVE_UNIXWARE7_POSIX, [1])
- fi
- # We must have cc
- AC_MSG_CHECKING("for gcc")
- if expr "$CC" : ".*gcc.*"
+ if expr "$CC" : ".*gcc.*" > /dev/null
then
+ with_named_thread="-pthread -lsocket -lnsl"
CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
else
+ with_named_thread="-Kthread -lsocket -lnsl"
CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
fi
- AC_MSG_RESULT("yes")
- else
- { echo "configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
- fi
- else
- AC_MSG_RESULT("no")
- fi
-fi
-
-# Hack for Caldera OpenUNIX8
-#
-if test "$with_named_thread" = "no"
-then
- AC_MSG_CHECKING("OpenUNIX8 native threads")
- if expr "$SYSTEM_TYPE" : ".*OpenUNIX*" > /dev/null
- then
- if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
- then
- MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
- if expr "$CC" : ".*gcc.*"
- then
- with_named_thread="-pthread -lsocket -lnsl"
- else
- with_named_thread="-Kthread -lsocket -lnsl"
- fi
if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
then
- AC_DEFINE([HAVE_UNIXWARE7_THREADS], [1],
- [UNIXWARE7 threads are not posix])
- else
- AC_DEFINE([HAVE_UNIXWARE7_POSIX], [1],
- [new UNIXWARE7 threads that are not yet posix])
- fi
- # We must have cc
- AC_MSG_CHECKING("for gcc")
- if expr "$CC" : ".*gcc.*"
- then
- CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- else
- CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
+ AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1], [Have UnixWare 7 (or similar) almost-POSIX threading library])
fi
- AC_MSG_RESULT("yes")
+ AC_MSG_RESULT(yes)
else
- { echo "configure: error: Can't find thread libs on Caldera OpenUNIX 8. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
+ AC_MSG_RESULT(failed)
+ { echo "configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
fi
else
- AC_MSG_RESULT("no")
+ AC_MSG_RESULT(no)
fi
fi
@@ -3016,7 +2977,7 @@ then
AC_CONFIG_FILES(bdb/Makefile)
echo "CONFIGURING FOR BERKELEY DB"
- bdb_conf_flags="--disable-shared"
+ bdb_conf_flags="--disable-shared --build=$build_alias"
if test $with_debug = "yes"
then
bdb_conf_flags="$bdb_conf_flags --enable-debug --enable-diagnostic"
diff --git a/include/my_global.h b/include/my_global.h
index f3d42106458..0f99aacd079 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -801,6 +801,7 @@ typedef off_t os_off_t;
#define socket_errno WSAGetLastError()
#define SOCKET_EINTR WSAEINTR
#define SOCKET_EAGAIN WSAEINPROGRESS
+#define SOCKET_ETIMEDOUT WSAETIMEDOUT
#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
#define SOCKET_ENFILE ENFILE
#define SOCKET_EMFILE EMFILE
@@ -808,6 +809,7 @@ typedef off_t os_off_t;
#define socket_errno sock_errno()
#define SOCKET_EINTR SOCEINTR
#define SOCKET_EAGAIN SOCEINPROGRESS
+#define SOCKET_ETIMEDOUT SOCKET_EINTR
#define SOCKET_EWOULDBLOCK SOCEWOULDBLOCK
#define SOCKET_ENFILE SOCENFILE
#define SOCKET_EMFILE SOCEMFILE
@@ -817,6 +819,7 @@ typedef off_t os_off_t;
#define closesocket(A) close(A)
#define SOCKET_EINTR EINTR
#define SOCKET_EAGAIN EAGAIN
+#define SOCKET_ETIMEDOUT SOCKET_EINTR
#define SOCKET_EWOULDBLOCK EWOULDBLOCK
#define SOCKET_ENFILE ENFILE
#define SOCKET_EMFILE EMFILE
diff --git a/include/my_pthread.h b/include/my_pthread.h
index fde62655c5f..d83ddf62a80 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -298,11 +298,6 @@ extern int my_pthread_create_detached;
int sigwait(sigset_t *set, int *sig);
#endif
-#if defined(HAVE_UNIXWARE7_POSIX)
-#undef HAVE_NONPOSIX_SIGWAIT
-#define HAVE_NONPOSIX_SIGWAIT /* sigwait takes only 1 argument */
-#endif
-
#ifndef HAVE_NONPOSIX_SIGWAIT
#define my_sigwait(A,B) sigwait((A),(B))
#else
diff --git a/include/violite.h b/include/violite.h
index 4b644051dd2..fbc6a546cc5 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -68,6 +68,8 @@ int vio_fastsend(Vio *vio);
int vio_keepalive(Vio *vio, my_bool onoff);
/* Whenever we should retry the last read/write operation. */
my_bool vio_should_retry(Vio *vio);
+/* Check that operation was timed out */
+my_bool vio_was_interrupted(Vio *vio);
/* Short text description of the socket for those, who are curious.. */
const char* vio_description(Vio *vio);
/* Return the type of the connection */
@@ -146,6 +148,7 @@ int vio_close_shared_memory(Vio * vio);
#define vio_fastsend(vio) (vio)->fastsend(vio)
#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive)
#define vio_should_retry(vio) (vio)->should_retry(vio)
+#define vio_was_interrupted(vio) (vio)->was_interrupted(vio)
#define vio_close(vio) ((vio)->vioclose)(vio)
#define vio_peer_addr(vio, buf, prt) (vio)->peer_addr(vio, buf, prt)
#define vio_in_addr(vio, in) (vio)->in_addr(vio, in)
@@ -188,6 +191,7 @@ struct st_vio
my_bool (*peer_addr)(Vio*, char *, uint16*);
void (*in_addr)(Vio*, struct in_addr*);
my_bool (*should_retry)(Vio*);
+ my_bool (*was_interrupted)(Vio*);
int (*vioclose)(Vio*);
void (*timeout)(Vio*, unsigned int which, unsigned int timeout);
void *ssl_arg;
diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index 09c606b5a04..0ebd4a3e409 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -102,3 +102,9 @@ select * from t1 procedure analyse();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
test.t1.v " \\ 1 19 0 0 3.7619 NULL ENUM('"','""','"c','\'\0\\"','\'','\'\'','\'b','a\0\0\0b','a\0','a""""b','a\'\'\'\'b','abc','abc\'def\\hij"klm\0opq','a\\\\\\\\b','b\'','c"','d\\','The\ZEnd','\\','\\d','\\\\') NOT NULL
drop table t1;
+create table t1 (d double);
+insert into t1 values (100000);
+select * from t1 procedure analyse (1,1);
+Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
+test.t1.d 100000 100000 6 6 0 0 100000 0 MEDIUMINT(6) UNSIGNED NOT NULL
+drop table t1;
diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result
index edf30e7f6e4..68c86b80e60 100644
--- a/mysql-test/r/connect.result
+++ b/mysql-test/r/connect.result
@@ -1,3 +1,4 @@
+drop table if exists t1,t2;
show tables;
Tables_in_mysql
columns_priv
@@ -65,3 +66,8 @@ show tables;
Tables_in_test
delete from mysql.user where user=_binary"test";
flush privileges;
+create table t1 (id integer not null auto_increment primary key);
+create temporary table t2(id integer not null auto_increment primary key);
+set @id := 1;
+delete from t1 where id like @id;
+drop table t1;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 95757fbd7dc..6edd4cbc48f 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -9,6 +9,8 @@ NULL
drop table if exists t1;
create table t1 (b char(0) not null);
create table if not exists t1 (b char(0) not null);
+Warnings:
+Note 1050 Table 't1' already exists
insert into t1 values (""),(null);
Warnings:
Warning 1263 Data truncated; NULL supplied to NOT NULL column 'b' at row 2
@@ -232,9 +234,13 @@ create table t1 select x'4132';
drop table t1;
create table t1 select 1,2,3;
create table if not exists t1 select 1,2;
+Warnings:
+Note 1050 Table 't1' already exists
create table if not exists t1 select 1,2,3,4;
ERROR 21S01: Column count doesn't match value count at row 1
create table if not exists t1 select 1;
+Warnings:
+Note 1050 Table 't1' already exists
select * from t1;
1 2 3
1 2 3
@@ -243,9 +249,13 @@ select * from t1;
drop table t1;
create table t1 select 1,2,3;
create table if not exists t1 select 1,2;
+Warnings:
+Note 1050 Table 't1' already exists
create table if not exists t1 select 1,2,3,4;
ERROR 21S01: Column count doesn't match value count at row 1
create table if not exists t1 select 1;
+Warnings:
+Note 1050 Table 't1' already exists
select * from t1;
1 2 3
1 2 3
@@ -255,11 +265,15 @@ drop table t1;
create table t1 (a int not null, b int, primary key (a));
insert into t1 values (1,1);
create table if not exists t1 select 2;
+Warnings:
+Note 1050 Table 't1' already exists
select * from t1;
a b
1 1
0 2
create table if not exists t1 select 3 as 'a',4 as 'b';
+Warnings:
+Note 1050 Table 't1' already exists
create table if not exists t1 select 3 as 'a',3 as 'b';
ERROR 23000: Duplicate entry '3' for key 1
select * from t1;
@@ -593,3 +607,17 @@ drop database mysqltest;
create table test.t1 like x;
ERROR 42000: Incorrect database name 'NULL'
drop table if exists test.t1;
+create database mysqltest;
+create database if not exists mysqltest character set latin2;
+Warnings:
+Note 1007 Can't create database 'mysqltest'; database exists
+show create database mysqltest;
+Database Create Database
+mysqltest CREATE DATABASE `mysqltest` /*!40100 DEFAULT CHARACTER SET latin1 */
+drop database mysqltest;
+use test;
+create table t1 (a int);
+create table if not exists t1 (a int);
+Warnings:
+Note 1050 Table 't1' already exists
+drop table t1;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 8287a042d60..4ad28091164 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -764,3 +764,12 @@ select date(left(f1+0,8)) from t1 group by 1;
date(left(f1+0,8))
2005-06-06
drop table t1;
+create table t1(f1 varchar(5) key);
+insert into t1 values (1),(2);
+select sql_buffer_result max(f1) is null from t1;
+max(f1) is null
+0
+select sql_buffer_result max(f1)+1 from t1;
+max(f1)+1
+3
+drop table t1;
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 858daacffe9..f47c78c9768 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1674,3 +1674,14 @@ select * from t1;
a
42
drop table t1;
+create table t1 (a int not null, b int not null, c blob not null, d int not null, e int, primary key (a,b,c(255),d)) engine=innodb;
+insert into t1 values (2,2,"b",2,2),(1,1,"a",1,1),(3,3,"ab",3,3);
+select * from t1 order by a,b,c,d;
+a b c d e
+1 1 a 1 1
+2 2 b 2 2
+3 3 ab 3 3
+explain select * from t1 order by a,b,c,d;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort
+drop table t1;
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index 2ac73fe7662..d4eb4e8b788 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -668,3 +668,13 @@ ERROR 42S02: Unknown table 't2' in field list
insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b;
ERROR 42S02: Unknown table 't2' in field list
drop table t1,t2,t3;
+create table t1(f1 varchar(5) key);
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+select * from t1;
+f1
+2000
+2001
+2002
+drop table t1;
diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result
index 5a1a82832fa..c61270c02a8 100644
--- a/mysql-test/r/ndb_autodiscover.result
+++ b/mysql-test/r/ndb_autodiscover.result
@@ -99,6 +99,8 @@ id int not null primary key,
id2 int not null,
name char(20)
) engine=ndb;
+Warnings:
+Note 1050 Table 't3' already exists
show status like 'handler_discover%';
Variable_name Value
Handler_discover 0
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index 7178895cf80..65f7c649624 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -516,3 +516,16 @@ a b c count
1 NULL NULL 2
NULL NULL NULL 2
DROP TABLE t1;
+CREATE TABLE t1 (a int(11) NOT NULL);
+INSERT INTO t1 VALUES (1),(2);
+SELECT * FROM (SELECT a, a + 1, COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
+a a + 1 COUNT(*)
+1 2 1
+2 3 1
+NULL NULL 2
+SELECT * FROM (SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
+a LENGTH(a) COUNT(*)
+1 1 1
+2 1 1
+NULL NULL 2
+DROP TABLE t1;
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index c4ccdf9eb34..49e858eca56 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -470,12 +470,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 14 N 1 31 8
+def Extra 253 255 14 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using filesort
SET @arg00=1 ;
@@ -486,12 +486,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 5 Y 0 31 8
-def possible_keys 252 4096 7 Y 0 31 8
+def possible_keys 253 4096 7 Y 0 31 8
def key 253 64 7 Y 0 31 8
def key_len 8 3 1 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 27 N 1 31 8
+def Extra 253 255 27 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where; Using filesort
drop table if exists t2;
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index 6ef61b05577..4b655cfb854 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -1153,12 +1153,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
drop table if exists t2 ;
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index 96047ac3182..4d2a62887d6 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -1153,12 +1153,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
test_sequence
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index bff4b6a5ad8..a4919b664c4 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -1154,12 +1154,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
test_sequence
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index 5ed6c10a47c..f98cc1b3cdf 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -1196,12 +1196,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
test_sequence
@@ -4210,12 +4210,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
test_sequence
diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result
index ef74e13a41d..acd7f45de95 100644
--- a/mysql-test/r/ps_6bdb.result
+++ b/mysql-test/r/ps_6bdb.result
@@ -1153,12 +1153,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 3
test_sequence
diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result
index e7ffbb7c6ef..27a1ea0925d 100644
--- a/mysql-test/r/ps_7ndb.result
+++ b/mysql-test/r/ps_7ndb.result
@@ -1153,12 +1153,12 @@ def id 8 3 1 N 32929 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
-def possible_keys 252 4096 0 Y 0 31 8
+def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 8 3 0 Y 32928 0 63
-def ref 252 1024 0 Y 0 31 8
+def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 252 255 0 N 1 31 8
+def Extra 253 255 0 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t9 ALL NULL NULL NULL NULL 2
test_sequence
diff --git a/mysql-test/r/rpl_slave_status.result b/mysql-test/r/rpl_slave_status.result
index 8badbab85ff..2146132aeb0 100644
--- a/mysql-test/r/rpl_slave_status.result
+++ b/mysql-test/r/rpl_slave_status.result
@@ -19,7 +19,7 @@ flush privileges;
stop slave;
start slave;
show slave status;
-Slave_IO_State Connecting to master
+Slave_IO_State #
Master_Host 127.0.0.1
Master_User rpl
Master_Port MASTER_MYPORT
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index f08fe6ddd0f..0b6bc48c350 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -23,6 +23,8 @@ a b
6 g
create TEMPORARY TABLE t2 engine=heap select * from t1;
create TEMPORARY TABLE IF NOT EXISTS t2 (a int) engine=heap;
+Warnings:
+Note 1050 Table 't2' already exists
CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null);
ERROR 42S01: Table 't1' already exists
ALTER TABLE t1 RENAME t2;
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index e97b309547a..b9c05bc388c 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -63,9 +63,11 @@ show count(*) warnings;
1
create table t1(id int);
create table if not exists t1(id int);
+Warnings:
+Note 1050 Table 't1' already exists
select @@warning_count;
@@warning_count
-0
+1
drop table t1;
create table t1(a tinyint, b int not null, c date, d char(5));
load data infile '../../std_data/warnings_loaddata.dat' into table t1 fields terminated by ',';
diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test
index e7fbf09c19a..e38e43381bc 100644
--- a/mysql-test/t/analyse.test
+++ b/mysql-test/t/analyse.test
@@ -48,4 +48,13 @@ insert into t1 values ('abc'),('abc\'def\\hij\"klm\0opq'),('\''),('\"'),('\\'),(
select * from t1 procedure analyse();
drop table t1;
+#
+# Bug#10716 - Procedure Analyse results in wrong values for optimal field type
+#
+
+create table t1 (d double);
+insert into t1 values (100000);
+select * from t1 procedure analyse (1,1);
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test
index 1a6dca5b69e..ff15d74e5ac 100644
--- a/mysql-test/t/connect.test
+++ b/mysql-test/t/connect.test
@@ -6,6 +6,10 @@
# This test makes no sense with the embedded server
--source include/not_embedded.inc
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
#connect (con1,localhost,root,,"");
#show tables;
connect (con1,localhost,root,,mysql);
@@ -77,4 +81,18 @@ show tables;
delete from mysql.user where user=_binary"test";
flush privileges;
+#
+# Bug#12517: Clear user variables and replication events before
+# closing temp tables in thread cleanup.
+connect (con2,localhost,root,,test);
+connection con2;
+create table t1 (id integer not null auto_increment primary key);
+create temporary table t2(id integer not null auto_increment primary key);
+set @id := 1;
+delete from t1 where id like @id;
+disconnect con2;
+--sleep 5
+connection default;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 9ea810aaf7d..73184853d1a 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -513,4 +513,17 @@ create table test.t1 like x;
drop table if exists test.t1;
--enable_warnings
+#
+# Bug #6008 MySQL does not create warnings when
+# creating database and using IF NOT EXISTS
+#
+create database mysqltest;
+create database if not exists mysqltest character set latin2;
+show create database mysqltest;
+drop database mysqltest;
+use test;
+create table t1 (a int);
+create table if not exists t1 (a int);
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 815da66c717..f14fab2d30e 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -600,4 +600,14 @@ insert into t1 values('2005-06-06');
select date(left(f1+0,8)) from t1 group by 1;
drop table t1;
+#
+# BUG#12695: Item_func_isnull::update_used_tables
+# did not update const_item_cache
+#
+create table t1(f1 varchar(5) key);
+insert into t1 values (1),(2);
+select sql_buffer_result max(f1) is null from t1;
+select sql_buffer_result max(f1)+1 from t1;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 33432209e65..a14370c6543 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -1220,4 +1220,14 @@ insert into t1 values (42);
select * from t1;
drop table t1;
+#
+# Bug #13025 Server crash during filesort
+#
+
+create table t1 (a int not null, b int not null, c blob not null, d int not null, e int, primary key (a,b,c(255),d)) engine=innodb;
+insert into t1 values (2,2,"b",2,2),(1,1,"a",1,1),(3,3,"ab",3,3);
+select * from t1 order by a,b,c,d;
+explain select * from t1 order by a,b,c,d;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index 14853b38db2..6fcdef6ab03 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -204,4 +204,14 @@ insert into t1 select t2.a from t2 on duplicate key update t2.a= a + t2.b;
insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b;
drop table t1,t2,t3;
+#
+# Bug #12695 Item_func_isnull::update_used_tables() did not update
+# const_item_cache
+create table t1(f1 varchar(5) key);
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+insert into t1(f1) select if(max(f1) is null, '2000',max(f1)+1) from t1;
+select * from t1;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index c9a16b897c6..76c62d14621 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -250,4 +250,17 @@ SELECT a, b, a AS c, COUNT(*) AS count FROM t1 GROUP BY a, b, c WITH ROLLUP;
DROP TABLE t1;
+#
+# Bug #11885: derived table specified by a subquery with
+# ROLLUP over expressions on not nullable group by attributes
+#
+
+CREATE TABLE t1 (a int(11) NOT NULL);
+INSERT INTO t1 VALUES (1),(2);
+
+SELECT * FROM (SELECT a, a + 1, COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
+SELECT * FROM (SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
+
+DROP TABLE t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/rpl_slave_status.test b/mysql-test/t/rpl_slave_status.test
index 2c5bd2bffb0..67d3816f443 100644
--- a/mysql-test/t/rpl_slave_status.test
+++ b/mysql-test/t/rpl_slave_status.test
@@ -23,7 +23,9 @@ connection slave;
stop slave;
start slave;
--replace_result $MASTER_MYPORT MASTER_MYPORT
---replace_column 7 # 8 # 9 # 22 # 23 #
+# Column 1 is replaced, since the output can be either
+# "Connecting to master" or "Waiting for master update"
+--replace_column 1 # 7 # 8 # 9 # 22 # 23 #
--vertical_results
show slave status;
diff --git a/ndb/include/kernel/signaldata/BackupImpl.hpp b/ndb/include/kernel/signaldata/BackupImpl.hpp
index 2032e2347b5..298440ad377 100644
--- a/ndb/include/kernel/signaldata/BackupImpl.hpp
+++ b/ndb/include/kernel/signaldata/BackupImpl.hpp
@@ -33,7 +33,7 @@ class DefineBackupReq {
friend bool printDEFINE_BACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 8 + NdbNodeBitmask::Size);
+ STATIC_CONST( SignalLength = 9 + NdbNodeBitmask::Size);
private:
/**
@@ -60,6 +60,13 @@ private:
* Length of backup data
*/
Uint32 backupDataLen;
+
+ /**
+ * Backup flags
+ */
+ /* & 0x3 - waitCompleted
+ */
+ Uint32 flags;
};
class DefineBackupRef {
diff --git a/ndb/include/kernel/signaldata/BackupSignalData.hpp b/ndb/include/kernel/signaldata/BackupSignalData.hpp
index b38dd8d14b2..e1b8c6203a1 100644
--- a/ndb/include/kernel/signaldata/BackupSignalData.hpp
+++ b/ndb/include/kernel/signaldata/BackupSignalData.hpp
@@ -36,11 +36,14 @@ class BackupReq {
friend bool printBACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 2 );
+ STATIC_CONST( SignalLength = 3 );
private:
Uint32 senderData;
Uint32 backupDataLen;
+ /* & 0x3 - waitCompleted
+ */
+ Uint32 flags;
};
class BackupData {
diff --git a/ndb/include/kernel/signaldata/NFCompleteRep.hpp b/ndb/include/kernel/signaldata/NFCompleteRep.hpp
index c8bde705a86..764da85b163 100644
--- a/ndb/include/kernel/signaldata/NFCompleteRep.hpp
+++ b/ndb/include/kernel/signaldata/NFCompleteRep.hpp
@@ -30,28 +30,12 @@
* from the failed NDB node
*
*/
-class NFCompleteRep {
- /**
- * Sender(s)
- */
- friend class Dbdict;
- friend class Dblqh;
- friend class Dbtc;
- friend class Qmgr;
-
- /**
- * Sender/Reciver
- */
- friend class Dbdih;
- friend class ClusterMgr;
+struct NFCompleteRep {
friend bool printNF_COMPLETE_REP(FILE *, const Uint32 *, Uint32, Uint16);
-public:
STATIC_CONST( SignalLength = 5 );
-private:
-
/**
* Which block has completed...
*
diff --git a/ndb/include/kernel/signaldata/NodeFailRep.hpp b/ndb/include/kernel/signaldata/NodeFailRep.hpp
index 060acd6a3e2..fe57ba1a712 100644
--- a/ndb/include/kernel/signaldata/NodeFailRep.hpp
+++ b/ndb/include/kernel/signaldata/NodeFailRep.hpp
@@ -24,34 +24,8 @@
* This signals is sent by Qmgr to NdbCntr
* and then from NdbCntr sent to: dih, dict, lqh, tc & API
*/
-class NodeFailRep {
- /**
- * Sender(s)
- */
- friend class Qmgr;
-
- /**
- * Sender(s) / Reciver(s)
- */
- friend class Ndbcntr;
- friend class Dbdict;
-
- /**
- * Reciver(s)
- */
- friend class Dbdih;
- friend class Dblqh;
- friend class Dbtc;
- friend class ClusterMgr;
- friend class Trix;
- friend class Backup;
- friend class Suma;
- friend class Grep;
- friend class SafeCounterManager;
-
-public:
+struct NodeFailRep {
STATIC_CONST( SignalLength = 3 + NodeBitmask::Size );
-private:
Uint32 failNo;
diff --git a/ndb/include/util/Parser.hpp b/ndb/include/util/Parser.hpp
index c117498e1ba..3baf7601a6c 100644
--- a/ndb/include/util/Parser.hpp
+++ b/ndb/include/util/Parser.hpp
@@ -285,7 +285,7 @@ template<class T>
inline
void
Parser<T>::setBreakOnInvalidArg(bool v){
- impl->m_breakOnInvalidArg;
+ impl->m_breakOnInvalidArg = v;
}
#endif
diff --git a/ndb/src/common/portlib/NdbThread.c b/ndb/src/common/portlib/NdbThread.c
index 55ebc4c8111..48d00956ec2 100644
--- a/ndb/src/common/portlib/NdbThread.c
+++ b/ndb/src/common/portlib/NdbThread.c
@@ -53,6 +53,16 @@ ndb_thread_wrapper(void* _ss){
}
#endif
{
+ /**
+ * Block all signals to thread by default
+ * let them go to main process instead
+ */
+ sigset_t mask;
+ sigfillset(&mask);
+ pthread_sigmask(SIG_BLOCK, &mask, 0);
+ }
+
+ {
void *ret;
struct NdbThread * ss = (struct NdbThread *)_ss;
ret= (* ss->func)(ss->object);
diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp
index 3334d69ae89..ec5c7a5d588 100644
--- a/ndb/src/kernel/blocks/backup/Backup.cpp
+++ b/ndb/src/kernel/blocks/backup/Backup.cpp
@@ -69,6 +69,9 @@ static const Uint32 BACKUP_SEQUENCE = 0x1F000000;
static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE;
+#define SEND_BACKUP_STARTED_FLAG(A) (((A) & 0x3) > 0)
+#define SEND_BACKUP_COMPLETED_FLAG(A) (((A) & 0x3) > 1)
+
void
Backup::execSTTOR(Signal* signal)
{
@@ -852,23 +855,24 @@ Backup::execBACKUP_REQ(Signal* signal)
const Uint32 senderData = req->senderData;
const BlockReference senderRef = signal->senderBlockRef();
const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words
-
+ const Uint32 flags = signal->getLength() > 2 ? req->flags : 2;
+
if(getOwnNodeId() != getMasterNodeId()) {
jam();
- sendBackupRef(senderRef, signal, senderData, BackupRef::IAmNotMaster);
+ sendBackupRef(senderRef, flags, signal, senderData, BackupRef::IAmNotMaster);
return;
}//if
if (m_diskless)
{
- sendBackupRef(senderRef, signal, senderData,
+ sendBackupRef(senderRef, flags, signal, senderData,
BackupRef::CannotBackupDiskless);
return;
}
if(dataLen32 != 0) {
jam();
- sendBackupRef(senderRef, signal, senderData,
+ sendBackupRef(senderRef, flags, signal, senderData,
BackupRef::BackupDefinitionNotImplemented);
return;
}//if
@@ -883,7 +887,7 @@ Backup::execBACKUP_REQ(Signal* signal)
c_backups.seize(ptr);
if(ptr.i == RNIL) {
jam();
- sendBackupRef(senderRef, signal, senderData, BackupRef::OutOfBackupRecord);
+ sendBackupRef(senderRef, flags, signal, senderData, BackupRef::OutOfBackupRecord);
return;
}//if
@@ -894,6 +898,7 @@ Backup::execBACKUP_REQ(Signal* signal)
ptr.p->errorCode = 0;
ptr.p->clientRef = senderRef;
ptr.p->clientData = senderData;
+ ptr.p->flags = flags;
ptr.p->masterRef = reference();
ptr.p->nodes = c_aliveNodes;
ptr.p->backupId = 0;
@@ -931,20 +936,23 @@ void
Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode)
{
jam();
- sendBackupRef(ptr.p->clientRef, signal, ptr.p->clientData, errorCode);
+ sendBackupRef(ptr.p->clientRef, ptr.p->flags, signal, ptr.p->clientData, errorCode);
cleanup(signal, ptr);
}
void
-Backup::sendBackupRef(BlockReference senderRef, Signal *signal,
+Backup::sendBackupRef(BlockReference senderRef, Uint32 flags, Signal *signal,
Uint32 senderData, Uint32 errorCode)
{
jam();
- BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
- ref->senderData = senderData;
- ref->errorCode = errorCode;
- ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
- sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
+ if (SEND_BACKUP_STARTED_FLAG(flags))
+ {
+ BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
+ ref->senderData = senderData;
+ ref->errorCode = errorCode;
+ ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
+ sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
+ }
if(errorCode != BackupRef::IAmNotMaster){
signal->theData[0] = EventReport::BackupFailedToStart;
@@ -1098,6 +1106,7 @@ Backup::sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr)
req->backupKey[1] = ptr.p->backupKey[1];
req->nodes = ptr.p->nodes;
req->backupDataLen = ptr.p->backupDataLen;
+ req->flags = ptr.p->flags;
ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
ptr.p->masterData.sendCounter = ptr.p->nodes;
@@ -1193,13 +1202,18 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
/**
* Reply to client
*/
- BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
- conf->backupId = ptr.p->backupId;
- conf->senderData = ptr.p->clientData;
- conf->nodes = ptr.p->nodes;
- sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
- BackupConf::SignalLength, JBB);
-
+ CRASH_INSERTION((10034));
+
+ if (SEND_BACKUP_STARTED_FLAG(ptr.p->flags))
+ {
+ BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
+ conf->backupId = ptr.p->backupId;
+ conf->senderData = ptr.p->clientData;
+ conf->nodes = ptr.p->nodes;
+ sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
+ BackupConf::SignalLength, JBB);
+ }
+
signal->theData[0] = EventReport::BackupStarted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
@@ -2080,19 +2094,22 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
if(!ptr.p->checkError())
{
- BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
- rep->backupId = ptr.p->backupId;
- rep->senderData = ptr.p->clientData;
- rep->startGCP = ptr.p->startGCP;
- rep->stopGCP = ptr.p->stopGCP;
- rep->noOfBytes = ptr.p->noOfBytes;
- rep->noOfRecords = ptr.p->noOfRecords;
- rep->noOfLogBytes = ptr.p->noOfLogBytes;
- rep->noOfLogRecords = ptr.p->noOfLogRecords;
- rep->nodes = ptr.p->nodes;
- sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
- BackupCompleteRep::SignalLength, JBB);
-
+ if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
+ {
+ BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
+ rep->backupId = ptr.p->backupId;
+ rep->senderData = ptr.p->clientData;
+ rep->startGCP = ptr.p->startGCP;
+ rep->stopGCP = ptr.p->stopGCP;
+ rep->noOfBytes = ptr.p->noOfBytes;
+ rep->noOfRecords = ptr.p->noOfRecords;
+ rep->noOfLogBytes = ptr.p->noOfLogBytes;
+ rep->noOfLogRecords = ptr.p->noOfLogRecords;
+ rep->nodes = ptr.p->nodes;
+ sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
+ BackupCompleteRep::SignalLength, JBB);
+ }
+
signal->theData[0] = EventReport::BackupCompleted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
@@ -2129,13 +2146,15 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
return;
}
- BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
- rep->backupId = ptr.p->backupId;
- rep->senderData = ptr.p->clientData;
- rep->reason = ptr.p->errorCode;
- sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
- BackupAbortRep::SignalLength, JBB);
-
+ if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
+ {
+ BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
+ rep->backupId = ptr.p->backupId;
+ rep->senderData = ptr.p->clientData;
+ rep->reason = ptr.p->errorCode;
+ sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
+ BackupAbortRep::SignalLength, JBB);
+ }
signal->theData[0] = EventReport::BackupAborted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
@@ -2267,6 +2286,13 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
ptr.p->errorCode = 0;
ptr.p->clientRef = req->clientRef;
ptr.p->clientData = req->clientData;
+ if(senderRef == reference())
+ ptr.p->flags = req->flags;
+ else
+ ptr.p->flags = req->flags & ~((Uint32)0x3); /* remove waitCompleted flags
+ * as non master should never
+ * reply
+ */
ptr.p->masterRef = senderRef;
ptr.p->nodes = req->nodes;
ptr.p->backupId = backupId;
diff --git a/ndb/src/kernel/blocks/backup/Backup.hpp b/ndb/src/kernel/blocks/backup/Backup.hpp
index 7bcea5655b4..f3d180b9467 100644
--- a/ndb/src/kernel/blocks/backup/Backup.hpp
+++ b/ndb/src/kernel/blocks/backup/Backup.hpp
@@ -413,6 +413,7 @@ public:
Uint32 clientRef;
Uint32 clientData;
+ Uint32 flags;
Uint32 backupId;
Uint32 backupKey[2];
Uint32 masterRef;
@@ -595,7 +596,7 @@ public:
bool insertFileHeader(BackupFormat::FileType, BackupRecord*, BackupFile*);
void sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode);
- void sendBackupRef(BlockReference ref, Signal *signal,
+ void sendBackupRef(BlockReference ref, Uint32 flags, Signal *signal,
Uint32 senderData, Uint32 errorCode);
void dumpUsedResources();
void cleanup(Signal*, BackupRecordPtr ptr);
diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index 836fc9398e5..951d1e90251 100644
--- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -86,6 +86,17 @@
#define ZCURR_PAGE_INDEX 8
#define ZLAST_LOG_PREP_REF 10
#define ZPOS_DIRTY 11
+/* A number of debug items written in the page header of all log files */
+#define ZPOS_LOG_TIMER 12
+#define ZPOS_PAGE_I 13
+#define ZPOS_PLACE_WRITTEN_FROM 14
+#define ZPOS_PAGE_NO 15
+#define ZPOS_PAGE_FILE_NO 16
+#define ZPOS_WORD_WRITTEN 17
+#define ZPOS_IN_WRITING 18
+#define ZPOS_PREV_PAGE_NO 19
+#define ZPOS_IN_FREE_LIST 20
+
/* ------------------------------------------------------------------------- */
/* CONSTANTS FOR THE VARIOUS REPLICA AND NODE TYPES. */
/* ------------------------------------------------------------------------- */
@@ -2278,7 +2289,7 @@ private:
const LogPartRecordPtr &sltLogPartPtr);
void checkGcpCompleted(Signal* signal, Uint32 pageWritten, Uint32 wordWritten);
void initFsopenconf(Signal* signal);
- void initFsrwconf(Signal* signal);
+ void initFsrwconf(Signal* signal, bool write);
void initLfo(Signal* signal);
void initLogfile(Signal* signal, Uint32 fileNo);
void initLogpage(Signal* signal);
@@ -2294,7 +2305,8 @@ private:
void writeFileDescriptor(Signal* signal);
void writeFileHeaderOpen(Signal* signal, Uint32 type);
void writeInitMbyte(Signal* signal);
- void writeSinglePage(Signal* signal, Uint32 pageNo, Uint32 wordWritten);
+ void writeSinglePage(Signal* signal, Uint32 pageNo,
+ Uint32 wordWritten, Uint32 place);
void buildLinkedLogPageList(Signal* signal);
void changeMbyte(Signal* signal);
Uint32 checkIfExecLog(Signal* signal);
@@ -2303,7 +2315,7 @@ private:
void checkScanTcCompleted(Signal* signal);
void checkSrCompleted(Signal* signal);
void closeFile(Signal* signal, LogFileRecordPtr logFilePtr);
- void completedLogPage(Signal* signal, Uint32 clpType);
+ void completedLogPage(Signal* signal, Uint32 clpType, Uint32 place);
void deleteFragrec(Uint32 fragId);
void deleteTransidHash(Signal* signal);
void findLogfile(Signal* signal,
@@ -2399,7 +2411,9 @@ private:
void writeAbortLog(Signal* signal);
void writeCommitLog(Signal* signal, LogPartRecordPtr regLogPartPtr);
void writeCompletedGciLog(Signal* signal);
- void writeDirty(Signal* signal);
+ void writeDbgInfoPageHeader(LogPageRecordPtr logPagePtr, Uint32 place,
+ Uint32 pageNo, Uint32 wordWritten);
+ void writeDirty(Signal* signal, Uint32 place);
void writeKey(Signal* signal);
void writeLogHeader(Signal* signal);
void writeLogWord(Signal* signal, Uint32 data);
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index 5e2e6dc392c..b6178227d31 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -11749,42 +11749,34 @@ void Dblqh::execFSCLOSECONF(Signal* signal)
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
exitFromInvalidate(signal);
return;
- break;
case LogFileRecord::CLOSING_INIT:
jam();
closingInitLab(signal);
return;
- break;
case LogFileRecord::CLOSING_SR:
jam();
closingSrLab(signal);
return;
- break;
case LogFileRecord::CLOSING_EXEC_SR:
jam();
closeExecSrLab(signal);
return;
- break;
case LogFileRecord::CLOSING_EXEC_SR_COMPLETED:
jam();
closeExecSrCompletedLab(signal);
return;
- break;
case LogFileRecord::CLOSING_WRITE_LOG:
jam();
closeWriteLogLab(signal);
return;
- break;
case LogFileRecord::CLOSING_EXEC_LOG:
jam();
closeExecLogLab(signal);
return;
- break;
default:
jam();
systemErrorLab(signal);
return;
- break;
}//switch
}//Dblqh::execFSCLOSECONF()
@@ -11802,77 +11794,64 @@ void Dblqh::execFSOPENCONF(Signal* signal)
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
readFileInInvalidate(signal);
return;
- break;
case LogFileRecord::OPENING_INIT:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openFileInitLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_FRONTPAGE:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrFrontpageLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_LAST_FILE:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrLastFileLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_NEXT_FILE:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrNextFileLab(signal);
return;
- break;
case LogFileRecord::OPEN_EXEC_SR_START:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openExecSrStartLab(signal);
return;
- break;
case LogFileRecord::OPEN_EXEC_SR_NEW_MBYTE:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openExecSrNewMbyteLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_FOURTH_PHASE:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrFourthPhaseLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_FOURTH_NEXT:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrFourthNextLab(signal);
return;
- break;
case LogFileRecord::OPEN_SR_FOURTH_ZERO:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openSrFourthZeroLab(signal);
return;
- break;
case LogFileRecord::OPENING_WRITE_LOG:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
return;
- break;
case LogFileRecord::OPEN_EXEC_LOG:
jam();
logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
openExecLogLab(signal);
return;
- break;
default:
jam();
systemErrorLab(signal);
return;
- break;
}//switch
}//Dblqh::execFSOPENCONF()
@@ -11883,7 +11862,7 @@ void Dblqh::execFSOPENCONF(Signal* signal)
void Dblqh::execFSREADCONF(Signal* signal)
{
jamEntry();
- initFsrwconf(signal);
+ initFsrwconf(signal, false);
switch (lfoPtr.p->lfoState) {
case LogFileOperationRecord::READ_SR_LAST_MBYTE:
@@ -11891,57 +11870,47 @@ void Dblqh::execFSREADCONF(Signal* signal)
releaseLfo(signal);
readSrLastMbyteLab(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_FRONTPAGE:
jam();
releaseLfo(signal);
readSrFrontpageLab(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_LAST_FILE:
jam();
releaseLfo(signal);
readSrLastFileLab(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_NEXT_FILE:
jam();
releaseLfo(signal);
readSrNextFileLab(signal);
return;
- break;
case LogFileOperationRecord::READ_EXEC_SR:
jam();
readExecSrLab(signal);
return;
- break;
case LogFileOperationRecord::READ_EXEC_LOG:
jam();
readExecLogLab(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
jam();
invalidateLogAfterLastGCI(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
jam();
releaseLfo(signal);
readSrFourthPhaseLab(signal);
return;
- break;
case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
jam();
releaseLfo(signal);
readSrFourthZeroLab(signal);
return;
- break;
default:
jam();
systemErrorLab(signal);
return;
- break;
}//switch
}//Dblqh::execFSREADCONF()
@@ -11998,63 +11967,52 @@ void Dblqh::execFSREADREF(Signal* signal)
void Dblqh::execFSWRITECONF(Signal* signal)
{
jamEntry();
- initFsrwconf(signal);
+ initFsrwconf(signal, true);
switch (lfoPtr.p->lfoState) {
case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
jam();
invalidateLogAfterLastGCI(signal);
return;
- break;
case LogFileOperationRecord::WRITE_PAGE_ZERO:
jam();
writePageZeroLab(signal);
return;
- break;
case LogFileOperationRecord::LAST_WRITE_IN_FILE:
jam();
lastWriteInFileLab(signal);
return;
- break;
case LogFileOperationRecord::INIT_WRITE_AT_END:
jam();
initWriteEndLab(signal);
return;
- break;
case LogFileOperationRecord::INIT_FIRST_PAGE:
jam();
initFirstPageLab(signal);
return;
- break;
case LogFileOperationRecord::WRITE_GCI_ZERO:
jam();
writeGciZeroLab(signal);
return;
- break;
case LogFileOperationRecord::WRITE_DIRTY:
jam();
writeDirtyLab(signal);
return;
- break;
case LogFileOperationRecord::WRITE_INIT_MBYTE:
jam();
writeInitMbyteLab(signal);
return;
- break;
case LogFileOperationRecord::ACTIVE_WRITE_LOG:
jam();
writeLogfileLab(signal);
return;
- break;
case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
jam();
firstPageWriteLab(signal);
return;
- break;
default:
jam();
systemErrorLab(signal);
return;
- break;
}//switch
}//Dblqh::execFSWRITECONF()
@@ -12130,16 +12088,35 @@ void Dblqh::initFsopenconf(Signal* signal)
/* ======= INITIATE WHEN RECEIVING FSREADCONF AND FSWRITECONF ======= */
/* */
/* ========================================================================= */
-void Dblqh::initFsrwconf(Signal* signal)
+void Dblqh::initFsrwconf(Signal* signal, bool write)
{
+ LogPageRecordPtr logP;
+ Uint32 noPages, totPages;
lfoPtr.i = signal->theData[0];
ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
+ totPages= lfoPtr.p->noPagesRw;
logFilePtr.i = lfoPtr.p->logFileRec;
ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
logPartPtr.i = logFilePtr.p->logPartRec;
ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
logPagePtr.i = lfoPtr.p->firstLfoPage;
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
+ logP= logPagePtr;
+ noPages= 1;
+ ndbassert(totPages > 0);
+ for (;;)
+ {
+ logP.p->logPageWord[ZPOS_IN_WRITING]= 0;
+ logP.p->logPageWord[ZPOS_IN_FREE_LIST]= 0;
+ if (noPages == totPages)
+ return;
+ if (write)
+ logP.i= logP.p->logPageWord[ZNEXT_PAGE];
+ else
+ logP.i= lfoPtr.p->logPageArray[noPages];
+ ptrCheckGuard(logP, clogPageFileSize, logPageRecord);
+ noPages++;
+ }
}//Dblqh::initFsrwconf()
/* ######################################################################### */
@@ -12227,7 +12204,7 @@ void Dblqh::timeSup(Signal* signal)
ndbrequire(wordWritten < ZPAGE_SIZE);
if (logFilePtr.p->noLogpagesInBuffer > 0) {
jam();
- completedLogPage(signal, ZENFORCE_WRITE);
+ completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
/*---------------------------------------------------------------------------*/
/*SINCE WE ARE ONLY WRITING PART OF THE LAST PAGE WE HAVE TO UPDATE THE WORD */
/*WRITTEN TO REFLECT THE REAL LAST WORD WRITTEN. WE ALSO HAVE TO MOVE THE */
@@ -12249,7 +12226,8 @@ void Dblqh::timeSup(Signal* signal)
releaseLogpage(signal);
} else {
jam();
- writeSinglePage(signal, logFilePtr.p->currentFilepage, wordWritten);
+ writeSinglePage(signal, logFilePtr.p->currentFilepage,
+ wordWritten, __LINE__);
lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
}//if
}//if
@@ -12385,7 +12363,7 @@ void Dblqh::firstPageWriteLab(Signal* signal)
logPagePtr.i = logFilePtr.p->logPageZero;
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
- writeSinglePage(signal, 0, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->logFileRec = currLogFile;
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
return;
@@ -12474,7 +12452,7 @@ void Dblqh::lastWriteInFileLab(Signal* signal)
logPagePtr.i = logFilePtr.p->logPageZero;
ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
- writeSinglePage(signal, 0, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->logFileRec = currLogFile;
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
return;
@@ -12509,7 +12487,8 @@ void Dblqh::openFileInitLab(Signal* signal)
{
logFilePtr.p->logFileStatus = LogFileRecord::OPEN_INIT;
seizeLogpage(signal);
- writeSinglePage(signal, (ZNO_MBYTES_IN_FILE * ZPAGES_IN_MBYTE) - 1, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, (ZNO_MBYTES_IN_FILE * ZPAGES_IN_MBYTE) - 1,
+ ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->lfoState = LogFileOperationRecord::INIT_WRITE_AT_END;
return;
}//Dblqh::openFileInitLab()
@@ -12550,7 +12529,7 @@ void Dblqh::initFirstPageLab(Signal* signal)
logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE] = ZCOMPLETED_GCI_TYPE;
logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + 1] = 1;
- writeSinglePage(signal, 1, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, 1, ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_GCI_ZERO;
return;
}//if
@@ -12852,17 +12831,13 @@ void Dblqh::releaseLogpage(Signal* signal)
{
#ifdef VM_TRACE
// Check that log page isn't already in free list
- LogPageRecordPtr TlogPagePtr;
- TlogPagePtr.i = cfirstfreeLogPage;
- while (TlogPagePtr.i != RNIL){
- ptrCheckGuard(TlogPagePtr, clogPageFileSize, logPageRecord);
- ndbrequire(TlogPagePtr.i != logPagePtr.i);
- TlogPagePtr.i = TlogPagePtr.p->logPageWord[ZNEXT_PAGE];
- }
+ ndbrequire(logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] == 0);
#endif
cnoOfLogPages++;
logPagePtr.p->logPageWord[ZNEXT_PAGE] = cfirstfreeLogPage;
+ logPagePtr.p->logPageWord[ZPOS_IN_WRITING]= 0;
+ logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST]= 1;
cfirstfreeLogPage = logPagePtr.i;
}//Dblqh::releaseLogpage()
@@ -12908,6 +12883,7 @@ void Dblqh::seizeLogpage(Signal* signal)
/* ------------------------------------------------------------------------- */
cfirstfreeLogPage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
+ logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] = 0;
}//Dblqh::seizeLogpage()
/* ------------------------------------------------------------------------- */
@@ -13015,7 +12991,7 @@ WMO_LOOP:
/* LOG FILE. THIS HAS SPECIAL SIGNIFANCE TO FIND */
/* THE END OF THE LOG AT SYSTEM RESTART. */
/* ------------------------------------------------------- */
- writeSinglePage(signal, 0, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
if (wmoType == ZINIT) {
jam();
lfoPtr.p->lfoState = LogFileOperationRecord::INIT_FIRST_PAGE;
@@ -13049,7 +13025,8 @@ WMO_LOOP:
void Dblqh::writeInitMbyte(Signal* signal)
{
initLogpage(signal);
- writeSinglePage(signal, logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE,
+ ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_INIT_MBYTE;
}//Dblqh::writeInitMbyte()
@@ -13059,13 +13036,15 @@ void Dblqh::writeInitMbyte(Signal* signal)
/* INPUT: TWSP_PAGE_NO THE PAGE NUMBER WRITTEN */
/* SUBROUTINE SHORT NAME: WSP */
/* ------------------------------------------------------------------------- */
-void Dblqh::writeSinglePage(Signal* signal, Uint32 pageNo, Uint32 wordWritten)
+void Dblqh::writeSinglePage(Signal* signal, Uint32 pageNo,
+ Uint32 wordWritten, Uint32 place)
{
seizeLfo(signal);
initLfo(signal);
lfoPtr.p->firstLfoPage = logPagePtr.i;
logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
+ writeDbgInfoPageHeader(logPagePtr, place, pageNo, wordWritten);
// Calculate checksum for page
logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
@@ -14534,7 +14513,7 @@ void Dblqh::execSr(Signal* signal)
* IN THIS WE HAVE COMPLETED EXECUTION OF THE CURRENT LOG PAGE
* AND CAN WRITE IT TO DISK SINCE IT IS DIRTY.
* ----------------------------------------------------------------- */
- writeDirty(signal);
+ writeDirty(signal, __LINE__);
return;
break;
case LogPartRecord::LES_EXEC_LOG:
@@ -14545,7 +14524,7 @@ void Dblqh::execSr(Signal* signal)
* ------------------------------------------------------------------- */
if (logFilePtr.p->currentLogpage != logPartPtr.p->prevLogpage) {
jam();
- writeDirty(signal);
+ writeDirty(signal, __LINE__);
return;
}//if
break;
@@ -14989,7 +14968,8 @@ void Dblqh::invalidateLogAfterLastGCI(Signal* signal) {
// This page must be invalidated.
logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 0;
// Contact NDBFS. Real time break.
- writeSinglePage(signal, logPartPtr.p->invalidatePageNo, ZPAGE_SIZE - 1);
+ writeSinglePage(signal, logPartPtr.p->invalidatePageNo,
+ ZPAGE_SIZE - 1, __LINE__);
lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES;
} else {
// We are done with invalidating. Finish start phase 3.4.
@@ -15937,7 +15917,7 @@ void Dblqh::closeFile(Signal* signal, LogFileRecordPtr clfLogFilePtr)
// logPartPtr
// Defines lfoPtr
/* ---------------------------------------------------------------- */
-void Dblqh::completedLogPage(Signal* signal, Uint32 clpType)
+void Dblqh::completedLogPage(Signal* signal, Uint32 clpType, Uint32 place)
{
LogPageRecordPtr clpLogPagePtr;
LogPageRecordPtr wlpLogPagePtr;
@@ -15980,6 +15960,9 @@ void Dblqh::completedLogPage(Signal* signal, Uint32 clpType)
twlpNoPages++;
ptrCheckGuard(wlpLogPagePtr, clogPageFileSize, logPageRecord);
+ writeDbgInfoPageHeader(wlpLogPagePtr, place,
+ logFilePtr.p->filePosition + twlpNoPages - 1,
+ ZPAGE_SIZE);
// Calculate checksum for page
wlpLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(wlpLogPagePtr);
wlpLogPagePtr.i = wlpLogPagePtr.p->logPageWord[ZNEXT_PAGE];
@@ -16382,6 +16365,8 @@ void Dblqh::initialiseLogPage(Signal* signal)
refresh_watch_dog();
ptrAss(logPagePtr, logPageRecord);
logPagePtr.p->logPageWord[ZNEXT_PAGE] = logPagePtr.i + 1;
+ logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST]= 1;
+ logPagePtr.p->logPageWord[ZPOS_IN_WRITING]= 0;
}//for
logPagePtr.i = clogPageFileSize - 1;
ptrAss(logPagePtr, logPageRecord);
@@ -18038,10 +18023,14 @@ void Dblqh::writeCompletedGciLog(Signal* signal)
*
* SUBROUTINE SHORT NAME: WD
* ------------------------------------------------------------------------- */
-void Dblqh::writeDirty(Signal* signal)
+void Dblqh::writeDirty(Signal* signal, Uint32 place)
{
logPagePtr.p->logPageWord[ZPOS_DIRTY] = ZNOT_DIRTY;
+ ndbassert(logPartPtr.p->prevFilepage ==
+ logPagePtr.p->logPageWord[ZPOS_PAGE_NO]);
+ writeDbgInfoPageHeader(logPagePtr, place, logPartPtr.p->prevFilepage,
+ ZPAGE_SIZE);
// Calculate checksum for page
logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
@@ -18075,7 +18064,7 @@ void Dblqh::writeLogWord(Signal* signal, Uint32 data)
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + 1;
if ((logPos + 1) == ZPAGE_SIZE) {
jam();
- completedLogPage(signal, ZNORMAL);
+ completedLogPage(signal, ZNORMAL, __LINE__);
seizeLogpage(signal);
initLogpage(signal);
logFilePtr.p->currentLogpage = logPagePtr.i;
@@ -18133,7 +18122,7 @@ void Dblqh::writeNextLog(Signal* signal)
/* -------------------------------------------------- */
/* WE HAVE TO CHANGE LOG FILE */
/* -------------------------------------------------- */
- completedLogPage(signal, ZLAST_WRITE_IN_FILE);
+ completedLogPage(signal, ZLAST_WRITE_IN_FILE, __LINE__);
if (wnlNextLogFilePtr.p->fileNo == 0) {
jam();
/* -------------------------------------------------- */
@@ -18152,7 +18141,7 @@ void Dblqh::writeNextLog(Signal* signal)
/* INCREMENT THE CURRENT MBYTE */
/* SET PAGE INDEX TO PAGE HEADER SIZE */
/* -------------------------------------------------- */
- completedLogPage(signal, ZENFORCE_WRITE);
+ completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
twnlNewMbyte = logFilePtr.p->currentMbyte + 1;
}//if
/* -------------------------------------------------- */
@@ -18520,3 +18509,16 @@ Uint32 Dblqh::calcPageCheckSum(LogPageRecordPtr logP){
return checkSum;
}
+void Dblqh::writeDbgInfoPageHeader(LogPageRecordPtr logP, Uint32 place,
+ Uint32 pageNo, Uint32 wordWritten)
+{
+ logP.p->logPageWord[ZPOS_LOG_TIMER]= logPartPtr.p->logTimer;
+ logP.p->logPageWord[ZPOS_PREV_PAGE_NO]= logP.p->logPageWord[ZPOS_PAGE_NO];
+ logP.p->logPageWord[ZPOS_PAGE_I]= logP.i;
+ logP.p->logPageWord[ZPOS_PLACE_WRITTEN_FROM]= place;
+ logP.p->logPageWord[ZPOS_PAGE_NO]= pageNo;
+ logP.p->logPageWord[ZPOS_PAGE_FILE_NO]= logFilePtr.p->fileNo;
+ logP.p->logPageWord[ZPOS_WORD_WRITTEN]= wordWritten;
+ logP.p->logPageWord[ZPOS_IN_WRITING]= 1;
+}
+
diff --git a/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp b/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp
index b7e2ab072b5..6eadefe5df5 100644
--- a/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp
+++ b/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp
@@ -266,7 +266,16 @@ NdbOut& operator<<(NdbOut& no, const PageHeader& ph) {
printOut("Current page index:", ph.m_current_page_index);
printOut("Oldest prepare op. file No.:", ph.m_old_prepare_file_number);
printOut("Oldest prepare op. page ref.:", ph.m_old_prepare_page_reference);
- printOut("Dirty flag:", ph.m_dirty_flag);
+ printOut("Dirty flag:", ph.m_dirty_flag);
+ printOut("Write Timer:", ph.m_log_timer);
+ printOut("Page i-val:", ph.m_page_i_value);
+ printOut("Place written:", ph.m_place_written_from);
+ printOut("Page No in File:", ph.m_page_no);
+ printOut("File No:", ph.m_file_no);
+ printOut("Word Written:", ph.m_word_written);
+ printOut("In Writing (should be 1)", ph.m_in_writing_flag);
+ printOut("Prev Page No (can be garbage)", ph.m_prev_page_no);
+ printOut("In Free List (should be 0):", ph.m_in_free_list);
no << endl;
return no;
}
diff --git a/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp b/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp
index b2da7427f4e..06bf7a85d53 100644
--- a/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp
+++ b/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp
@@ -147,6 +147,17 @@ protected:
Uint32 m_old_prepare_file_number;
Uint32 m_old_prepare_page_reference;
Uint32 m_dirty_flag;
+/* Debug info Start */
+ Uint32 m_log_timer;
+ Uint32 m_page_i_value;
+ Uint32 m_place_written_from;
+ Uint32 m_page_no;
+ Uint32 m_file_no;
+ Uint32 m_word_written;
+ Uint32 m_in_writing_flag;
+ Uint32 m_prev_page_no;
+ Uint32 m_in_free_list;
+/* Debug info End */
};
//----------------------------------------------------------------
diff --git a/ndb/src/kernel/main.cpp b/ndb/src/kernel/main.cpp
index aa220b0ae05..d9953b920d2 100644
--- a/ndb/src/kernel/main.cpp
+++ b/ndb/src/kernel/main.cpp
@@ -394,5 +394,5 @@ handler_sigusr1(int signum)
failed_startups++;
failed_startup_flag = true;
}
- g_eventLogger.info("Received signal %d. Ndbd failed startup (%u).", signum, failed_startups);
+ g_eventLogger.info("Angel received ndbd startup failure count %u.", failed_startups);
}
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index bf78adec970..06b534ac0ca 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -638,12 +638,10 @@ ndb_mgm_get_status(NdbMgmHandle handle)
Vector<BaseString> split;
tmp.split(split, ":");
if(split.size() != 2){
- abort();
return NULL;
}
if(!(split[0].trim() == "nodes")){
- abort();
return NULL;
}
@@ -692,7 +690,6 @@ ndb_mgm_get_status(NdbMgmHandle handle)
if(i+1 != noOfNodes){
free(state);
- abort();
return NULL;
}
diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp
index acab2ef9eac..56c24e5f862 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -39,6 +39,8 @@
#include <signaldata/BackupSignalData.hpp>
#include <signaldata/GrepImpl.hpp>
#include <signaldata/ManagementServer.hpp>
+#include <signaldata/NFCompleteRep.hpp>
+#include <signaldata/NodeFailRep.hpp>
#include <NdbSleep.h>
#include <EventLogger.hpp>
#include <DebuggerNames.hpp>
@@ -56,6 +58,8 @@
#include <mgmapi_config_parameters.h>
#include <m_string.h>
+#include <SignalSender.hpp>
+
//#define MGM_SRV_DEBUG
#ifdef MGM_SRV_DEBUG
#define DEBUG(x) do ndbout << x << endl; while(0)
@@ -709,6 +713,15 @@ int MgmtSrvr::okToSendTo(NodeId processId, bool unCond)
}
}
+void report_unknown_signal(SimpleSignal *signal)
+{
+ g_eventLogger.error("Unknown signal received. SignalNumber: "
+ "%i from (%d, %x)",
+ signal->readSignalNumber(),
+ refToNode(signal->header.theSendersBlockRef),
+ refToBlock(signal->header.theSendersBlockRef));
+}
+
/*****************************************************************************
* Starting and stopping database nodes
****************************************************************************/
@@ -1911,81 +1924,6 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
}
break;
- case GSN_BACKUP_CONF:{
- const BackupConf * const conf =
- CAST_CONSTPTR(BackupConf, signal->getDataPtr());
- BackupEvent event;
- event.Event = BackupEvent::BackupStarted;
- event.Started.BackupId = conf->backupId;
- event.Nodes = conf->nodes;
-#ifdef VM_TRACE
- ndbout_c("Backup master is %d", refToNode(signal->theSendersBlockRef));
-#endif
- backupCallback(event);
- }
- break;
-
- case GSN_BACKUP_REF:{
- const BackupRef * const ref =
- CAST_CONSTPTR(BackupRef, signal->getDataPtr());
- Uint32 errCode = ref->errorCode;
- if(ref->errorCode == BackupRef::IAmNotMaster){
- const Uint32 aNodeId = refToNode(ref->masterRef);
-#ifdef VM_TRACE
- ndbout_c("I'm not master resending to %d", aNodeId);
-#endif
- theWaitNode= aNodeId;
- NdbApiSignal aSignal(_ownReference);
- BackupReq* req = CAST_PTR(BackupReq, aSignal.getDataPtrSend());
- aSignal.set(TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
- BackupReq::SignalLength);
- req->senderData = 19;
- req->backupDataLen = 0;
-
- int i = theFacade->sendSignalUnCond(&aSignal, aNodeId);
- if(i == 0){
- return;
- }
- errCode = 5030;
- }
- BackupEvent event;
- event.Event = BackupEvent::BackupFailedToStart;
- event.FailedToStart.ErrorCode = errCode;
- backupCallback(event);
- break;
- }
-
- case GSN_BACKUP_ABORT_REP:{
- const BackupAbortRep * const rep =
- CAST_CONSTPTR(BackupAbortRep, signal->getDataPtr());
- BackupEvent event;
- event.Event = BackupEvent::BackupAborted;
- event.Aborted.Reason = rep->reason;
- event.Aborted.BackupId = rep->backupId;
- event.Aborted.ErrorCode = rep->reason;
- backupCallback(event);
- }
- break;
-
- case GSN_BACKUP_COMPLETE_REP:{
- const BackupCompleteRep * const rep =
- CAST_CONSTPTR(BackupCompleteRep, signal->getDataPtr());
- BackupEvent event;
- event.Event = BackupEvent::BackupCompleted;
- event.Completed.BackupId = rep->backupId;
-
- event.Completed.NoOfBytes = rep->noOfBytes;
- event.Completed.NoOfLogBytes = rep->noOfLogBytes;
- event.Completed.NoOfRecords = rep->noOfRecords;
- event.Completed.NoOfLogRecords = rep->noOfLogRecords;
- event.Completed.stopGCP = rep->stopGCP;
- event.Completed.startGCP = rep->startGCP;
- event.Nodes = rep->nodes;
-
- backupCallback(event);
- }
- break;
-
case GSN_MGM_LOCK_CONFIG_REP:
case GSN_MGM_LOCK_CONFIG_REQ:
case GSN_MGM_UNLOCK_CONFIG_REP:
@@ -2446,6 +2384,9 @@ MgmtSrvr::eventReport(NodeId nodeId, const Uint32 * theData)
int
MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
{
+ SignalSender ss(theFacade);
+ ss.lock(); // lock will be released on exit
+
bool next;
NodeId nodeId = 0;
while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
@@ -2453,50 +2394,124 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
if(!next) return NO_CONTACT_WITH_DB_NODES;
- NdbApiSignal* signal = getSignal();
- if (signal == NULL) {
- return COULD_NOT_ALLOCATE_MEMORY;
- }
+ SimpleSignal ssig;
- BackupReq* req = CAST_PTR(BackupReq, signal->getDataPtrSend());
- signal->set(TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
- BackupReq::SignalLength);
+ BackupReq* req = CAST_PTR(BackupReq, ssig.getDataPtrSend());
+ ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
+ BackupReq::SignalLength);
req->senderData = 19;
req->backupDataLen = 0;
+ assert(waitCompleted < 3);
+ req->flags = waitCompleted & 0x3;
- int result;
- if (waitCompleted == 2) {
- result = sendRecSignal(nodeId, WAIT_BACKUP_COMPLETED,
- signal, true, 48*60*60*1000 /* 48 hours */);
- }
- else if (waitCompleted == 1) {
- result = sendRecSignal(nodeId, WAIT_BACKUP_STARTED,
- signal, true, 5*60*1000 /*5 mins*/);
- }
- else {
- result = sendRecSignal(nodeId, NO_WAIT, signal, true);
- }
- if (result == -1) {
- return SEND_OR_RECEIVE_FAILED;
- }
-
- if (waitCompleted){
- switch(m_lastBackupEvent.Event){
- case BackupEvent::BackupCompleted:
- backupId = m_lastBackupEvent.Completed.BackupId;
+ BackupEvent event;
+ int do_send = 1;
+ while (1) {
+ if (do_send)
+ {
+ SendStatus result = ss.sendSignal(nodeId, &ssig);
+ if (result != SEND_OK) {
+ return SEND_OR_RECEIVE_FAILED;
+ }
+ if (waitCompleted == 0)
+ return 0;
+ do_send = 0;
+ }
+ SimpleSignal *signal = ss.waitFor();
+
+ int gsn = signal->readSignalNumber();
+ switch (gsn) {
+ case GSN_BACKUP_CONF:{
+ const BackupConf * const conf =
+ CAST_CONSTPTR(BackupConf, signal->getDataPtr());
+ event.Event = BackupEvent::BackupStarted;
+ event.Started.BackupId = conf->backupId;
+ event.Nodes = conf->nodes;
+#ifdef VM_TRACE
+ ndbout_c("Backup(%d) master is %d", conf->backupId,
+ refToNode(signal->header.theSendersBlockRef));
+#endif
+ backupId = conf->backupId;
+ if (waitCompleted == 1)
+ return 0;
+ // wait for next signal
break;
- case BackupEvent::BackupStarted:
- backupId = m_lastBackupEvent.Started.BackupId;
+ }
+ case GSN_BACKUP_COMPLETE_REP:{
+ const BackupCompleteRep * const rep =
+ CAST_CONSTPTR(BackupCompleteRep, signal->getDataPtr());
+#ifdef VM_TRACE
+ ndbout_c("Backup(%d) completed %d", rep->backupId);
+#endif
+ event.Event = BackupEvent::BackupCompleted;
+ event.Completed.BackupId = rep->backupId;
+
+ event.Completed.NoOfBytes = rep->noOfBytes;
+ event.Completed.NoOfLogBytes = rep->noOfLogBytes;
+ event.Completed.NoOfRecords = rep->noOfRecords;
+ event.Completed.NoOfLogRecords = rep->noOfLogRecords;
+ event.Completed.stopGCP = rep->stopGCP;
+ event.Completed.startGCP = rep->startGCP;
+ event.Nodes = rep->nodes;
+
+ backupId = rep->backupId;
+ return 0;
+ }
+ case GSN_BACKUP_REF:{
+ const BackupRef * const ref =
+ CAST_CONSTPTR(BackupRef, signal->getDataPtr());
+ if(ref->errorCode == BackupRef::IAmNotMaster){
+ nodeId = refToNode(ref->masterRef);
+#ifdef VM_TRACE
+ ndbout_c("I'm not master resending to %d", nodeId);
+#endif
+ do_send = 1; // try again
+ continue;
+ }
+ event.Event = BackupEvent::BackupFailedToStart;
+ event.FailedToStart.ErrorCode = ref->errorCode;
+ return ref->errorCode;
+ }
+ case GSN_BACKUP_ABORT_REP:{
+ const BackupAbortRep * const rep =
+ CAST_CONSTPTR(BackupAbortRep, signal->getDataPtr());
+ event.Event = BackupEvent::BackupAborted;
+ event.Aborted.Reason = rep->reason;
+ event.Aborted.BackupId = rep->backupId;
+ event.Aborted.ErrorCode = rep->reason;
+#ifdef VM_TRACE
+ ndbout_c("Backup %d aborted", rep->backupId);
+#endif
+ return rep->reason;
+ }
+ case GSN_NF_COMPLETEREP:{
+ const NFCompleteRep * const rep =
+ CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
+#ifdef VM_TRACE
+ ndbout_c("Node %d fail completed", rep->failedNodeId);
+#endif
+ if (rep->failedNodeId == nodeId ||
+ waitCompleted == 1)
+ return 1326;
+ // wait for next signal
+ // master node will report aborted backup
break;
- case BackupEvent::BackupFailedToStart:
- return m_lastBackupEvent.FailedToStart.ErrorCode;
- case BackupEvent::BackupAborted:
- return m_lastBackupEvent.Aborted.ErrorCode;
- default:
- return -1;
+ }
+ case GSN_NODE_FAILREP:{
+ const NodeFailRep * const rep =
+ CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
+ if (NodeBitmask::get(rep->theNodes,nodeId) ||
+ waitCompleted == 1)
+ return 1326;
+ // wait for next signal
+ // master node will report aborted backup
break;
}
+ default:
+ report_unknown_signal(signal);
+ return SEND_OR_RECEIVE_FAILED;
+ }
}
return 0;
@@ -2535,36 +2550,6 @@ MgmtSrvr::abortBackup(Uint32 backupId)
return 0;
}
-void
-MgmtSrvr::backupCallback(BackupEvent & event)
-{
- DBUG_ENTER("MgmtSrvr::backupCallback");
- m_lastBackupEvent = event;
- switch(event.Event){
- case BackupEvent::BackupFailedToStart:
- DBUG_PRINT("info",("BackupEvent::BackupFailedToStart"));
- theWaitState = NO_WAIT;
- break;
- case BackupEvent::BackupAborted:
- DBUG_PRINT("info",("BackupEvent::BackupAborted"));
- theWaitState = NO_WAIT;
- break;
- case BackupEvent::BackupCompleted:
- DBUG_PRINT("info",("BackupEvent::BackupCompleted"));
- theWaitState = NO_WAIT;
- break;
- case BackupEvent::BackupStarted:
- if(theWaitState == WAIT_BACKUP_STARTED)
- {
- DBUG_PRINT("info",("BackupEvent::BackupStarted NO_WAIT"));
- theWaitState = NO_WAIT;
- } else {
- DBUG_PRINT("info",("BackupEvent::BackupStarted"));
- }
- }
- DBUG_VOID_RETURN;
-}
-
/*****************************************************************************
* Global Replication
diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp
index c132852338b..f8c244a1bf1 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.hpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.hpp
@@ -757,9 +757,6 @@ private:
static void *signalRecvThread_C(void *);
void signalRecvThreadRun();
- void backupCallback(BackupEvent &);
- BackupEvent m_lastBackupEvent;
-
Config *_props;
int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type);
diff --git a/ndb/src/ndbapi/Makefile.am b/ndb/src/ndbapi/Makefile.am
index 9f8a851b995..1ba80ef7d85 100644
--- a/ndb/src/ndbapi/Makefile.am
+++ b/ndb/src/ndbapi/Makefile.am
@@ -35,7 +35,8 @@ libndbapi_la_SOURCES = \
NdbDictionaryImpl.cpp \
DictCache.cpp \
ndb_cluster_connection.cpp \
- NdbBlob.cpp
+ NdbBlob.cpp \
+ SignalSender.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp
index e1f70160fb7..c9e26f8ccaf 100644
--- a/ndb/src/ndbapi/NdbConnection.cpp
+++ b/ndb/src/ndbapi/NdbConnection.cpp
@@ -280,6 +280,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
AbortOption abortOption,
int forceSend)
{
+ NdbError savedError= theError;
DBUG_ENTER("NdbConnection::execute");
DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d",
aTypeOfExec, abortOption));
@@ -309,7 +310,11 @@ NdbConnection::execute(ExecType aTypeOfExec,
NdbBlob* tBlob = tPrepOp->theBlobList;
while (tBlob != NULL) {
if (tBlob->preExecute(tExecType, batch) == -1)
+ {
ret = -1;
+ if(savedError.code==0)
+ savedError= theError;
+ }
tBlob = tBlob->theNext;
}
if (batch) {
@@ -338,7 +343,11 @@ NdbConnection::execute(ExecType aTypeOfExec,
NdbBlob* tBlob = tOp->theBlobList;
while (tBlob != NULL) {
if (tBlob->preCommit() == -1)
- ret = -1;
+ {
+ ret = -1;
+ if(savedError.code==0)
+ savedError= theError;
+ }
tBlob = tBlob->theNext;
}
}
@@ -360,7 +369,12 @@ NdbConnection::execute(ExecType aTypeOfExec,
}
if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
- ret = -1;
+ {
+ ret = -1;
+ if(savedError.code==0)
+ savedError= theError;
+ }
+
#ifdef ndb_api_crash_on_complex_blob_abort
assert(theFirstOpInList == NULL && theLastOpInList == NULL);
#else
@@ -375,7 +389,11 @@ NdbConnection::execute(ExecType aTypeOfExec,
while (tBlob != NULL) {
// may add new operations if batch
if (tBlob->postExecute(tExecType) == -1)
+ {
ret = -1;
+ if(savedError.code==0)
+ savedError= theError;
+ }
tBlob = tBlob->theNext;
}
}
@@ -406,6 +424,10 @@ NdbConnection::execute(ExecType aTypeOfExec,
ndbout << "completed ops: " << n << endl;
}
#endif
+
+ if(savedError.code!=0 && theError.code==4350) // Trans already aborted
+ theError= savedError;
+
DBUG_RETURN(ret);
}
diff --git a/ndb/src/ndbapi/SignalSender.cpp b/ndb/src/ndbapi/SignalSender.cpp
new file mode 100644
index 00000000000..a29fe68937b
--- /dev/null
+++ b/ndb/src/ndbapi/SignalSender.cpp
@@ -0,0 +1,280 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#include "SignalSender.hpp"
+#include <NdbSleep.h>
+#include <SignalLoggerManager.hpp>
+#include <signaldata/NFCompleteRep.hpp>
+#include <signaldata/NodeFailRep.hpp>
+
+SimpleSignal::SimpleSignal(bool dealloc){
+ memset(this, 0, sizeof(* this));
+ deallocSections = dealloc;
+}
+
+SimpleSignal::~SimpleSignal(){
+ if(!deallocSections)
+ return;
+ if(ptr[0].p != 0) delete []ptr[0].p;
+ if(ptr[1].p != 0) delete []ptr[1].p;
+ if(ptr[2].p != 0) delete []ptr[2].p;
+}
+
+void
+SimpleSignal::set(class SignalSender& ss,
+ Uint8 trace, Uint16 recBlock, Uint16 gsn, Uint32 len){
+
+ header.theTrace = trace;
+ header.theReceiversBlockNumber = recBlock;
+ header.theVerId_signalNumber = gsn;
+ header.theLength = len;
+ header.theSendersBlockRef = refToBlock(ss.getOwnRef());
+}
+
+void
+SimpleSignal::print(FILE * out){
+ fprintf(out, "---- Signal ----------------\n");
+ SignalLoggerManager::printSignalHeader(out, header, 0, 0, false);
+ SignalLoggerManager::printSignalData(out, header, theData);
+ for(Uint32 i = 0; i<header.m_noOfSections; i++){
+ Uint32 len = ptr[i].sz;
+ fprintf(out, " --- Section %d size=%d ---\n", i, len);
+ Uint32 * signalData = ptr[i].p;
+ while(len >= 7){
+ fprintf(out,
+ " H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x\n",
+ signalData[0], signalData[1], signalData[2], signalData[3],
+ signalData[4], signalData[5], signalData[6]);
+ len -= 7;
+ signalData += 7;
+ }
+ if(len > 0){
+ fprintf(out, " H\'%.8x", signalData[0]);
+ for(Uint32 i = 1; i<len; i++)
+ fprintf(out, " H\'%.8x", signalData[i]);
+ fprintf(out, "\n");
+ }
+ }
+}
+
+SignalSender::SignalSender(TransporterFacade *facade)
+ : m_lock(0)
+{
+ m_cond = NdbCondition_Create();
+ theFacade = facade;
+ m_blockNo = theFacade->open(this, execSignal, execNodeStatus);
+ assert(m_blockNo > 0);
+}
+
+SignalSender::~SignalSender(){
+ int i;
+ if (m_lock)
+ unlock();
+ theFacade->close(m_blockNo,0);
+ // free these _after_ closing theFacade to ensure that
+ // we delete all signals
+ for (i= m_jobBuffer.size()-1; i>= 0; i--)
+ delete m_jobBuffer[i];
+ for (i= m_usedBuffer.size()-1; i>= 0; i--)
+ delete m_usedBuffer[i];
+ NdbCondition_Destroy(m_cond);
+}
+
+int SignalSender::lock()
+{
+ if (NdbMutex_Lock(theFacade->theMutexPtr))
+ return -1;
+ m_lock= 1;
+ return 0;
+}
+
+int SignalSender::unlock()
+{
+ if (NdbMutex_Unlock(theFacade->theMutexPtr))
+ return -1;
+ m_lock= 0;
+ return 0;
+}
+
+Uint32
+SignalSender::getOwnRef() const {
+ return numberToRef(m_blockNo, theFacade->ownId());
+}
+
+Uint32
+SignalSender::getAliveNode() const{
+ return theFacade->get_an_alive_node();
+}
+
+const ClusterMgr::Node &
+SignalSender::getNodeInfo(Uint16 nodeId) const {
+ return theFacade->theClusterMgr->getNodeInfo(nodeId);
+}
+
+Uint32
+SignalSender::getNoOfConnectedNodes() const {
+ return theFacade->theClusterMgr->getNoOfConnectedNodes();
+}
+
+SendStatus
+SignalSender::sendSignal(Uint16 nodeId, const SimpleSignal * s){
+ return theFacade->theTransporterRegistry->prepareSend(&s->header,
+ 1, // JBB
+ &s->theData[0],
+ nodeId,
+ &s->ptr[0]);
+}
+
+template<class T>
+SimpleSignal *
+SignalSender::waitFor(Uint32 timeOutMillis, T & t)
+{
+ SimpleSignal * s = t.check(m_jobBuffer);
+ if(s != 0){
+ return s;
+ }
+
+ NDB_TICKS now = NdbTick_CurrentMillisecond();
+ NDB_TICKS stop = now + timeOutMillis;
+ Uint32 wait = (timeOutMillis == 0 ? 10 : timeOutMillis);
+ do {
+ NdbCondition_WaitTimeout(m_cond,
+ theFacade->theMutexPtr,
+ wait);
+
+
+ SimpleSignal * s = t.check(m_jobBuffer);
+ if(s != 0){
+ m_usedBuffer.push_back(s);
+ return s;
+ }
+
+ now = NdbTick_CurrentMillisecond();
+ wait = (timeOutMillis == 0 ? 10 : stop - now);
+ } while(stop > now || timeOutMillis == 0);
+
+ return 0;
+}
+
+class WaitForAny {
+public:
+ SimpleSignal * check(Vector<SimpleSignal*> & m_jobBuffer){
+ if(m_jobBuffer.size() > 0){
+ SimpleSignal * s = m_jobBuffer[0];
+ m_jobBuffer.erase(0);
+ return s;
+ }
+ return 0;
+ }
+};
+
+SimpleSignal *
+SignalSender::waitFor(Uint32 timeOutMillis){
+
+ WaitForAny w;
+ return waitFor(timeOutMillis, w);
+}
+
+class WaitForNode {
+public:
+ Uint32 m_nodeId;
+ SimpleSignal * check(Vector<SimpleSignal*> & m_jobBuffer){
+ Uint32 len = m_jobBuffer.size();
+ for(Uint32 i = 0; i<len; i++){
+ if(refToNode(m_jobBuffer[i]->header.theSendersBlockRef) == m_nodeId){
+ SimpleSignal * s = m_jobBuffer[i];
+ m_jobBuffer.erase(i);
+ return s;
+ }
+ }
+ return 0;
+ }
+};
+
+SimpleSignal *
+SignalSender::waitFor(Uint16 nodeId, Uint32 timeOutMillis){
+
+ WaitForNode w;
+ w.m_nodeId = nodeId;
+ return waitFor(timeOutMillis, w);
+}
+
+#include <NdbApiSignal.hpp>
+
+void
+SignalSender::execSignal(void* signalSender,
+ NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3]){
+ SimpleSignal * s = new SimpleSignal(true);
+ s->header = * signal;
+ memcpy(&s->theData[0], signal->getDataPtr(), 4 * s->header.theLength);
+ for(Uint32 i = 0; i<s->header.m_noOfSections; i++){
+ s->ptr[i].p = new Uint32[ptr[i].sz];
+ s->ptr[i].sz = ptr[i].sz;
+ memcpy(s->ptr[i].p, ptr[i].p, 4 * ptr[i].sz);
+ }
+ SignalSender * ss = (SignalSender*)signalSender;
+ ss->m_jobBuffer.push_back(s);
+ NdbCondition_Signal(ss->m_cond);
+}
+
+void
+SignalSender::execNodeStatus(void* signalSender,
+ Uint32 nodeId,
+ bool alive,
+ bool nfCompleted){
+ if (alive) {
+ // node connected
+ return;
+ }
+
+ SimpleSignal * s = new SimpleSignal(true);
+ SignalSender * ss = (SignalSender*)signalSender;
+
+ // node disconnected
+ if(nfCompleted)
+ {
+ // node shutdown complete
+ s->header.theVerId_signalNumber = GSN_NF_COMPLETEREP;
+ NFCompleteRep *rep = (NFCompleteRep *)s->getDataPtrSend();
+ rep->blockNo = 0;
+ rep->nodeId = 0;
+ rep->failedNodeId = nodeId;
+ rep->unused = 0;
+ rep->from = 0;
+ }
+ else
+ {
+ // node failure
+ s->header.theVerId_signalNumber = GSN_NODE_FAILREP;
+ NodeFailRep *rep = (NodeFailRep *)s->getDataPtrSend();
+ rep->failNo = 0;
+ rep->masterNodeId = 0;
+ rep->noOfNodes = 1;
+ NodeBitmask::clear(rep->theNodes);
+ NodeBitmask::set(rep->theNodes,nodeId);
+ }
+
+ ss->m_jobBuffer.push_back(s);
+ NdbCondition_Signal(ss->m_cond);
+}
+
+#if __SUNPRO_CC != 0x560
+template SimpleSignal* SignalSender::waitFor<WaitForNode>(unsigned, WaitForNode&);
+template SimpleSignal* SignalSender::waitFor<WaitForAny>(unsigned, WaitForAny&);
+#endif
+template class Vector<SimpleSignal*>;
+
diff --git a/ndb/src/ndbapi/SignalSender.hpp b/ndb/src/ndbapi/SignalSender.hpp
new file mode 100644
index 00000000000..4b991460034
--- /dev/null
+++ b/ndb/src/ndbapi/SignalSender.hpp
@@ -0,0 +1,83 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#ifndef SIGNAL_SENDER_HPP
+#define SIGNAL_SENDER_HPP
+
+#include <ndb_global.h>
+#include "TransporterFacade.hpp"
+#include <Vector.hpp>
+
+struct SimpleSignal {
+public:
+ SimpleSignal(bool dealloc = false);
+ ~SimpleSignal();
+
+ void set(class SignalSender&,
+ Uint8 trace, Uint16 recBlock, Uint16 gsn, Uint32 len);
+
+ struct SignalHeader header;
+ Uint32 theData[25];
+ LinearSectionPtr ptr[3];
+
+ int readSignalNumber() {return header.theVerId_signalNumber; }
+ Uint32 *getDataPtrSend() { return theData; }
+ const Uint32 *getDataPtr() const { return theData; }
+
+ void print(FILE * out = stdout);
+private:
+ bool deallocSections;
+};
+
+class SignalSender {
+public:
+ SignalSender(TransporterFacade *facade);
+ virtual ~SignalSender();
+
+ int lock();
+ int unlock();
+
+ Uint32 getOwnRef() const;
+ Uint32 getAliveNode() const;
+ const ClusterMgr::Node &getNodeInfo(Uint16 nodeId) const;
+ Uint32 getNoOfConnectedNodes() const;
+
+ SendStatus sendSignal(Uint16 nodeId, const SimpleSignal *);
+
+ SimpleSignal * waitFor(Uint32 timeOutMillis = 0);
+ SimpleSignal * waitFor(Uint16 nodeId, Uint32 timeOutMillis = 0);
+ SimpleSignal * waitFor(Uint16 nodeId, Uint16 gsn, Uint32 timeOutMillis = 0);
+private:
+ int m_blockNo;
+ TransporterFacade * theFacade;
+
+ static void execSignal(void* signalSender,
+ NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3]);
+
+ static void execNodeStatus(void* signalSender, Uint32 nodeId,
+ bool alive, bool nfCompleted);
+
+ int m_lock;
+ struct NdbCondition * m_cond;
+ Vector<SimpleSignal *> m_jobBuffer;
+ Vector<SimpleSignal *> m_usedBuffer;
+
+ template<class T>
+ SimpleSignal * waitFor(Uint32 timeOutMillis, T & t);
+};
+
+#endif
diff --git a/ndb/test/include/NDBT_Test.hpp b/ndb/test/include/NDBT_Test.hpp
index a60228c1a5d..bcaa0bf4d40 100644
--- a/ndb/test/include/NDBT_Test.hpp
+++ b/ndb/test/include/NDBT_Test.hpp
@@ -64,7 +64,8 @@ public:
const char* getPropertyWait(const char*, const char* );
void decProperty(const char *);
-
+ void incProperty(const char *);
+
// Communicate with other tests
void stopTest();
bool isTestStopped();
diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am
index 6f04ac3fce2..7b4a96f5890 100644
--- a/ndb/test/ndbapi/Makefile.am
+++ b/ndb/test/ndbapi/Makefile.am
@@ -31,7 +31,8 @@ testTimeout \
testTransactions \
testDeadlock \
test_event ndbapi_slow_select testReadPerf testLcp \
-DbCreate DbAsyncGenerator
+DbCreate DbAsyncGenerator \
+testSRBank
#flexTimedAsynch
#testBlobs
@@ -72,6 +73,7 @@ testReadPerf_SOURCES = testReadPerf.cpp
testLcp_SOURCES = testLcp.cpp
DbCreate_SOURCES= bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
DbAsyncGenerator_SOURCES= bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
+testSRBank_SOURCES = testSRBank.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel
@@ -83,6 +85,7 @@ include $(top_srcdir)/ndb/config/type_ndbapitest.mk.am
##testSystemRestart_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
##testTransactions_INCLUDES = $(INCLUDES) -I$(top_srcdir)/ndb/include/kernel
testBackup_LDADD = $(LDADD) bank/libbank.a
+testSRBank_LDADD = bank/libbank.a $(LDADD)
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/ndb/test/ndbapi/bank/Bank.cpp b/ndb/test/ndbapi/bank/Bank.cpp
index c6029259357..346442367fc 100644
--- a/ndb/test/ndbapi/bank/Bank.cpp
+++ b/ndb/test/ndbapi/bank/Bank.cpp
@@ -19,12 +19,13 @@
#include <NdbSleep.h>
#include <UtilTransactions.hpp>
-Bank::Bank():
+Bank::Bank(bool _init):
m_ndb("BANK"),
m_maxAccount(-1),
m_initialized(false)
{
-
+ if(_init)
+ init();
}
int Bank::init(){
@@ -34,40 +35,39 @@ int Bank::init(){
myRandom48Init(NdbTick_CurrentMillisecond());
m_ndb.init();
- while (m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
+ if (m_ndb.waitUntilReady(30) != 0)
+ {
+ ndbout << "Ndb not ready" << endl;
+ return NDBT_FAILED;
+ }
+
if (getNumAccounts() != NDBT_OK)
return NDBT_FAILED;
+
+ m_initialized = true;
return NDBT_OK;
}
int Bank::performTransactions(int maxSleepBetweenTrans, int yield){
- if (init() != NDBT_OK)
- return NDBT_FAILED;
int transactions = 0;
- while(1){
-
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
- while(performTransaction() != NDBT_FAILED){
- transactions++;
-
- if (maxSleepBetweenTrans > 0){
- int val = myRandom48(maxSleepBetweenTrans);
- NdbSleep_MilliSleep(val);
- }
-
- if((transactions % 100) == 0)
- g_info << transactions << endl;
-
- if (yield != 0 && transactions >= yield)
- return NDBT_OK;
+ while(performTransaction() == NDBT_OK)
+ {
+ transactions++;
+
+ if (maxSleepBetweenTrans > 0){
+ int val = myRandom48(maxSleepBetweenTrans);
+ NdbSleep_MilliSleep(val);
}
+
+ if((transactions % 100) == 0)
+ g_info << transactions << endl;
+
+ if (yield != 0 && transactions >= yield)
+ return NDBT_OK;
}
+
return NDBT_FAILED;
}
@@ -92,7 +92,7 @@ int Bank::performTransaction(){
int amount = myRandom48(maxAmount);
- retry_transaction:
+retry_transaction:
int res = performTransaction(fromAccount, toAccount, amount);
if (res != 0){
switch (res){
@@ -158,8 +158,9 @@ int Bank::performTransactionImpl1(int fromAccountId,
// Ok, all clear to do the transaction
Uint64 transId;
- if (getNextTransactionId(transId) != NDBT_OK){
- return NDBT_FAILED;
+ int result = NDBT_OK;
+ if ((result= getNextTransactionId(transId)) != NDBT_OK){
+ return result;
}
NdbConnection* pTrans = m_ndb.startTransaction();
@@ -500,8 +501,6 @@ int Bank::performTransactionImpl1(int fromAccountId,
int Bank::performMakeGLs(int yield){
int result;
- if (init() != NDBT_OK)
- return NDBT_FAILED;
int counter, maxCounter;
int yieldCounter = 0;
@@ -512,9 +511,6 @@ int Bank::performMakeGLs(int yield){
counter = 0;
maxCounter = 50 + myRandom48(100);
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
/**
* Validate GLs and Transactions for previous days
*
@@ -526,6 +522,7 @@ int Bank::performMakeGLs(int yield){
return NDBT_FAILED;
}
g_info << "performValidateGLs failed" << endl;
+ return NDBT_FAILED;
continue;
}
@@ -536,7 +533,7 @@ int Bank::performMakeGLs(int yield){
return NDBT_FAILED;
}
g_info << "performValidatePurged failed" << endl;
- continue;
+ return NDBT_FAILED;
}
while (1){
@@ -607,14 +604,9 @@ int Bank::performMakeGLs(int yield){
int Bank::performValidateAllGLs(){
int result;
- if (init() != NDBT_OK)
- return NDBT_FAILED;
while (1){
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
/**
* Validate GLs and Transactions for previous days
* Set age so that ALL GL's are validated
@@ -1937,39 +1929,29 @@ int Bank::findTransactionsToPurge(const Uint64 glTime,
}
- int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield){
- if (init() != NDBT_OK)
- return NDBT_FAILED;
-
+int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield)
+{
int yieldCounter = 0;
-
- while(1){
-
- while(m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
- while(1){
-
- Uint64 currTime;
- if (incCurrTime(currTime) != NDBT_OK)
- break;
-
- g_info << "Current time is " << currTime << endl;
- if (maxSleepBetweenDays > 0){
- int val = myRandom48(maxSleepBetweenDays);
- NdbSleep_SecSleep(val);
- }
-
- yieldCounter++;
- if (yield != 0 && yieldCounter >= yield)
- return NDBT_OK;
-
- }
- }
- return NDBT_FAILED;
- }
-
-
+
+ while(1){
+
+ Uint64 currTime;
+ if (incCurrTime(currTime) != NDBT_OK)
+ break;
+
+ g_info << "Current time is " << currTime << endl;
+ if (maxSleepBetweenDays > 0){
+ int val = myRandom48(maxSleepBetweenDays);
+ NdbSleep_SecSleep(val);
+ }
+
+ yieldCounter++;
+ if (yield != 0 && yieldCounter >= yield)
+ return NDBT_OK;
+
+ }
+ return NDBT_FAILED;
+}
int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){
@@ -1978,22 +1960,30 @@ int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){
NdbConnection* pTrans = m_ndb.startTransaction();
if (pTrans == NULL){
ERR(m_ndb.getNdbError());
+ if(m_ndb.getNdbError().status == NdbError::TemporaryError)
+ return NDBT_TEMPORARY;
return NDBT_FAILED;
}
- if (prepareReadSystemValueOp(pTrans, sysValId, value) != NDBT_OK) {
+ int result;
+ if ((result= prepareReadSystemValueOp(pTrans, sysValId, value)) != NDBT_OK) {
ERR(pTrans->getNdbError());
m_ndb.closeTransaction(pTrans);
- return NDBT_FAILED;
+ return result;
}
check = pTrans->execute(Commit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
+ if(pTrans->getNdbError().status == NdbError::TemporaryError)
+ {
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_TEMPORARY;
+ }
m_ndb.closeTransaction(pTrans);
return NDBT_FAILED;
}
-
+
m_ndb.closeTransaction(pTrans);
return NDBT_OK;
@@ -2099,6 +2089,8 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
NdbConnection* pTrans = m_ndb.startTransaction();
if (pTrans == NULL){
ERR(m_ndb.getNdbError());
+ if (m_ndb.getNdbError().status == NdbError::TemporaryError)
+ DBUG_RETURN(NDBT_TEMPORARY);
DBUG_RETURN(NDBT_FAILED);
}
@@ -2134,6 +2126,11 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
check = pTrans->execute(NoCommit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
+ if (pTrans->getNdbError().status == NdbError::TemporaryError)
+ {
+ m_ndb.closeTransaction(pTrans);
+ DBUG_RETURN(NDBT_TEMPORARY);
+ }
m_ndb.closeTransaction(pTrans);
DBUG_RETURN(NDBT_FAILED);
}
@@ -2208,16 +2205,21 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
check = pTrans->execute(Commit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
+ if (pTrans->getNdbError().status == NdbError::TemporaryError)
+ {
+ m_ndb.closeTransaction(pTrans);
+ DBUG_RETURN(NDBT_TEMPORARY);
+ }
m_ndb.closeTransaction(pTrans);
DBUG_RETURN(NDBT_FAILED);
}
// Check that value updated equals the value we read after the update
if (valueNewRec->u_64_value() != value){
-
+
printf("value actual=%lld\n", valueNewRec->u_64_value());
printf("value expected=%lld actual=%lld\n", value, valueNewRec->u_64_value());
-
+
DBUG_PRINT("info", ("value expected=%ld actual=%ld", value, valueNewRec->u_64_value()));
g_err << "getNextTransactionId: value was not updated" << endl;
m_ndb.closeTransaction(pTrans);
@@ -2225,7 +2227,7 @@ int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
}
m_ndb.closeTransaction(pTrans);
-
+
DBUG_RETURN(0);
}
@@ -2242,6 +2244,8 @@ int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){
NdbConnection* pTrans = m_ndb.startTransaction();
if (pTrans == NULL){
ERR(m_ndb.getNdbError());
+ if(m_ndb.getNdbError().status == NdbError::TemporaryError)
+ return NDBT_TEMPORARY;
return NDBT_FAILED;
}
@@ -2284,6 +2288,11 @@ int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){
check = pTrans->execute(Commit);
if( check == -1 ) {
ERR(pTrans->getNdbError());
+ if(pTrans->getNdbError().status == NdbError::TemporaryError)
+ {
+ m_ndb.closeTransaction(pTrans);
+ return NDBT_TEMPORARY;
+ }
m_ndb.closeTransaction(pTrans);
return NDBT_FAILED;
}
@@ -2308,16 +2317,11 @@ int Bank::prepareGetCurrTimeOp(NdbConnection *pTrans, Uint64 &time){
int Bank::performSumAccounts(int maxSleepBetweenSums, int yield){
- if (init() != NDBT_OK)
- return NDBT_FAILED;
int yieldCounter = 0;
while (1){
- while (m_ndb.waitUntilReady(10) != 0)
- ndbout << "Waiting for ndb to be ready" << endl;
-
Uint32 sumAccounts = 0;
Uint32 numAccounts = 0;
if (getSumAccounts(sumAccounts, numAccounts) != NDBT_OK){
diff --git a/ndb/test/ndbapi/bank/Bank.hpp b/ndb/test/ndbapi/bank/Bank.hpp
index 34c5ff51cc2..14e01df29d5 100644
--- a/ndb/test/ndbapi/bank/Bank.hpp
+++ b/ndb/test/ndbapi/bank/Bank.hpp
@@ -27,7 +27,7 @@
class Bank {
public:
- Bank();
+ Bank(bool init = true);
int createAndLoadBank(bool overWrite, int num_accounts=10);
int dropBank();
diff --git a/ndb/test/ndbapi/testSRBank.cpp b/ndb/test/ndbapi/testSRBank.cpp
new file mode 100644
index 00000000000..5677f551da6
--- /dev/null
+++ b/ndb/test/ndbapi/testSRBank.cpp
@@ -0,0 +1,246 @@
+/* Copyright (C) 2003 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 */
+
+#include <NDBT.hpp>
+#include <NDBT_Test.hpp>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <NdbBackup.hpp>
+
+#include "bank/Bank.hpp"
+
+int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int overWriteExisting = true;
+ if (bank.createAndLoadBank(overWriteExisting, 10) != NDBT_OK)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+/**
+ *
+ * SR 0 - normal
+ * SR 1 - shutdown in progress
+ * SR 2 - restart in progress
+ */
+int runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
+ int wait = 5; // Max seconds between each "day"
+ int yield = 1; // Loops before bank returns
+
+ ctx->incProperty("ThreadCount");
+ while (!ctx->isTestStopped())
+ {
+ Bank bank;
+ while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1)
+ if(bank.performIncreaseTime(wait, yield) == NDBT_FAILED)
+ break;
+
+ ndbout_c("runBankTimer is stopped");
+ ctx->incProperty("ThreadStopped");
+ if(ctx->getPropertyWait("SR", (Uint32)0))
+ break;
+ }
+ return NDBT_OK;
+}
+
+int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
+ int wait = 0; // Max ms between each transaction
+ int yield = 1; // Loops before bank returns
+
+ ctx->incProperty("ThreadCount");
+ while (!ctx->isTestStopped())
+ {
+ Bank bank;
+ while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1)
+ if(bank.performTransactions(0, 1) == NDBT_FAILED)
+ break;
+
+ ndbout_c("runBankTransactions is stopped");
+ ctx->incProperty("ThreadStopped");
+ if(ctx->getPropertyWait("SR", (Uint32)0))
+ break;
+ }
+ return NDBT_OK;
+}
+
+int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
+ int yield = 1; // Loops before bank returns
+ int result = NDBT_OK;
+
+ ctx->incProperty("ThreadCount");
+ while (ctx->isTestStopped() == false)
+ {
+ Bank bank;
+ while(!ctx->isTestStopped() && ctx->getProperty("SR") <= 1)
+ if (bank.performMakeGLs(yield) != NDBT_OK)
+ {
+ if(ctx->getProperty("SR") != 0)
+ break;
+ ndbout << "bank.performMakeGLs FAILED" << endl;
+ return NDBT_FAILED;
+ }
+
+ ndbout_c("runBankGL is stopped");
+ ctx->incProperty("ThreadStopped");
+ if(ctx->getPropertyWait("SR", (Uint32)0))
+ break;
+ }
+ return NDBT_OK;
+}
+
+int runBankSum(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ int wait = 2000; // Max ms between each sum of accounts
+ int yield = 1; // Loops before bank returns
+ int result = NDBT_OK;
+
+ while (ctx->isTestStopped() == false) {
+ if (bank.performSumAccounts(wait, yield) != NDBT_OK){
+ ndbout << "bank.performSumAccounts FAILED" << endl;
+ result = NDBT_FAILED;
+ }
+ }
+ return result ;
+}
+
+#define CHECK(b) if (!(b)) { \
+ g_err << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ result = NDBT_FAILED; \
+ continue; }
+
+int runSR(NDBT_Context* ctx, NDBT_Step* step)
+{
+ int result = NDBT_OK;
+ int runtime = ctx->getNumLoops();
+ int sleeptime = ctx->getNumRecords();
+ NdbRestarter restarter;
+ bool abort = true;
+ int timeout = 180;
+
+ Uint32 now;
+ const Uint32 stop = time(0)+ runtime;
+ while(!ctx->isTestStopped() && ((now= time(0)) < stop) && result == NDBT_OK)
+ {
+ ndbout << " -- Sleep " << sleeptime << "s " << endl;
+ NdbSleep_SecSleep(sleeptime);
+ ndbout << " -- Shutting down " << endl;
+ ctx->setProperty("SR", 1);
+ CHECK(restarter.restartAll(false, true, abort) == 0);
+ ctx->setProperty("SR", 2);
+ CHECK(restarter.waitClusterNoStart(timeout) == 0);
+
+ Uint32 cnt = ctx->getProperty("ThreadCount");
+ Uint32 curr= ctx->getProperty("ThreadStopped");
+ while(curr != cnt)
+ {
+ ndbout_c("%d %d", curr, cnt);
+ NdbSleep_MilliSleep(100);
+ curr= ctx->getProperty("ThreadStopped");
+ }
+
+ ctx->setProperty("ThreadStopped", (Uint32)0);
+ CHECK(restarter.startAll() == 0);
+ CHECK(restarter.waitClusterStarted(timeout) == 0);
+
+ ndbout << " -- Validating starts " << endl;
+ {
+ int wait = 0;
+ int yield = 1;
+ Bank bank;
+ if (bank.performSumAccounts(wait, yield) != 0)
+ {
+ ndbout << "bank.performSumAccounts FAILED" << endl;
+ return NDBT_FAILED;
+ }
+
+ if (bank.performValidateAllGLs() != 0)
+ {
+ ndbout << "bank.performValidateAllGLs FAILED" << endl;
+ return NDBT_FAILED;
+ }
+ }
+
+ ndbout << " -- Validating complete " << endl;
+ ctx->setProperty("SR", (Uint32)0);
+ ctx->broadcast();
+ }
+ ctx->stopTest();
+ return NDBT_OK;
+}
+
+int runDropBank(NDBT_Context* ctx, NDBT_Step* step){
+ Bank bank;
+ if (bank.dropBank() != NDBT_OK)
+ return NDBT_FAILED;
+ return NDBT_OK;
+}
+
+
+NDBT_TESTSUITE(testSRBank);
+TESTCASE("Graceful",
+ " Test that a consistent bank is restored after graceful shutdown\n"
+ "1. Create bank\n"
+ "2. Start bank and let it run\n"
+ "3. Restart ndb and verify consistency\n"
+ "4. Drop bank\n")
+{
+ INITIALIZER(runCreateBank);
+ STEP(runBankTimer);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankGL);
+ STEP(runSR);
+}
+TESTCASE("Abort",
+ " Test that a consistent bank is restored after graceful shutdown\n"
+ "1. Create bank\n"
+ "2. Start bank and let it run\n"
+ "3. Restart ndb and verify consistency\n"
+ "4. Drop bank\n")
+{
+ INITIALIZER(runCreateBank);
+ STEP(runBankTimer);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankTransactions);
+ STEP(runBankGL);
+ STEP(runSR);
+ FINALIZER(runDropBank);
+}
+NDBT_TESTSUITE_END(testSRBank);
+
+int main(int argc, const char** argv){
+ ndb_init();
+ return testSRBank.execute(argc, argv);
+}
+
+
diff --git a/ndb/test/src/NDBT_Test.cpp b/ndb/test/src/NDBT_Test.cpp
index 600a5443f40..6355c21c997 100644
--- a/ndb/test/src/NDBT_Test.cpp
+++ b/ndb/test/src/NDBT_Test.cpp
@@ -145,6 +145,15 @@ NDBT_Context::decProperty(const char * name){
NdbCondition_Broadcast(propertyCondPtr);
NdbMutex_Unlock(propertyMutexPtr);
}
+void
+NDBT_Context::incProperty(const char * name){
+ NdbMutex_Lock(propertyMutexPtr);
+ Uint32 val = 0;
+ props.get(name, &val);
+ props.put(name, (val + 1), true);
+ NdbCondition_Broadcast(propertyCondPtr);
+ NdbMutex_Unlock(propertyMutexPtr);
+}
void NDBT_Context::setProperty(const char* _name, const char* _val){
NdbMutex_Lock(propertyMutexPtr);
diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp
index 28724323bd7..1e56db83c11 100644
--- a/ndb/test/src/NdbBackup.cpp
+++ b/ndb/test/src/NdbBackup.cpp
@@ -50,14 +50,17 @@ NdbBackup::start(unsigned int & _backup_id){
2, // wait until completed
&_backup_id,
&reply) == -1) {
- g_err << "Could not start backup " << endl;
- g_err << "Error: " << reply.message << endl;
+ g_err << "Error: " << ndb_mgm_get_latest_error(handle) << endl;
+ g_err << "Error msg: " << ndb_mgm_get_latest_error_msg(handle) << endl;
+ g_err << "Error desc: " << ndb_mgm_get_latest_error_desc(handle) << endl;
return -1;
}
if(reply.return_code != 0){
g_err << "PLEASE CHECK CODE NdbBackup.cpp line=" << __LINE__ << endl;
- g_err << "Error: " << reply.message << endl;
+ g_err << "Error: " << ndb_mgm_get_latest_error(handle) << endl;
+ g_err << "Error msg: " << ndb_mgm_get_latest_error_msg(handle) << endl;
+ g_err << "Error desc: " << ndb_mgm_get_latest_error_desc(handle) << endl;
return reply.return_code;
}
return 0;
diff --git a/ndb/test/src/UtilTransactions.cpp b/ndb/test/src/UtilTransactions.cpp
index 869f7fc76cb..92073143d34 100644
--- a/ndb/test/src/UtilTransactions.cpp
+++ b/ndb/test/src/UtilTransactions.cpp
@@ -766,19 +766,29 @@ UtilTransactions::selectCount(Ndb* pNdb,
int check;
NdbScanOperation *pOp;
- if(!pTrans)
- pTrans = pNdb->startTransaction();
while (true){
-
if (retryAttempt >= retryMax){
g_info << "ERROR: has retried this operation " << retryAttempt
<< " times, failing!" << endl;
return NDBT_FAILED;
}
+ if(!pTrans)
+ pTrans = pNdb->startTransaction();
+
+ if(!pTrans)
+ {
+ const NdbError err = pNdb->getNdbError();
+
+ if (err.status == NdbError::TemporaryError)
+ continue;
+ return NDBT_FAILED;
+ }
+
pOp = pTrans->getNdbScanOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
return NDBT_FAILED;
}
@@ -786,6 +796,7 @@ UtilTransactions::selectCount(Ndb* pNdb,
if( rs == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
return NDBT_FAILED;
}
@@ -799,6 +810,7 @@ UtilTransactions::selectCount(Ndb* pNdb,
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
return NDBT_FAILED;
}
}
@@ -808,6 +820,7 @@ UtilTransactions::selectCount(Ndb* pNdb,
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
return NDBT_FAILED;
}
@@ -823,16 +836,19 @@ UtilTransactions::selectCount(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
return NDBT_FAILED;
}
pNdb->closeTransaction(pTrans);
+ pTrans = 0;
if (count_rows != NULL){
*count_rows = rows;
diff --git a/sql-common/client.c b/sql-common/client.c
index 73e136f7366..3979b9304f7 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -602,7 +602,7 @@ net_safe_read(MYSQL *mysql)
DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d",
vio_description(net->vio),len));
#ifdef MYSQL_SERVER
- if (vio_errno(net->vio) == SOCKET_EINTR)
+ if (vio_was_interrupted(net->vio))
return (packet_error);
#endif /*MYSQL_SERVER*/
end_server(mysql);
diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc
index 577ead8a86d..ee4cad25460 100644
--- a/sql/examples/ha_archive.cc
+++ b/sql/examples/ha_archive.cc
@@ -520,7 +520,7 @@ int ha_archive::create(const char *name, TABLE *table_arg,
error= my_errno;
goto error;
}
- if ((archive= gzdopen(create_file, "ab")) == NULL)
+ if ((archive= gzdopen(create_file, "wb")) == NULL)
{
error= errno;
goto error2;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 75b114fc140..63a8515020b 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -443,7 +443,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
ha_store_ptr(ref_pos,ref_length,record); // Position to row
record+=sort_form->db_record_offset;
}
- else
+ else if (!error)
file->position(sort_form->record[0]);
}
if (error && error != HA_ERR_RECORD_DELETED)
diff --git a/sql/item.cc b/sql/item.cc
index 7aaa678ddb0..010189c321c 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1973,14 +1973,7 @@ void Item::make_field(Send_field *tmp_field)
void Item_empty_string::make_field(Send_field *tmp_field)
{
- enum_field_types type = FIELD_TYPE_VAR_STRING;
- if (max_length >= 16777216)
- type = FIELD_TYPE_LONG_BLOB;
- else if (max_length >= 65536)
- type = FIELD_TYPE_MEDIUM_BLOB;
- else if (max_length >= 256)
- type = FIELD_TYPE_BLOB;
- init_make_field(tmp_field, type);
+ init_make_field(tmp_field,FIELD_TYPE_VAR_STRING);
}
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 936dac393b9..74eed7fa41a 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -51,7 +51,8 @@ static void agg_cmp_type(Item_result *type, Item **items, uint nitems)
type[0]= item_cmp_type(type[0], items[i]->result_type());
}
-static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname)
+static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
+ const char *fname)
{
my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
c1.collation->name,c1.derivation_name(),
@@ -850,8 +851,8 @@ longlong Item_func_interval::val_int()
1 got error
*/
-bool
-Item_func_between::fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
+bool Item_func_between::fix_fields(THD *thd, struct st_table_list *tables,
+ Item **ref)
{
if (Item_func_opt_neg::fix_fields(thd, tables, ref))
return 1;
@@ -861,8 +862,9 @@ Item_func_between::fix_fields(THD *thd, struct st_table_list *tables, Item **ref
return 0;
/* not_null_tables_cache == union(T1(e), intersection(T1(e1),T1(e2))) */
- not_null_tables_cache= args[0]->not_null_tables() |
- (args[1]->not_null_tables() & args[2]->not_null_tables());
+ not_null_tables_cache= (args[0]->not_null_tables() |
+ (args[1]->not_null_tables() &
+ args[2]->not_null_tables()));
return 0;
}
@@ -983,6 +985,8 @@ void Item_func_between::print(String *str)
{
str->append('(');
args[0]->print(str);
+ if (negated)
+ str->append(" not", 4);
str->append(" between ", 9);
args[1]->print(str);
str->append(" and ", 5);
@@ -1104,8 +1108,8 @@ Item_func_if::fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
if (Item_func::fix_fields(thd, tlist, ref))
return 1;
- not_null_tables_cache= (args[1]->not_null_tables()
- & args[2]->not_null_tables());
+ not_null_tables_cache= (args[1]->not_null_tables() &
+ args[2]->not_null_tables());
return 0;
}
@@ -1969,6 +1973,8 @@ void Item_func_in::print(String *str)
{
str->append('(');
args[0]->print(str);
+ if (negated)
+ str->append(" not", 4);
str->append(" in (", 5);
print_args(str, 1);
str->append("))", 2);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 03ab9c5b34d..741ae90108a 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -826,7 +826,7 @@ public:
else
{
args[0]->update_used_tables();
- if (!(used_tables_cache=args[0]->used_tables()))
+ if ((const_item_cache= !(used_tables_cache= args[0]->used_tables())))
{
/* Remember if the value is always NULL or never NULL */
cached_value= (longlong) args[0]->is_null();
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 9d84d0b2427..93fa7ac938c 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -759,7 +759,7 @@ my_real_read(NET *net, ulong *complen)
net->error= 2; /* Close socket */
net->report_error= 1;
#ifdef MYSQL_SERVER
- net->last_errno= (interrupted ? ER_NET_READ_INTERRUPTED :
+ net->last_errno= (vio_was_interrupted(net->vio) ? ER_NET_READ_INTERRUPTED :
ER_NET_READ_ERROR);
#endif
goto end;
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index fb5d0eb0a3f..d2237c24139 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -788,19 +788,22 @@ void field_real::get_opt_type(String *answer,
if (!max_notzero_dec_len)
{
+ int len= (int) max_length - ((item->decimals == NOT_FIXED_DEC) ?
+ 0 : (item->decimals + 1));
+
if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127))
- sprintf(buff, "TINYINT(%d)", (int) max_length - (item->decimals + 1));
+ sprintf(buff, "TINYINT(%d)", len);
else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ?
UINT_MAX16 : INT_MAX16))
- sprintf(buff, "SMALLINT(%d)", (int) max_length - (item->decimals + 1));
+ sprintf(buff, "SMALLINT(%d)", len);
else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ?
UINT_MAX24 : INT_MAX24))
- sprintf(buff, "MEDIUMINT(%d)", (int) max_length - (item->decimals + 1));
+ sprintf(buff, "MEDIUMINT(%d)", len);
else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ?
UINT_MAX32 : INT_MAX32))
- sprintf(buff, "INT(%d)", (int) max_length - (item->decimals + 1));
+ sprintf(buff, "INT(%d)", len);
else
- sprintf(buff, "BIGINT(%d)", (int) max_length - (item->decimals + 1));
+ sprintf(buff, "BIGINT(%d)", len);
answer->append(buff, (uint) strlen(buff));
if (min_arg >= 0)
answer->append(" UNSIGNED");
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index e845769d7ad..11b45b848c8 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -353,12 +353,12 @@ void THD::cleanup(void)
mysql_ha_flush(this, (TABLE_LIST*) 0,
MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
hash_free(&handler_tables_hash);
+ delete_dynamic(&user_var_events);
+ hash_free(&user_vars);
close_temporary_tables(this);
my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR));
- delete_dynamic(&user_var_events);
- hash_free(&user_vars);
if (global_read_lock)
unlock_global_read_lock(this);
if (ull)
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 7635774e3ac..7c834c91183 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -427,7 +427,11 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
error= -1;
goto exit;
}
- result= 0;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
+ error= 0;
+ send_ok(thd);
+ goto exit;
}
else
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 89f166aca8e..a2df59e56c7 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3327,7 +3327,6 @@ purposes internal to the MySQL server", MYF(0));
!db_ok_with_wild_table(lex->name)))
{
my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
- reset_one_shot_variables(thd);
break;
}
#endif
@@ -3363,7 +3362,6 @@ purposes internal to the MySQL server", MYF(0));
!db_ok_with_wild_table(lex->name)))
{
my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
- reset_one_shot_variables(thd);
break;
}
#endif
@@ -3404,7 +3402,6 @@ purposes internal to the MySQL server", MYF(0));
!db_ok_with_wild_table(db)))
{
my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
- reset_one_shot_variables(thd);
break;
}
#endif
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e7af2a1aa75..f702e531a4d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9277,6 +9277,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
The function replaces occurrences of group by fields in expr
by ref objects for these fields unless they are under aggregate
functions.
+ The function also corrects value of the the maybe_null attribute
+ for the items of all subexpressions containing group by fields.
IMPLEMENTATION
The function recursively traverses the tree of the expr expression,
@@ -9287,6 +9289,9 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
This substitution is needed GROUP BY queries with ROLLUP if
SELECT list contains expressions over group by attributes.
+ TODO: Some functions are not null-preserving. For those functions
+ updating of the maybe_null attribute is an overkill.
+
EXAMPLES
SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP
SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP
@@ -9302,6 +9307,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
if (expr->arg_count)
{
Item **arg,**arg_end;
+ bool arg_changed= FALSE;
for (arg= expr->arguments(),
arg_end= expr->arguments()+expr->arg_count;
arg != arg_end; arg++)
@@ -9318,16 +9324,21 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
if(!(new_item= new Item_ref(group_tmp->item, 0, item->name)))
return 1; // fatal_error is set
thd->change_item_tree(arg, new_item);
- *changed= TRUE;
+ arg_changed= TRUE;
}
}
}
else if (item->type() == Item::FUNC_ITEM)
{
- if (change_group_ref(thd, (Item_func *) item, group_list, changed))
+ if (change_group_ref(thd, (Item_func *) item, group_list, &arg_changed))
return 1;
}
}
+ if (arg_changed)
+ {
+ expr->maybe_null= 1;
+ *changed= TRUE;
+ }
}
return 0;
}
@@ -9389,7 +9400,7 @@ bool JOIN::rollup_init()
}
if (item->type() == Item::FUNC_ITEM)
{
- bool changed= 0;
+ bool changed= FALSE;
if (change_group_ref(thd, (Item_func *) item, group_list, &changed))
return 1;
/*
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 647dfe2ac4d..7cefd89c23c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -638,33 +638,6 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
DBUG_RETURN(0);
}
-/*
- returns the length of the longest type on the given table.
-
- This is used so that show fields will return the data using the proper
- lengths instead of forcing columns such as type to always return with a
- given length.
-*/
-
-uint get_longest_type_in_table(TABLE *table, const char *wild)
-{
- Field **ptr,*field;
- char tmp[MAX_FIELD_WIDTH];
- uint max_len= 0;
-
- for (ptr=table->field; (field= *ptr); ptr++)
- {
- if (!wild || !wild[0] ||
- !wild_case_compare(system_charset_info, field->field_name,wild))
- {
- String type(tmp,sizeof(tmp), system_charset_info);
- field->sql_type(type);
- max_len= max(max_len, type.length());
- }
- }
- return max_len;
-}
-
/***************************************************************************
** List all columns in a table_list->real_name
@@ -694,14 +667,9 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
(void) get_table_grant(thd, table_list);
#endif
-
- /* we scan for the longest since long enum types can exceed 40 */
- uint max_len = get_longest_type_in_table(table, wild);
-
List<Item> field_list;
field_list.push_back(new Item_empty_string("Field",NAME_LEN));
- field_list.push_back(new Item_empty_string("Type",
- max_len > 40 ? max_len : 40));
+ field_list.push_back(new Item_empty_string("Type", 40));
if (verbose)
field_list.push_back(new Item_empty_string("Collation",40));
field_list.push_back(new Item_empty_string("Null",1));
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 92db0143980..01126043764 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1360,6 +1360,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{
create_info->table_existed= 1; // Mark that table existed
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
+ alias);
DBUG_RETURN(0);
}
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
@@ -1373,12 +1376,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (!access(path,F_OK))
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
- {
- create_info->table_existed= 1; // Mark that table existed
- error= 0;
- }
- else
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ goto warn;
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
goto end;
}
}
@@ -1401,12 +1400,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_PRINT("info", ("Table with same name already existed in handler"));
if (create_if_not_exists)
- {
- create_info->table_existed= 1; // Mark that table existed
- error= 0;
- }
- else
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ goto warn;
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
goto end;
}
}
@@ -1447,6 +1442,15 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
}
error=0;
+ goto end;
+
+warn:
+ error= 0;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
+ alias);
+ create_info->table_existed= 1; // Mark that table existed
+
end:
VOID(pthread_mutex_unlock(&LOCK_open));
start_waiting_global_read_lock(thd);
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index ffcf5b6f34d..eadbd37f8f6 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -7182,7 +7182,7 @@ static void test_explain_bug()
verify_prepare_field(result, 3, "type", "", MYSQL_TYPE_VAR_STRING,
"", "", "", 10, 0);
- verify_prepare_field(result, 4, "possible_keys", "", MYSQL_TYPE_BLOB,
+ verify_prepare_field(result, 4, "possible_keys", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN*64, 0);
verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING,
@@ -7195,13 +7195,13 @@ static void test_explain_bug()
(mysql_get_server_version(mysql) <= 50000 ? 3 : 4096),
0);
- verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_BLOB,
+ verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN*16, 0);
verify_prepare_field(result, 8, "rows", "", MYSQL_TYPE_LONGLONG,
"", "", "", 10, 0);
- verify_prepare_field(result, 9, "Extra", "", MYSQL_TYPE_BLOB,
+ verify_prepare_field(result, 9, "Extra", "", MYSQL_TYPE_VAR_STRING,
"", "", "", 255, 0);
mysql_free_result(result);
diff --git a/vio/vio.c b/vio/vio.c
index 4660efe3048..45572b93ed6 100644
--- a/vio/vio.c
+++ b/vio/vio.c
@@ -50,6 +50,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
vio->fastsend =vio_fastsend;
vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
vio->vioclose =vio_close_pipe;
vio->peer_addr =vio_peer_addr;
vio->in_addr =vio_in_addr;
@@ -69,6 +70,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
vio->fastsend =vio_fastsend;
vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
vio->vioclose =vio_close_shared_memory;
vio->peer_addr =vio_peer_addr;
vio->in_addr =vio_in_addr;
@@ -88,6 +90,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
vio->fastsend =vio_ssl_fastsend;
vio->viokeepalive =vio_ssl_keepalive;
vio->should_retry =vio_ssl_should_retry;
+ vio->was_interrupted=vio_ssl_was_interrupted;
vio->vioclose =vio_ssl_close;
vio->peer_addr =vio_ssl_peer_addr;
vio->in_addr =vio_ssl_in_addr;
@@ -105,6 +108,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
vio->fastsend =vio_fastsend;
vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
vio->vioclose =vio_close;
vio->peer_addr =vio_peer_addr;
vio->in_addr =vio_in_addr;
diff --git a/vio/vio_priv.h b/vio/vio_priv.h
index 3a75a08021d..c1c78cc6efa 100644
--- a/vio/vio_priv.h
+++ b/vio/vio_priv.h
@@ -39,6 +39,8 @@ int vio_ssl_fastsend(Vio *vio);
int vio_ssl_keepalive(Vio *vio, my_bool onoff);
/* Whenever we should retry the last read/write operation. */
my_bool vio_ssl_should_retry(Vio *vio);
+/* Check that operation was timed out */
+my_bool vio_ssl_was_interrupted(Vio *vio);
/* When the workday is over... */
int vio_ssl_close(Vio *vio);
/* Return last error number */
diff --git a/vio/viosocket.c b/vio/viosocket.c
index c7561890ead..0f1abfeea46 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -196,6 +196,15 @@ vio_should_retry(Vio * vio __attribute__((unused)))
}
+my_bool
+vio_was_interrupted(Vio *vio __attribute__((unused)))
+{
+ int en= socket_errno;
+ return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
+ en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
+}
+
+
int vio_close(Vio * vio)
{
int r=0;
diff --git a/vio/viossl.c b/vio/viossl.c
index 2f608209a53..a3a2e7190bd 100644
--- a/vio/viossl.c
+++ b/vio/viossl.c
@@ -184,6 +184,15 @@ vio_ssl_should_retry(Vio * vio __attribute__((unused)))
}
+my_bool
+vio_ssl_was_interrupted(Vio *vio __attribute__((unused)))
+{
+ int en= socket_errno;
+ return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
+ en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
+}
+
+
int vio_ssl_close(Vio * vio)
{
int r;