List:Commits« Previous MessageNext Message »
From:Tomas Ulin Date:August 7 2008 12:53pm
Subject:bzr commit into mysql-5.1-telco-6.2-merge branch (tomas.ulin:2663)
View as plain text  
#At file:///home/tomas/mysql_src/mysql-5.1-telco-6.2-merge2/

 2663 Tomas Ulin	2008-08-07 [merge]
      merge
added:
  mysql-test/suite/ndb_binlog/r/ndb_binlog_restore.result
  mysql-test/suite/ndb_binlog/t/ndb_binlog_restore.test
renamed:
  storage/ndb/src/common/util/ndb_show_compat.cc => storage/ndb/src/common/util/ndb_show_compat.cpp
modified:
  configure.in
  mysql-test/suite/binlog/r/binlog_multi_engine.result
  mysql-test/suite/ndb/r/ndb_multi_row.result
  mysql-test/suite/ndb/r/ndb_restore.result
  mysql-test/suite/ndb/r/ndb_trigger.result
  mysql-test/suite/ndb/t/ndb_restore.test
  mysql-test/suite/ndb/t/ndb_trigger.test
  mysql-test/suite/ndb_binlog/r/ndb_binlog_ddl_multi.result
  mysql-test/suite/ndb_binlog/r/ndb_binlog_format.result
  mysql-test/suite/ndb_binlog/r/ndb_binlog_log_bin.result
  sql/ha_ndbcluster.cc
  sql/ha_ndbcluster_binlog.cc
  sql/rpl_injector.cc
  sql/rpl_injector.h
  storage/ndb/include/kernel/signaldata/SumaImpl.hpp
  storage/ndb/include/mgmapi/mgmapi.h
  storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp
  storage/ndb/include/ndbapi/NdbOperation.hpp
  storage/ndb/include/ndbapi/NdbTransaction.hpp
  storage/ndb/src/common/logger/Logger.cpp
  storage/ndb/src/common/portlib/NdbCondition.c
  storage/ndb/src/common/portlib/NdbTick.c
  storage/ndb/src/common/transporter/TransporterRegistry.cpp
  storage/ndb/src/common/util/Makefile.am
  storage/ndb/src/common/util/ndb_init.cpp
  storage/ndb/src/kernel/blocks/backup/Backup.cpp
  storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
  storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
  storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
  storage/ndb/src/kernel/blocks/suma/Suma.cpp
  storage/ndb/src/kernel/blocks/suma/Suma.hpp
  storage/ndb/src/kernel/blocks/suma/SumaInit.cpp
  storage/ndb/src/mgmsrv/MgmtSrvr.cpp
  storage/ndb/src/ndbapi/Ndb.cpp
  storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
  storage/ndb/src/ndbapi/NdbOperationExec.cpp
  storage/ndb/src/ndbapi/NdbScanFilter.cpp
  storage/ndb/src/ndbapi/NdbScanOperation.cpp
  storage/ndb/src/ndbapi/NdbTransaction.cpp
  storage/ndb/test/ndbapi/testInterpreter.cpp
  storage/ndb/test/ndbapi/testNdbApi.cpp
  storage/ndb/test/ndbapi/testOIBasic.cpp
  storage/ndb/test/ndbapi/testScanFilter.cpp
  storage/ndb/test/ndbapi/testSystemRestart.cpp
  storage/ndb/test/ndbapi/test_event.cpp
  storage/ndb/test/run-test/autotest-boot.sh
  storage/ndb/test/run-test/daily-basic-tests.txt
  storage/ndb/tools/restore/Restore.cpp
  storage/ndb/tools/restore/consumer_restore.cpp
  storage/ndb/tools/restore/restore_main.cpp
  storage/ndb/tools/waiter.cpp

=== modified file 'configure.in'
--- a/configure.in	2008-05-23 07:55:34 +0000
+++ b/configure.in	2008-08-07 12:53:02 +0000
@@ -2063,6 +2063,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bs
 #
 #
 #
+AC_CHECK_LIB(rt, clock_gettime)
 case "$target" in
  *-*-aix4* | *-*-sco*)
 	# (grr) aix 4.3 has a stub for clock_gettime, (returning ENOSYS)
@@ -2073,6 +2074,7 @@ case "$target" in
  *) AC_CHECK_FUNCS(clock_gettime)
     ;;
 esac
+AC_CHECK_FUNCS(pthread_condattr_setclock)
 
 # Check that isinf() is available in math.h and can be used in both C and C++ 
 # code

=== modified file 'mysql-test/suite/binlog/r/binlog_multi_engine.result'
--- a/mysql-test/suite/binlog/r/binlog_multi_engine.result	2008-03-28 12:16:41 +0000
+++ b/mysql-test/suite/binlog/r/binlog_multi_engine.result	2008-06-19 07:18:42 +0000
@@ -27,11 +27,6 @@ master-bin.000001	#	Query	#	#	use `test`
 master-bin.000001	#	Query	#	#	use `test`; UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f
 master-bin.000001	#	Query	#	#	use `test`; UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c
 master-bin.000001	#	Query	#	#	use `test`; COMMIT
-master-bin.000001	#	Query	#	#	BEGIN
-master-bin.000001	#	Table_map	#	#	table_id: # (test.t1n)
-master-bin.000001	#	Table_map	#	#	table_id: # (mysql.ndb_apply_status)
-master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
-master-bin.000001	#	Query	#	#	COMMIT
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE t1m
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE t1b
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE t1n

=== modified file 'mysql-test/suite/ndb/r/ndb_multi_row.result'
--- a/mysql-test/suite/ndb/r/ndb_multi_row.result	2007-11-01 14:08:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_multi_row.result	2008-08-07 05:29:44 +0000
@@ -63,6 +63,6 @@ t4
 drop table t1, t2, t3, t4;
 drop table if exists t1, t3, t4;
 Warnings:
-Error	155	Table 'test.t1' doesn't exist
-Error	155	Table 'test.t3' doesn't exist
-Error	155	Table 'test.t4' doesn't exist
+Note	1051	Unknown table 't1'
+Note	1051	Unknown table 't3'
+Note	1051	Unknown table 't4'

=== modified file 'mysql-test/suite/ndb/r/ndb_restore.result'
--- a/mysql-test/suite/ndb/r/ndb_restore.result	2008-02-11 12:30:36 +0000
+++ b/mysql-test/suite/ndb/r/ndb_restore.result	2008-07-24 09:23:05 +0000
@@ -505,8 +505,29 @@ SELECT @the_backup_id:=backup_id FROM te
 @the_backup_id:=backup_id
 <the_backup_id>
 DROP TABLE test.backup_info;
+CREATE TABLE t11_c (
+c1 int primary key, c2 char(10), c3 varchar(10)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+CREATE TABLE t12_c (
+c1 int primary key, c2 char(10), c3 varchar(10)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+INSERT INTO t11_c VALUES(1, "aaaaa", "bbbbb"), (2, "ccccc", "ddddd"), (3, "eeeee","fffff");
+INSERT INTO t12_c VALUES(4, "ggggg", "hhhhh"), (5, "iiiii", "jjjjj"), (6, "kkkkk","lllll");
+CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP;
+DELETE FROM test.backup_info;
+LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ',';
+SELECT @the_backup_id:=backup_id FROM test.backup_info;
+@the_backup_id:=backup_id
+<the_backup_id>
+DROP TABLE test.backup_info;
+drop table t2_c,t11_c,t12_c;
+SELECT * FROM t11_c ORDER BY c1;
+c1	c2	c3
+1	aaaaa	bbbbb
+2	ccccc	ddddd
+3	eeeee	fffff
 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
-drop table if exists t2_c;
+drop table if exists t2_c,t11_c,t12_c;
 520093696,<the_backup_id>
 select epoch from mysql.ndb_apply_status where server_id=0;
 epoch

=== modified file 'mysql-test/suite/ndb/r/ndb_trigger.result'
--- a/mysql-test/suite/ndb/r/ndb_trigger.result	2007-07-04 20:38:53 +0000
+++ b/mysql-test/suite/ndb/r/ndb_trigger.result	2008-08-07 05:29:44 +0000
@@ -1,4 +1,7 @@
 drop table if exists t1, t2, t3, t4, t5;
+flush status;
+drop table if exists t1, t2, t3, t4, t5;
+flush status;
 create table t1 (id int primary key, a int not null, b decimal (63,30) default 0) engine=ndb;
 create table t2 (op char(1), a int not null, b decimal (63,30)) engine=ndb;
 create table t3  engine=ndb select 1 as i;
@@ -312,4 +315,29 @@ id	xy
 DROP TRIGGER t1_delete;
 DROP TRIGGER t4_delete;
 DROP TABLE t1, t2, t3, t4, t5;
+create table t1(a int, b varchar(10), c date) engine=ndb;
+CREATE TRIGGER trg1 BEFORE UPDATE ON t1 FOR EACH ROW BEGIN
+SET new.c = date(now());
+End //
+select trigger_name,event_object_table from information_schema.triggers where
+trigger_name='trg1';
+trigger_name	event_object_table
+trg1	t1
+CREATE TRIGGER trg1 BEFORE UPDATE ON t1 FOR EACH ROW BEGIN
+SET new.c = date(now());
+End //
+select trigger_name,event_object_table from information_schema.triggers where
+trigger_name='trg1';
+trigger_name	event_object_table
+trg1	t1
+rename table t1 to t2;
+select trigger_name,event_object_table from information_schema.triggers where
+trigger_name='trg1';
+trigger_name	event_object_table
+trg1	t2
+select trigger_name,event_object_table from information_schema.triggers where
+trigger_name='trg1';
+trigger_name	event_object_table
+trg1	t2
+drop table t2;
 End of 5.1 tests

=== modified file 'mysql-test/suite/ndb/t/ndb_restore.test'
--- a/mysql-test/suite/ndb/t/ndb_restore.test	2008-02-11 12:30:36 +0000
+++ b/mysql-test/suite/ndb/t/ndb_restore.test	2008-07-24 09:23:05 +0000
@@ -395,13 +395,31 @@ drop table t1_c,t3_c,t4_c,t5_c,t6_c,t7_c
 --source include/ndb_backup.inc
 --exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --core=0 -b $the_backup_id -n 1 -m -r --ndb-nodegroup_map '(0,1)' $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id 2>&1 | grep Translate || true
 
+CREATE TABLE t11_c (
+  c1 int primary key, c2 char(10), c3 varchar(10)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+
+CREATE TABLE t12_c (
+  c1 int primary key, c2 char(10), c3 varchar(10)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+
+INSERT INTO t11_c VALUES(1, "aaaaa", "bbbbb"), (2, "ccccc", "ddddd"), (3, "eeeee","fffff");
+INSERT INTO t12_c VALUES(4, "ggggg", "hhhhh"), (5, "iiiii", "jjjjj"), (6, "kkkkk","lllll");
+--source include/ndb_backup.inc
+drop table t2_c,t11_c,t12_c;
+# Only part of tables is restored, it should work
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b $the_backup_id -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id test t11_c >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b $the_backup_id -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id test t11_c >> $NDB_TOOLS_OUTPUT
+#Should only t11_c is restored
+SELECT * FROM t11_c ORDER BY c1;
+
 #
 # Cleanup
 #
 
 --disable_warnings
 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
-drop table if exists t2_c;
+drop table if exists t2_c,t11_c,t12_c;
 --enable_warnings
 
 #

=== modified file 'mysql-test/suite/ndb/t/ndb_trigger.test'
--- a/mysql-test/suite/ndb/t/ndb_trigger.test	2007-07-04 20:38:53 +0000
+++ b/mysql-test/suite/ndb/t/ndb_trigger.test	2008-08-07 05:29:44 +0000
@@ -1,5 +1,5 @@
 # Tests which involve triggers and NDB storage engine
---source include/have_ndb.inc
+--source include/have_multi_ndb.inc
 --source include/not_embedded.inc
 
 # 
@@ -14,7 +14,12 @@
 #
 
 --disable_warnings
+connection server2;
 drop table if exists t1, t2, t3, t4, t5;
+flush status;
+connection server1;
+drop table if exists t1, t2, t3, t4, t5;
+flush status;
 --enable_warnings
 
 create table t1 (id int primary key, a int not null, b decimal (63,30) default 0) engine=ndb;
@@ -217,5 +222,40 @@ SELECT * FROM t2 order by id;
 DROP TRIGGER t1_delete;
 DROP TRIGGER t4_delete;
 DROP TABLE t1, t2, t3, t4, t5;
+
+# Test for bug#36658
+# Verify that rename table
+# doesn't remove triggers
+
+connection server1;
+create table t1(a int, b varchar(10), c date) engine=ndb;
+delimiter //;
+CREATE TRIGGER trg1 BEFORE UPDATE ON t1 FOR EACH ROW BEGIN
+   SET new.c = date(now());
+End //
+delimiter ;//
+select trigger_name,event_object_table from information_schema.triggers where
+trigger_name='trg1';
+
+connection server2;
+delimiter //;
+CREATE TRIGGER trg1 BEFORE UPDATE ON t1 FOR EACH ROW BEGIN
+   SET new.c = date(now());
+End //
+delimiter ;//
+select trigger_name,event_object_table from information_schema.triggers where
+trigger_name='trg1';
+
+connection server1;
+rename table t1 to t2;
+select trigger_name,event_object_table from information_schema.triggers where
+trigger_name='trg1';
+
+connection server2;
+select trigger_name,event_object_table from information_schema.triggers where
+trigger_name='trg1';
+
+connection server1;
+drop table t2;
 
 --echo End of 5.1 tests

=== modified file 'mysql-test/suite/ndb_binlog/r/ndb_binlog_ddl_multi.result'
--- a/mysql-test/suite/ndb_binlog/r/ndb_binlog_ddl_multi.result	2008-02-25 13:50:20 +0000
+++ b/mysql-test/suite/ndb_binlog/r/ndb_binlog_ddl_multi.result	2008-08-07 05:29:44 +0000
@@ -33,11 +33,11 @@ drop table mysqltest.t1;
 show binlog events from <binlog_start>;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
 master-bin.000001	#	Query	102	#	ALTER DATABASE mysqltest CHARACTER SET latin1
-master-bin.000001	#	Query	102	#	use `mysqltest`; drop table `t1`
+master-bin.000001	#	Query	102	#	use `mysqltest`; drop table `mysqltest`.`t1`
 show binlog events from <binlog_start>;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
 master-bin.000001	#	Query	102	#	ALTER DATABASE mysqltest CHARACTER SET latin1
-master-bin.000001	#	Query	102	#	use `mysqltest`; drop table `t1`
+master-bin.000001	#	Query	102	#	use `mysqltest`; drop table `mysqltest`.`t1`
 reset master;
 reset master;
 use test;
@@ -161,10 +161,10 @@ Log_name	Pos	Event_type	Server_id	End_lo
 master-bin1.000001	#	Query	1	#	use `test`; create table t1 (a int key) engine=ndb
 master-bin1.000001	#	Query	1	#	use `test`; create table t2 (a int key) engine=ndb
 master-bin1.000001	#	Query	1	#	use `test`; create table t3 (a int key) engine=ndb
-master-bin1.000001	#	Query	1	#	use `test`; rename table `test.t3` to `test.t4`
-master-bin1.000001	#	Query	1	#	use `test`; rename table `test.t2` to `test.t3`
-master-bin1.000001	#	Query	1	#	use `test`; rename table `test.t1` to `test.t2`
-master-bin1.000001	#	Query	1	#	use `test`; rename table `test.t4` to `test.t1`
+master-bin1.000001	#	Query	1	#	use `test`; rename table `test`.`t3` to `test`.`t4`
+master-bin1.000001	#	Query	1	#	use `test`; rename table `test`.`t2` to `test`.`t3`
+master-bin1.000001	#	Query	1	#	use `test`; rename table `test`.`t1` to `test`.`t2`
+master-bin1.000001	#	Query	1	#	use `test`; rename table `test`.`t4` to `test`.`t1`
 drop table t1;
 drop table t2;
 drop table t3;
@@ -188,7 +188,7 @@ master-bin1.000001	#	Table_map	102	#	tab
 master-bin1.000001	#	Write_rows	102	#	table_id: #
 master-bin1.000001	#	Write_rows	102	#	table_id: # flags: STMT_END_F
 master-bin1.000001	#	Query	102	#	COMMIT
-master-bin1.000001	#	Query	1	#	use `test`; rename table `test.t1` to `test.t2`
+master-bin1.000001	#	Query	1	#	use `test`; rename table `test`.`t1` to `test`.`t2`
 master-bin1.000001	#	Query	102	#	BEGIN
 master-bin1.000001	#	Table_map	102	#	table_id: # (test.t2)
 master-bin1.000001	#	Table_map	102	#	table_id: # (mysql.ndb_apply_status)

=== modified file 'mysql-test/suite/ndb_binlog/r/ndb_binlog_format.result'
--- a/mysql-test/suite/ndb_binlog/r/ndb_binlog_format.result	2008-03-25 18:03:33 +0000
+++ b/mysql-test/suite/ndb_binlog/r/ndb_binlog_format.result	2008-06-19 07:18:42 +0000
@@ -24,9 +24,4 @@ master-bin.000001	#	Query	#	#	use `test`
 master-bin.000001	#	Query	#	#	use `test`; UPDATE t1, t3 SET m = 2, e = 3 WHERE n = f
 master-bin.000001	#	Query	#	#	use `test`; UPDATE t3, t2 SET e = 2, b = 3 WHERE f = c
 master-bin.000001	#	Query	#	#	use `test`; COMMIT
-master-bin.000001	#	Query	#	#	BEGIN
-master-bin.000001	#	Table_map	#	#	table_id: # (test.t3)
-master-bin.000001	#	Table_map	#	#	table_id: # (mysql.ndb_apply_status)
-master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
-master-bin.000001	#	Query	#	#	COMMIT
 DROP TABLE t1, t2, t3;

=== modified file 'mysql-test/suite/ndb_binlog/r/ndb_binlog_log_bin.result'
--- a/mysql-test/suite/ndb_binlog/r/ndb_binlog_log_bin.result	2008-02-25 13:50:20 +0000
+++ b/mysql-test/suite/ndb_binlog/r/ndb_binlog_log_bin.result	2008-08-07 05:29:44 +0000
@@ -13,22 +13,12 @@ Warnings:
 Warning	1478	Converted FIXED field to DYNAMIC to enable on-line ADD COLUMN
 show binlog events from <binlog_start>;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	#	Query	1	#	BEGIN
-master-bin.000001	#	Table_map	1	#	table_id: # (mysqltest.t1)
-master-bin.000001	#	Table_map	1	#	table_id: # (mysql.ndb_apply_status)
-master-bin.000001	#	Write_rows	1	#	table_id: # flags: STMT_END_F
-master-bin.000001	#	Query	1	#	COMMIT
 reset master;
 use mysqltest;
 insert into t2 values (1,1);
 show binlog events from <binlog_start>;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
 master-bin1.000001	#	Query	102	#	BEGIN
-master-bin1.000001	#	Table_map	102	#	table_id: # (mysqltest.t1)
-master-bin1.000001	#	Table_map	102	#	table_id: # (mysql.ndb_apply_status)
-master-bin1.000001	#	Write_rows	102	#	table_id: # flags: STMT_END_F
-master-bin1.000001	#	Query	102	#	COMMIT
-master-bin1.000001	#	Query	102	#	BEGIN
 master-bin1.000001	#	Table_map	102	#	table_id: # (mysqltest.t2)
 master-bin1.000001	#	Table_map	102	#	table_id: # (mysql.ndb_apply_status)
 master-bin1.000001	#	Write_rows	102	#	table_id: #
@@ -63,8 +53,8 @@ use mysqltest;
 insert into t2 values (1,1);
 show binlog events from <binlog_start>;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin1.000001	#	Query	1	#	use `mysqltest`; drop table `t1`
-master-bin1.000001	#	Query	1	#	use `mysqltest`; drop table `t2`
+master-bin1.000001	#	Query	1	#	use `mysqltest`; drop table `mysqltest`.`t1`
+master-bin1.000001	#	Query	1	#	use `mysqltest`; drop table `mysqltest`.`t2`
 master-bin1.000001	#	Query	1	#	use `mysqltest`; create table t1 (d int key, e int) engine=ndb
 master-bin1.000001	#	Query	1	#	use `mysqltest`; create table t2 (d int key, e int) engine=ndb
 master-bin1.000001	#	Query	102	#	BEGIN

=== added file 'mysql-test/suite/ndb_binlog/r/ndb_binlog_restore.result'
--- a/mysql-test/suite/ndb_binlog/r/ndb_binlog_restore.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb_binlog/r/ndb_binlog_restore.result	2008-06-18 15:03:43 +0000
@@ -0,0 +1,101 @@
+drop table if exists t1;
+#
+# create a table with some data with and without binlogging
+#
+create table t1 (a int key, b int) engine ndb;
+insert into t1 values (1,1);
+@the_backup_id:=backup_id
+<the_backup_id>
+#
+# extra table to be used to ensure data has arrived to binlog
+create table t2 (a int key, b int) engine ndb;
+#
+# reset and restore schema
+drop table t1;
+reset master;
+show tables;
+Tables_in_test
+t2
+t1
+#
+# restore and _no_ binlog
+#
+# check the binlog, should be empty
+# extra insert (not logged) to ensure data has arrived to binlog
+set SQL_LOG_BIN=0;
+insert into t2 values (1,1);
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+#
+# reset and restore schema again
+drop table t1;
+reset master;
+show tables;
+Tables_in_test
+t2
+t1
+#
+# restore and  binlog should now happen
+#
+# check the binlog, should contain data
+# extra insert (not logged) to ensure data has arrived to binlog
+set SQL_LOG_BIN=0;
+insert into t2 values (2,2);
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	1	#	BEGIN
+master-bin.000001	#	Table_map	1	#	table_id: # (test.t1)
+master-bin.000001	#	Table_map	1	#	table_id: # (mysql.ndb_apply_status)
+master-bin.000001	#	Write_rows	1	#	table_id: #
+master-bin.000001	#	Write_rows	1	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	1	#	COMMIT
+drop table t1, t2;
+#
+# Now more complex using "BANK schema" including restore of log
+#
+CREATE DATABASE IF NOT EXISTS BANK;
+DROP DATABASE BANK;
+CREATE DATABASE BANK default charset=latin1 default collate=latin1_bin;
+USE BANK;
+CREATE TABLE GL ( TIME BIGINT UNSIGNED NOT NULL,
+ACCOUNT_TYPE INT UNSIGNED NOT NULL,
+BALANCE INT UNSIGNED NOT NULL,
+DEPOSIT_COUNT INT UNSIGNED NOT NULL,
+DEPOSIT_SUM INT UNSIGNED NOT NULL,
+WITHDRAWAL_COUNT INT UNSIGNED NOT NULL,
+WITHDRAWAL_SUM INT UNSIGNED NOT NULL,
+PURGED INT UNSIGNED NOT NULL,
+PRIMARY KEY USING HASH (TIME,ACCOUNT_TYPE))
+ENGINE = NDB;
+CREATE TABLE ACCOUNT ( ACCOUNT_ID INT UNSIGNED NOT NULL,
+OWNER INT UNSIGNED NOT NULL,
+BALANCE INT UNSIGNED NOT NULL,
+ACCOUNT_TYPE INT UNSIGNED NOT NULL,
+PRIMARY KEY USING HASH (ACCOUNT_ID))
+ENGINE = NDB;
+CREATE TABLE TRANSACTION ( TRANSACTION_ID BIGINT UNSIGNED NOT NULL,
+ACCOUNT INT UNSIGNED NOT NULL,
+ACCOUNT_TYPE INT UNSIGNED NOT NULL,
+OTHER_ACCOUNT INT UNSIGNED NOT NULL,
+TRANSACTION_TYPE INT UNSIGNED NOT NULL,
+TIME BIGINT UNSIGNED NOT NULL,
+AMOUNT INT UNSIGNED NOT NULL,
+PRIMARY KEY USING HASH (TRANSACTION_ID,ACCOUNT))
+ENGINE = NDB;
+CREATE TABLE SYSTEM_VALUES ( SYSTEM_VALUES_ID INT UNSIGNED NOT NULL,
+VALUE BIGINT UNSIGNED NOT NULL,
+PRIMARY KEY USING HASH (SYSTEM_VALUES_ID))
+ENGINE = NDB;
+CREATE TABLE ACCOUNT_TYPE ( ACCOUNT_TYPE_ID INT UNSIGNED NOT NULL,
+DESCRIPTION CHAR(64) NOT NULL,
+PRIMARY KEY USING HASH (ACCOUNT_TYPE_ID))
+ENGINE = NDB;
+#
+# reset, restore and  binlog should _not_ happen
+reset master;
+select count(*) from TRANSACTION;
+count(*)
+3444
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+DROP DATABASE BANK;

=== added file 'mysql-test/suite/ndb_binlog/t/ndb_binlog_restore.test'
--- a/mysql-test/suite/ndb_binlog/t/ndb_binlog_restore.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb_binlog/t/ndb_binlog_restore.test	2008-06-18 15:03:43 +0000
@@ -0,0 +1,126 @@
+-- source include/have_ndb.inc
+-- source include/have_binlog_format_mixed_or_row.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+--echo #
+--echo # create a table with some data with and without binlogging
+--echo #
+create table t1 (a int key, b int) engine ndb;
+insert into t1 values (1,1);
+
+# backup and drop data
+--disable_query_log
+--source include/ndb_backup.inc
+--enable_query_log
+
+--echo #
+--echo # extra table to be used to ensure data has arrived to binlog
+create table t2 (a int key, b int) engine ndb;
+
+--echo #
+--echo # reset and restore schema
+drop table t1;
+reset master;
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b $the_backup_id -n 1 -m --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
+show tables;
+
+--echo #
+--echo # restore and _no_ binlog
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --no-binlog -b $the_backup_id -n 1 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --no-binlog -b $the_backup_id -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
+
+--echo #
+--echo # check the binlog, should be empty
+--echo # extra insert (not logged) to ensure data has arrived to binlog
+set SQL_LOG_BIN=0;
+insert into t2 values (1,1);
+--source include/show_binlog_events2.inc
+
+--echo #
+--echo # reset and restore schema again
+drop table t1;
+reset master;
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b $the_backup_id -n 1 -m --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
+show tables;
+
+--echo #
+--echo # restore and  binlog should now happen
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b $the_backup_id -n 1 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b $the_backup_id -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
+
+--echo #
+--echo # check the binlog, should contain data
+--echo # extra insert (not logged) to ensure data has arrived to binlog
+set SQL_LOG_BIN=0;
+insert into t2 values (2,2);
+--source include/show_binlog_events2.inc
+
+drop table t1, t2;
+
+
+
+--echo #
+--echo # Now more complex using "BANK schema" including restore of log
+--echo #
+--disable_warnings
+CREATE DATABASE IF NOT EXISTS BANK;
+DROP DATABASE BANK;
+--enable_warnings
+CREATE DATABASE BANK default charset=latin1 default collate=latin1_bin;
+
+#
+# These tables should correspond to the table definitions in
+# storage/ndb/test/src/NDBT_Tables.cpp
+#
+USE BANK;
+CREATE TABLE GL ( TIME BIGINT UNSIGNED NOT NULL,
+                  ACCOUNT_TYPE INT UNSIGNED NOT NULL,
+                  BALANCE INT UNSIGNED NOT NULL,
+                  DEPOSIT_COUNT INT UNSIGNED NOT NULL,
+                  DEPOSIT_SUM INT UNSIGNED NOT NULL,
+                  WITHDRAWAL_COUNT INT UNSIGNED NOT NULL,
+                  WITHDRAWAL_SUM INT UNSIGNED NOT NULL,
+                  PURGED INT UNSIGNED NOT NULL,
+                  PRIMARY KEY USING HASH (TIME,ACCOUNT_TYPE))
+   ENGINE = NDB;
+
+CREATE TABLE ACCOUNT ( ACCOUNT_ID INT UNSIGNED NOT NULL,
+                       OWNER INT UNSIGNED NOT NULL,
+                       BALANCE INT UNSIGNED NOT NULL,
+                       ACCOUNT_TYPE INT UNSIGNED NOT NULL,
+                       PRIMARY KEY USING HASH (ACCOUNT_ID))
+   ENGINE = NDB;
+
+CREATE TABLE TRANSACTION ( TRANSACTION_ID BIGINT UNSIGNED NOT NULL,
+                           ACCOUNT INT UNSIGNED NOT NULL,
+                           ACCOUNT_TYPE INT UNSIGNED NOT NULL,
+                           OTHER_ACCOUNT INT UNSIGNED NOT NULL,
+                           TRANSACTION_TYPE INT UNSIGNED NOT NULL,
+                           TIME BIGINT UNSIGNED NOT NULL,
+                           AMOUNT INT UNSIGNED NOT NULL,
+                           PRIMARY KEY USING HASH (TRANSACTION_ID,ACCOUNT))
+   ENGINE = NDB;
+
+CREATE TABLE SYSTEM_VALUES ( SYSTEM_VALUES_ID INT UNSIGNED NOT NULL,
+                             VALUE BIGINT UNSIGNED NOT NULL,
+                             PRIMARY KEY USING HASH (SYSTEM_VALUES_ID))
+   ENGINE = NDB;
+
+CREATE TABLE ACCOUNT_TYPE ( ACCOUNT_TYPE_ID INT UNSIGNED NOT NULL,
+                            DESCRIPTION CHAR(64) NOT NULL,
+                            PRIMARY KEY USING HASH (ACCOUNT_TYPE_ID))
+   ENGINE = NDB;
+
+--echo #
+--echo # reset, restore and  binlog should _not_ happen
+reset master;
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --no-binlog -b 1 -n 1 -p 1 -r $MYSQL_TEST_DIR/std_data/ndb_backup51 >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --no-binlog -b 1 -n 2 -p 1 -r $MYSQL_TEST_DIR/std_data/ndb_backup51 >> $NDB_TOOLS_OUTPUT
+
+select count(*) from TRANSACTION;
+--source include/show_binlog_events2.inc
+
+DROP DATABASE BANK;

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2008-05-30 11:12:38 +0000
+++ b/sql/ha_ndbcluster.cc	2008-08-07 05:29:44 +0000
@@ -152,6 +152,7 @@ static int ndb_get_table_statistics(ha_n
 static int ndb_get_table_statistics(ha_ndbcluster*, bool, Ndb*,
                                     const NdbRecord *, struct Ndb_statistics *);
 
+THD *injector_thd= 0;
 
 // Util thread variables
 pthread_t ndb_util_thread;
@@ -5953,6 +5954,17 @@ int ha_ndbcluster::rename_table(const ch
 
   DBUG_ENTER("ha_ndbcluster::rename_table");
   DBUG_PRINT("info", ("Renaming %s to %s", from, to));
+
+  if (thd == injector_thd)
+  {
+    /*
+      Table was renamed remotely is already
+      renamed inside ndb.
+      Just rename .ndb file.
+     */
+    DBUG_RETURN(handler::rename_table(from, to));
+  }
+
   set_dbname(from, old_dbname);
   set_dbname(to, new_dbname);
   set_tabname(from);
@@ -6027,7 +6039,7 @@ int ha_ndbcluster::rename_table(const ch
 #endif
     ERR_RETURN(ndb_error);
   }
-  
+
   // Rename .ndb file
   if ((result= handler::rename_table(from, to)))
   {
@@ -6333,6 +6345,17 @@ int ha_ndbcluster::delete_table(const ch
   int error= 0;
   DBUG_ENTER("ha_ndbcluster::delete_table");
   DBUG_PRINT("enter", ("name: %s", name));
+
+  if (thd == injector_thd)
+  {
+    /*
+      Table was dropped remotely is already
+      dropped inside ndb.
+      Just drop local files.
+     */
+    DBUG_RETURN(handler::delete_table(name));
+  }
+
   set_dbname(name);
   set_tabname(name);
 

=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc	2008-05-09 09:42:18 +0000
+++ b/sql/ha_ndbcluster_binlog.cc	2008-08-07 11:26:22 +0000
@@ -72,7 +72,7 @@ my_bool ndb_binlog_is_ready= FALSE;
   Has one sole purpose, for setting the in_use table member variable
   in get_share(...)
 */
-THD *injector_thd= 0;
+extern THD * injector_thd; // Declared in ha_ndbcluster.cc
 
 /*
   Global reference to ndb injector thd object.
@@ -141,12 +141,6 @@ static void ndb_free_schema_object(NDB_S
                                    bool have_lock);
 
 /*
-  Global variables for holding the ndb_binlog_index table reference
-*/
-static TABLE *ndb_binlog_index= 0;
-static TABLE_LIST binlog_tables;
-
-/*
   Helper functions
 */
 
@@ -309,15 +303,6 @@ static void run_query(THD *thd, char *bu
   thd->transaction.all= save_thd_transaction_all;
   thd->transaction.stmt= save_thd_transaction_stmt;
   thd->net= save_thd_net;
-
-  if (thd == injector_thd)
-  {
-    /*
-      running the query will close all tables, including the ndb_binlog_index
-      used in injector_thd
-    */
-    ndb_binlog_index= 0;
-  }
 }
 
 static void
@@ -1304,8 +1289,9 @@ int ndbcluster_log_schema_op(THD *thd,
       DBUG_RETURN(0);
     /* redo the drop table query as is may contain several tables */
     query= tmp_buf2;
-    query_length= (uint) (strxmov(tmp_buf2, "drop table `",
-                                  table_name, "`", NullS) - tmp_buf2);
+    query_length= (uint) (strxmov(tmp_buf2, "drop table ",
+                                  "`", db, "`", ".",
+                                  "`", table_name, "`", NullS) - tmp_buf2);
     type_str= "drop table";
     break;
   case SOT_RENAME_TABLE_PREPARE:
@@ -1315,9 +1301,11 @@ int ndbcluster_log_schema_op(THD *thd,
   case SOT_RENAME_TABLE:
     /* redo the rename table query as is may contain several tables */
     query= tmp_buf2;
-    query_length= (uint) (strxmov(tmp_buf2, "rename table `",
-                                  db, ".", table_name, "` to `",
-                                  new_db, ".", new_table_name, "`", NullS) - tmp_buf2);
+    query_length= (uint) (strxmov(tmp_buf2, "rename table ",
+                                  "`", db, "`", ".",
+                                  "`", table_name, "` to ",
+                                  "`", new_db, "`", ".",
+                                  "`", new_table_name, "`", NullS) - tmp_buf2);
     type_str= "rename table";
     break;
   case SOT_CREATE_TABLE:
@@ -1858,17 +1846,53 @@ ndb_binlog_thread_handle_schema_event(TH
       if (schema->node_id != node_id)
       {
         int log_query= 0, post_epoch_unlock= 0;
+        char errmsg[MYSQL_ERRMSG_SIZE];
+
         switch (schema_type)
         {
-        case SOT_DROP_TABLE:
-          // fall through
         case SOT_RENAME_TABLE:
           // fall through
         case SOT_RENAME_TABLE_NEW:
-          post_epoch_log_list->push_back(schema, mem_root);
-          /* acknowledge this query _after_ epoch completion */
-          post_epoch_unlock= 1;
-          break;
+        {
+          uint end= snprintf(&errmsg[0], MYSQL_ERRMSG_SIZE,
+                             "NDB Binlog: Skipping renaming locally defined table '%s.%s' from binlog schema event '%s' from node %d. ",
+                             schema->db, schema->name, schema->query,
+                             schema->node_id);
+          
+          errmsg[end]= '\0';
+        }
+        // fall through
+        case SOT_DROP_TABLE:
+          if (schema_type == SOT_DROP_TABLE)
+          {
+            uint end= snprintf(&errmsg[0], MYSQL_ERRMSG_SIZE,
+                               "NDB Binlog: Skipping dropping locally defined table '%s.%s' from binlog schema event '%s' from node %d. ",
+                               schema->db, schema->name, schema->query,
+                               schema->node_id);
+            errmsg[end]= '\0';
+          }
+          if (! ndbcluster_check_if_local_table(schema->db, schema->name))
+          {
+            const int no_print_error[1]=
+              {ER_BAD_TABLE_ERROR}; /* ignore missing table */
+            run_query(thd, schema->query,
+                      schema->query + schema->query_length,
+                      no_print_error, //   /* don't print error */
+                      TRUE); //  /* don't binlog the query */
+
+            /* binlog dropping table after any table operations */
+            post_epoch_log_list->push_back(schema, mem_root);
+            /* acknowledge this query _after_ epoch completion */
+            post_epoch_unlock= 1;
+          }
+          else
+          {
+            /* Tables exists as a local table, leave it */
+            DBUG_PRINT("info", ((const char *) errmsg));
+            sql_print_error((const char *) errmsg);
+            log_query= 1;
+          }
+          // Fall through
 	case SOT_TRUNCATE_TABLE:
         {
           char key[FN_REFLEN];
@@ -1904,6 +1928,8 @@ ndb_binlog_thread_handle_schema_event(TH
             free_share(&share);
           }
         }
+        if (schema_type != SOT_TRUNCATE_TABLE)
+          break;
         // fall through
         case SOT_CREATE_TABLE:
           pthread_mutex_lock(&LOCK_open);
@@ -2526,8 +2552,8 @@ struct ndb_binlog_index_row {
 /*
   Open the ndb_binlog_index table
 */
-static int open_ndb_binlog_index(THD *thd, TABLE_LIST *tables,
-                                 TABLE **ndb_binlog_index)
+static int open_and_lock_ndb_binlog_index(THD *thd, TABLE_LIST *tables,
+                                          TABLE **ndb_binlog_index)
 {
   static char repdb[]= NDB_REP_DB;
   static char reptable[]= NDB_REP_TABLE;
@@ -2539,9 +2565,8 @@ static int open_ndb_binlog_index(THD *th
   tables->lock_type= TL_WRITE;
   thd->proc_info= "Opening " NDB_REP_DB "." NDB_REP_TABLE;
   tables->required_type= FRMTYPE_TABLE;
-  uint counter;
   thd->clear_error();
-  if (open_tables(thd, &tables, &counter, MYSQL_LOCK_IGNORE_FLUSH))
+  if (simple_open_n_lock_tables(thd, tables))
   {
     if (thd->killed)
       sql_print_error("NDB Binlog: Opening ndb_binlog_index: killed");
@@ -2558,32 +2583,6 @@ static int open_ndb_binlog_index(THD *th
   return 0;
 }
 
-
-/*
-  Check if ndb_binlog_index is lockable, if not close, to free for
-  other threads use
-*/
-
-static void
-ndb_check_ndb_binlog_index(THD *thd)
-{
-  if (!ndb_binlog_index)
-    return;
-
-  bool need_reopen;
-  if (lock_tables(thd, &binlog_tables, 1, &need_reopen))
-  {
-    ndb_binlog_index= 0;
-    close_thread_tables(thd);
-    ndb_binlog_index= 0;
-    return;
-  }
-
-  mysql_unlock_tables(thd, thd->lock);
-  thd->lock= 0;
-  return;
-}
-
 /*
   Insert one row in the ndb_binlog_index
 */
@@ -2592,8 +2591,10 @@ static int
 ndb_add_ndb_binlog_index(THD *thd, ndb_binlog_index_row *row)
 {
   int error= 0;
-  bool need_reopen;
   ndb_binlog_index_row *first= row;
+  TABLE *ndb_binlog_index= 0;
+  TABLE_LIST binlog_tables;
+
   /*
     Turn of binlogging to prevent the table changes to be written to
     the binary log.
@@ -2601,28 +2602,12 @@ ndb_add_ndb_binlog_index(THD *thd, ndb_b
   ulong saved_options= thd->options;
   thd->options&= ~(OPTION_BIN_LOG);
 
-  for ( ; ; ) /* loop for need_reopen */
-  {
-    if (!ndb_binlog_index && open_ndb_binlog_index(thd, &binlog_tables, &ndb_binlog_index))
-    {
-      error= -1;
-      goto add_ndb_binlog_index_err;
-    }
 
-    if (lock_tables(thd, &binlog_tables, 1, &need_reopen))
-    {
-      if (need_reopen)
-      {
-        TABLE_LIST *p_binlog_tables= &binlog_tables;
-        close_tables_for_reopen(thd, &p_binlog_tables);
-        ndb_binlog_index= 0;
-        continue;
-      }
-      sql_print_error("NDB Binlog: Unable to lock table ndb_binlog_index");
-      error= -1;
-      goto add_ndb_binlog_index_err;
-    }
-    break;
+  if (open_and_lock_ndb_binlog_index(thd, &binlog_tables, &ndb_binlog_index))
+  {
+    sql_print_error("NDB Binlog: Unable to lock table ndb_binlog_index");
+    error= -1;
+    goto add_ndb_binlog_index_err;
   }
 
   /*
@@ -2671,13 +2656,8 @@ ndb_add_ndb_binlog_index(THD *thd, ndb_b
     }
   } while (row);
 
-  mysql_unlock_tables(thd, thd->lock);
-  thd->lock= 0;
-  thd->options= saved_options;
-  return 0;
 add_ndb_binlog_index_err:
   close_thread_tables(thd);
-  ndb_binlog_index= 0;
   thd->options= saved_options;
   return error;
 }
@@ -3885,7 +3865,8 @@ ndb_find_binlog_index_row(ndb_binlog_ind
 static int
 ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
                                     ndb_binlog_index_row **rows,
-                                    injector::transaction &trans)
+                                    injector::transaction &trans,
+                                    unsigned &trans_row_count)
 {
   Ndb_event_data *event_data= (Ndb_event_data *) pOp->getCustomData();
   TABLE *table= event_data->table;
@@ -3982,6 +3963,7 @@ ndb_binlog_thread_handle_data_event(Ndb 
   {
   case NDBEVENT::TE_INSERT:
     row->n_inserts++;
+    trans_row_count++;
     DBUG_PRINT("info", ("INSERT INTO %s.%s",
                         table->s->db.str, table->s->table_name.str));
     {
@@ -4004,6 +3986,7 @@ ndb_binlog_thread_handle_data_event(Ndb 
     break;
   case NDBEVENT::TE_DELETE:
     row->n_deletes++;
+    trans_row_count++;
     DBUG_PRINT("info",("DELETE FROM %s.%s",
                        table->s->db.str, table->s->table_name.str));
     {
@@ -4044,6 +4027,7 @@ ndb_binlog_thread_handle_data_event(Ndb 
     break;
   case NDBEVENT::TE_UPDATE:
     row->n_updates++;
+    trans_row_count++;
     DBUG_PRINT("info", ("UPDATE %s.%s",
                         table->s->db.str, table->s->table_name.str));
     {
@@ -4579,15 +4563,6 @@ restart:
          !ndb_binlog_running))
       break; /* Shutting down server */
 
-    if (ndb_binlog_index && ndb_binlog_index->s->version < refresh_version)
-    {
-      if (ndb_binlog_index->s->version < refresh_version)
-      {
-        close_thread_tables(thd);
-        ndb_binlog_index= 0;
-      }
-    }
-
     MEM_ROOT **root_ptr=
       my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
     MEM_ROOT *old_root= *root_ptr;
@@ -4645,17 +4620,8 @@ restart:
       }
     }
 
-    /*
-      For each epoch atleast one check should be made to see if ndb_binlog_index
-      table is lockable.  Variable 'do_check_ndb_binlog_index' is used as a flag
-      to signal if a check is needed for current epoch.
-    */
-    int do_check_ndb_binlog_index= 1;
-
     if (res > 0)
     {
-      do_check_ndb_binlog_index= 1;
-
       DBUG_PRINT("info", ("pollEvents res: %d", res));
       thd->proc_info= "Processing events";
       NdbEventOperation *pOp= i_ndb->nextEvent();
@@ -4686,6 +4652,7 @@ restart:
         bzero((char*)&_row, sizeof(_row));
         thd->variables.character_set_client= &my_charset_latin1;
         injector::transaction trans;
+        unsigned trans_row_count= 0;
         // pass table map before epoch
         {
           Uint32 iter= 0;
@@ -4852,7 +4819,7 @@ restart:
 #endif
           if ((unsigned) pOp->getEventType() <
               (unsigned) NDBEVENT::TE_FIRST_NON_DATA_EVENT)
-            ndb_binlog_thread_handle_data_event(i_ndb, pOp, &rows, trans);
+            ndb_binlog_thread_handle_data_event(i_ndb, pOp, &rows, trans, trans_row_count);
           else
           {
             // set injector_ndb database/schema from table internal name
@@ -4895,9 +4862,20 @@ restart:
         write_timer.stop();
 #endif
 
-        if (trans.good())
+        while (trans.good())
         {
-          //DBUG_ASSERT(row.n_inserts || row.n_updates || row.n_deletes);
+          if (trans_row_count == 0)
+          {
+            /* nothing to commit, rollback instead */
+            if (int r= trans.rollback())
+            {
+              sql_print_error("NDB Binlog: "
+                              "Error during ROLLBACK of GCI %u/%u. Error: %d",
+                              uint(gci >> 32), uint(gci), r);
+              /* TODO: Further handling? */
+            }
+            break;
+          }
           thd->proc_info= "Committing events to binlog";
           injector::transaction::binlog_pos start= trans.start_pos();
           if (int r= trans.commit())
@@ -4916,18 +4894,12 @@ restart:
           if (ndb_update_ndb_binlog_index)
           {
             ndb_add_ndb_binlog_index(thd, rows);
-            do_check_ndb_binlog_index= 0;
           }
           ndb_latest_applied_binlog_epoch= gci;
+          break;
         }
         ndb_latest_handled_binlog_epoch= gci;
 
-        if (do_check_ndb_binlog_index)
-        {
-          ndb_check_ndb_binlog_index(thd);
-          do_check_ndb_binlog_index= 0;
-        }
-
 #ifdef RUN_NDB_BINLOG_TIMER
         gci_timer.stop();
         sql_print_information("gci %ld event_count %d write time "
@@ -4960,25 +4932,16 @@ restart:
     free_root(&mem_root, MYF(0));
     *root_ptr= old_root;
     ndb_latest_handled_binlog_epoch= ndb_latest_received_binlog_epoch;
-
-    if (do_check_ndb_binlog_index)
-    {
-      ndb_check_ndb_binlog_index(thd);
-      do_check_ndb_binlog_index= 0;
-    }
   }
   if (do_ndbcluster_binlog_close_connection == BCCC_restart)
   {
     ndb_binlog_tables_inited= FALSE;
-    close_thread_tables(thd);
-    ndb_binlog_index= 0;
     goto restart;
   }
 err:
   sql_print_information("Stopping Cluster Binlog");
   DBUG_PRINT("info",("Shutting down cluster binlog thread"));
   thd->proc_info= "Shutting down";
-  close_thread_tables(thd);
   pthread_mutex_lock(&injector_mutex);
   /* don't mess with the injector_ndb anymore from other threads */
   injector_thd= 0;

=== modified file 'sql/rpl_injector.cc'
--- a/sql/rpl_injector.cc	2008-02-19 11:43:01 +0000
+++ b/sql/rpl_injector.cc	2008-06-18 12:53:42 +0000
@@ -86,6 +86,14 @@ int injector::transaction::commit()
    DBUG_RETURN(0);
 }
 
+int injector::transaction::rollback()
+{
+   DBUG_ENTER("injector::transaction::rollback()");
+   ha_autocommit_or_rollback(m_thd, 1 /* error to get rollback */);
+   end_trans(m_thd, ROLLBACK);
+   DBUG_RETURN(0);
+}
+
 int injector::transaction::use_table(server_id_type sid, table tbl)
 {
   DBUG_ENTER("injector::transaction::use_table");

=== modified file 'sql/rpl_injector.h'
--- a/sql/rpl_injector.h	2007-05-10 09:59:39 +0000
+++ b/sql/rpl_injector.h	2008-06-18 12:53:42 +0000
@@ -210,6 +210,14 @@ public:
       int commit();
 
       /*
+        Rollback a transaction.
+
+        This member function will clean up after a sequence of *_row calls by,
+        for example, releasing resource and unlocking files.
+      */
+      int rollback();
+
+      /*
         Get the position for the start of the transaction.
 
         Returns the position in the binary log of the first event in this

=== modified file 'storage/ndb/include/kernel/signaldata/SumaImpl.hpp'
--- a/storage/ndb/include/kernel/signaldata/SumaImpl.hpp	2008-02-20 09:04:29 +0000
+++ b/storage/ndb/include/kernel/signaldata/SumaImpl.hpp	2008-06-16 06:25:29 +0000
@@ -39,7 +39,8 @@ struct SubCreateReq {
     GetFlags     = 0xff << 16,
     RestartFlag  = 0x2 << 16,
     ReportAll    = 0x4 << 16,
-    ReportSubscribe= 0x8 << 16
+    ReportSubscribe= 0x8 << 16,
+    NR_Sub_Dropped = 0x1 << 24   // sub is dropped but needs to be copied
   };
   
   Uint32 senderRef;

=== modified file 'storage/ndb/include/mgmapi/mgmapi.h'
--- a/storage/ndb/include/mgmapi/mgmapi.h	2008-03-28 10:31:07 +0000
+++ b/storage/ndb/include/mgmapi/mgmapi.h	2008-08-07 03:44:29 +0000
@@ -444,10 +444,6 @@ extern "C" {
   int ndb_mgm_number_of_mgmd_in_connect_string(NdbMgmHandle handle);
 
   int ndb_mgm_set_configuration_nodeid(NdbMgmHandle handle, int nodeid);
-  int ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle);
-  int ndb_mgm_get_connected_port(NdbMgmHandle handle);
-  const char *ndb_mgm_get_connected_host(NdbMgmHandle handle);
-  const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
 
   /**
    * Set local bindaddress

=== modified file 'storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp'
--- a/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp	2008-02-19 15:00:29 +0000
+++ b/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp	2008-08-07 06:24:52 +0000
@@ -309,6 +309,7 @@ int
 NdbIndexScanOperation::setBound(const char* attr, int type, const void* value,
                                 Uint32 len)
 {
+  (void)len;  // unused
   return setBound(attr, type, value);
 }
 
@@ -317,6 +318,7 @@ int
 NdbIndexScanOperation::setBound(Uint32 anAttrId, int type, const void* value,
                                 Uint32 len)
 {
+  (void)len;  // unused
   return setBound(anAttrId, type, value);
 }
 

=== modified file 'storage/ndb/include/ndbapi/NdbOperation.hpp'
--- a/storage/ndb/include/ndbapi/NdbOperation.hpp	2008-04-28 14:17:28 +0000
+++ b/storage/ndb/include/ndbapi/NdbOperation.hpp	2008-08-07 06:24:52 +0000
@@ -1447,6 +1447,9 @@ inline
 int
 NdbOperation::checkMagicNumber(bool b)
 {
+#ifndef NDB_NO_DROPPED_SIGNAL
+  (void)b;  // unused param in this context
+#endif
   if (theMagicNumber != 0xABCDEF01){
 #ifdef NDB_NO_DROPPED_SIGNAL
     if(b) abort();
@@ -1566,8 +1569,10 @@ NdbOperation::NdbCon(NdbTransaction* aNd
 
 inline
 int
-NdbOperation::equal(const char* anAttrName, const char* aValue, Uint32 len)
+NdbOperation::equal(const char* anAttrName, const char* aValue,
+                    Uint32 len)
 {
+  (void)len;   // unused
   return equal(anAttrName, aValue);
 }
 
@@ -1601,8 +1606,10 @@ NdbOperation::equal(const char* anAttrNa
 
 inline
 int
-NdbOperation::equal(Uint32 anAttrId, const char* aValue, Uint32 len)
+NdbOperation::equal(Uint32 anAttrId, const char* aValue,
+                    Uint32 len)
 {
+  (void)len;   // unused
   return equal(anAttrId, aValue);
 }
 
@@ -1636,8 +1643,10 @@ NdbOperation::equal(Uint32 anAttrId, Uin
 
 inline
 int
-NdbOperation::setValue(const char* anAttrName, const char* aValue, Uint32 len)
+NdbOperation::setValue(const char* anAttrName, const char* aValue,
+                       Uint32 len)
 {
+  (void)len;   // unused
   return setValue(anAttrName, aValue);
 }
 
@@ -1685,8 +1694,10 @@ NdbOperation::setValue(const char* anAtt
 
 inline
 int
-NdbOperation::setValue(Uint32 anAttrId, const char* aValue, Uint32 len)
+NdbOperation::setValue(Uint32 anAttrId, const char* aValue,
+                       Uint32 len)
 {
+  (void)len;   // unused
   return setValue(anAttrId, aValue);
 }
 

=== modified file 'storage/ndb/include/ndbapi/NdbTransaction.hpp'
--- a/storage/ndb/include/ndbapi/NdbTransaction.hpp	2008-02-19 15:00:29 +0000
+++ b/storage/ndb/include/ndbapi/NdbTransaction.hpp	2008-08-07 06:24:52 +0000
@@ -1093,6 +1093,7 @@ inline
 void
 NdbTransaction::set_send_size(Uint32 send_size)
 {
+  (void)send_size; //unused
   return;
 }
 

=== modified file 'storage/ndb/src/common/logger/Logger.cpp'
--- a/storage/ndb/src/common/logger/Logger.cpp	2006-12-23 19:20:40 +0000
+++ b/storage/ndb/src/common/logger/Logger.cpp	2008-07-25 16:10:36 +0000
@@ -222,6 +222,7 @@ Logger::addHandler(const BaseString &log
       *err= handler->getErrorCode();
       if(handler->getErrorStr())
         strncpy(errStr, handler->getErrorStr(), len);
+      delete handler;
       DBUG_RETURN(false);
     }
     loghandlers.push_back(handler);

=== modified file 'storage/ndb/src/common/portlib/NdbCondition.c'
--- a/storage/ndb/src/common/portlib/NdbCondition.c	2006-12-23 19:20:40 +0000
+++ b/storage/ndb/src/common/portlib/NdbCondition.c	2008-06-09 11:57:17 +0000
@@ -26,7 +26,51 @@ struct NdbCondition
   pthread_cond_t cond;
 };
 
+#ifdef HAVE_CLOCK_GETTIME
+static int clock_id = CLOCK_REALTIME;
+#endif
 
+void
+NdbCondition_Init()
+{
+#if defined HAVE_CLOCK_GETTIME && defined HAVE_PTHREAD_CONDATTR_SETCLOCK && \
+    defined CLOCK_MONOTONIC
+  
+  int res, init = 0;
+  pthread_cond_t tmp;
+  pthread_condattr_t attr;
+  if ((res = pthread_condattr_init(&attr)) != 0)
+    goto nogo;
+
+  init = 1;
+  
+  if ((res = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) != 0)
+    goto nogo;
+
+  if ((res = pthread_cond_init(&tmp, &attr)) != 0)
+    goto nogo;
+
+  pthread_condattr_destroy(&attr);
+  pthread_cond_destroy(&tmp);
+
+  clock_id = CLOCK_MONOTONIC;
+  
+  return;
+  
+nogo:
+  if (init)
+  {
+    pthread_condattr_destroy(&attr);
+  }
+  
+  clock_id = CLOCK_REALTIME;
+  fprintf(stderr, 
+          "Failed to use CLOCK_MONOTONIC for pthread_condition res: %u\n", 
+          res);
+  fflush(stderr);
+  return;
+#endif
+}
 
 struct NdbCondition* 
 NdbCondition_Create(void)
@@ -38,8 +82,24 @@ NdbCondition_Create(void)
   
   if (tmpCond == NULL)
     return NULL;
-  
+ 
+#if defined HAVE_CLOCK_GETTIME && defined HAVE_PTHREAD_CONDATTR_SETCLOCK && \
+    defined CLOCK_MONOTONIC
+  if (clock_id == CLOCK_MONOTONIC)
+  {
+    pthread_condattr_t attr;
+    pthread_condattr_init(&attr);
+    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+    result = pthread_cond_init(&tmpCond->cond, &attr);
+    pthread_condattr_destroy(&attr);
+  }
+  else
+  {
+    result = pthread_cond_init(&tmpCond->cond, NULL);
+  }
+#else
   result = pthread_cond_init(&tmpCond->cond, NULL);
+#endif
   
   assert(result==0);
   return tmpCond;
@@ -73,7 +133,7 @@ NdbCondition_WaitTimeout(struct NdbCondi
     return 1;
   
 #ifdef HAVE_CLOCK_GETTIME
-  clock_gettime(CLOCK_REALTIME, &abstime);
+  clock_gettime(clock_id, &abstime);
 #else
   {
     struct timeval tick_time;

=== modified file 'storage/ndb/src/common/portlib/NdbTick.c'
--- a/storage/ndb/src/common/portlib/NdbTick.c	2007-06-05 16:00:42 +0000
+++ b/storage/ndb/src/common/portlib/NdbTick.c	2008-06-09 11:57:17 +0000
@@ -23,12 +23,18 @@
 #define MICROSEC_PER_MILLISEC 1000
 #define MILLISEC_PER_NANOSEC 1000000
 
-
 #ifdef HAVE_CLOCK_GETTIME
+
+#ifdef CLOCK_MONOTONIC
+#define CLOCK CLOCK_MONOTONIC
+#else
+#define CLOCK CLOCK_REALTIME
+#endif
+
 NDB_TICKS NdbTick_CurrentMillisecond(void)
 {
   struct timespec tick_time;
-  clock_gettime(CLOCK_REALTIME, &tick_time);
+  clock_gettime(CLOCK, &tick_time);
 
   return 
     ((NDB_TICKS)tick_time.tv_sec)  * ((NDB_TICKS)MILLISEC_PER_SEC) +
@@ -38,7 +44,7 @@ NDB_TICKS NdbTick_CurrentMillisecond(voi
 int 
 NdbTick_CurrentMicrosecond(NDB_TICKS * secs, Uint32 * micros){
   struct timespec t;
-  int res = clock_gettime(CLOCK_REALTIME, &t);
+  int res = clock_gettime(CLOCK, &t);
   * secs   = t.tv_sec;
   * micros = t.tv_nsec / 1000;
   return res;

=== modified file 'storage/ndb/src/common/transporter/TransporterRegistry.cpp'
--- a/storage/ndb/src/common/transporter/TransporterRegistry.cpp	2008-04-25 09:17:15 +0000
+++ b/storage/ndb/src/common/transporter/TransporterRegistry.cpp	2008-06-11 09:28:40 +0000
@@ -1165,6 +1165,17 @@ TransporterRegistry::start_clients_threa
 	if(t->isConnected())
 	  t->doDisconnect();
 	break;
+      case DISCONNECTED:
+      {
+        if (t->isConnected())
+        {
+          g_eventLogger->warning("Found connection to %u in state DISCONNECTED "
+                                 " while being connected, disconnecting!",
+                                 t->getRemoteNodeId());
+          t->doDisconnect();
+        }
+        break;
+      }
       default:
 	break;
       }

=== modified file 'storage/ndb/src/common/util/Makefile.am'
--- a/storage/ndb/src/common/util/Makefile.am	2008-05-09 17:53:25 +0000
+++ b/storage/ndb/src/common/util/Makefile.am	2008-06-09 18:58:35 +0000
@@ -35,10 +35,10 @@ testBitmask_LDFLAGS = @ndb_bin_am_ldflag
          $(top_builddir)/mysys/libmysyslt.la \
          $(top_builddir)/strings/libmystringslt.la
 
-#noinst_PROGRAMS = ndb_show_compat
-ndb_show_compat_SOURCES = ndb_show_compat.cc
+noinst_PROGRAMS = ndb_show_compat
+ndb_show_compat_SOURCES = ndb_show_compat.cpp
 ndb_show_compat_LDADD = \
-	$(builddir)libgeneral.la \
+	libgeneral.la \
 	$(top_builddir)/storage/ndb/src/common/portlib/libportlib.la \
 	$(top_builddir)/dbug/libdbuglt.la \
 	$(top_builddir)/mysys/libmysyslt.la \

=== modified file 'storage/ndb/src/common/util/ndb_init.cpp'
--- a/storage/ndb/src/common/util/ndb_init.cpp	2008-04-22 19:36:05 +0000
+++ b/storage/ndb/src/common/util/ndb_init.cpp	2008-06-09 11:57:17 +0000
@@ -26,6 +26,8 @@ extern void destroy_event_logger(class E
 
 static int ndb_init_called = 0;
 
+extern "C" void NdbCondition_Init();
+
 extern "C"
 {
 
@@ -44,6 +46,8 @@ ndb_init_internal()
       exit(1);
     }
   }
+
+  NdbCondition_Init();
 }
 
 int

=== renamed file 'storage/ndb/src/common/util/ndb_show_compat.cc' => 'storage/ndb/src/common/util/ndb_show_compat.cpp'
=== modified file 'storage/ndb/src/kernel/blocks/backup/Backup.cpp'
--- a/storage/ndb/src/kernel/blocks/backup/Backup.cpp	2008-05-16 13:08:36 +0000
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.cpp	2008-06-09 11:57:17 +0000
@@ -2367,9 +2367,8 @@ Backup::stopBackupReply(Signal* signal, 
 void
 Backup::initReportStatus(Signal *signal, BackupRecordPtr ptr)
 {
-  struct timeval the_time;
-  gettimeofday(&the_time, 0);
-  ptr.p->m_next_report = the_time.tv_sec + m_backup_report_frequency;
+  Uint64 now = NdbTick_CurrentMillisecond() / 1000;
+  ptr.p->m_next_report = now + m_backup_report_frequency;
 }
 
 void
@@ -2378,12 +2377,11 @@ Backup::checkReportStatus(Signal *signal
   if (m_backup_report_frequency == 0)
     return;
 
-  struct timeval the_time;
-  gettimeofday(&the_time, 0);
-  if (the_time.tv_sec > ptr.p->m_next_report)
+  Uint64 now = NdbTick_CurrentMillisecond() / 1000;
+  if (now > ptr.p->m_next_report)
   {
     reportStatus(signal, ptr);
-    ptr.p->m_next_report = the_time.tv_sec + m_backup_report_frequency;
+    ptr.p->m_next_report = now + m_backup_report_frequency;
   }
 }
 

=== modified file 'storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp	2008-04-23 14:29:01 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp	2008-06-09 10:04:48 +0000
@@ -12107,6 +12107,8 @@ void Dbdih::checkGcpStopLab(Signal* sign
  */
 void Dbdih::crashSystemAtGcpStop(Signal* signal, bool local)
 {
+  Uint32 save_counter = m_gcp_monitor.m_gcp_save.m_counter;
+  Uint32 micro_counter = m_gcp_monitor.m_micro_gcp.m_counter;
   m_gcp_monitor.m_gcp_save.m_counter = 0;
   m_gcp_monitor.m_micro_gcp.m_counter = 0;
 
@@ -12131,7 +12133,7 @@ void Dbdih::crashSystemAtGcpStop(Signal*
     return;
   }
 
-  if (m_gcp_monitor.m_gcp_save.m_counter == m_gcp_monitor.m_gcp_save.m_max_lag)
+  if (save_counter == m_gcp_monitor.m_gcp_save.m_max_lag)
   {
     switch(m_gcp_save.m_master.m_state){
     case GcpSave::GCP_SAVE_IDLE:
@@ -12195,7 +12197,7 @@ void Dbdih::crashSystemAtGcpStop(Signal*
     }
   }
 
-  if (m_gcp_monitor.m_micro_gcp.m_counter==m_gcp_monitor.m_micro_gcp.m_max_lag)
+  if (micro_counter == m_gcp_monitor.m_micro_gcp.m_max_lag)
   {
     switch(m_micro_gcp.m_master.m_state){
     case MicroGcp::M_GCP_IDLE:

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2008-05-30 06:33:46 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2008-07-23 11:15:31 +0000
@@ -8955,7 +8955,7 @@ Dblqh::copy_bounds(Uint32 * dst, TcConne
     
     if(len < left)
     {
-      offset = len;
+      offset = tcPtrP->m_offset_current_keybuf + len;
     }
     else
     {

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2008-03-25 16:49:01 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2008-08-04 15:49:01 +0000
@@ -1845,7 +1845,11 @@ int Dbtup::interpreterStartLab(Signal* s
 
   Uint32 RattroutCounter= 0;
   Uint32 RinstructionCounter= 5;
-  Uint32 RlogSize= 0;
+
+  /* All information to be logged/propagated to replicas
+   * is generated from here on so reset the log word count
+   */
+  Uint32 RlogSize= req_struct->log_size= 0;
   if (((RtotalLen + 5) == RattrinbufLen) &&
       (RattrinbufLen >= 5) &&
       (RattrinbufLen < ZATTR_BUFFER_SIZE)) {
@@ -1951,7 +1955,12 @@ int Dbtup::interpreterStartLab(Signal* s
 	return -1;
       }
     }
-    req_struct->log_size= RlogSize;
+    /* Add log words explicitly generated here to existing log size
+     *  - readAttributes can generate log for ANYVALUE column
+     *    It adds the words directly to req_struct->log_size
+     *    This is used for ANYVALUE and interpreted delete.
+     */
+    req_struct->log_size+= RlogSize;
     req_struct->read_length= RattroutCounter;
     sendReadAttrinfo(signal, req_struct, RattroutCounter, regOperPtr);
     if (RlogSize > 0) {

=== modified file 'storage/ndb/src/kernel/blocks/suma/Suma.cpp'
--- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp	2008-05-21 07:18:45 +0000
+++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp	2008-06-17 08:49:39 +0000
@@ -733,6 +733,7 @@ void Suma::execAPI_FAILREQ(Signal* signa
 
   c_failedApiNodes.set(failedApiNode);
   c_subscriber_nodes.clear(failedApiNode);
+  c_subscriber_per_node[failedApiNode] = 0;
   
   check_start_handover(signal);
 
@@ -1470,6 +1471,16 @@ Suma::execSUB_CREATE_REQ(Signal* signal)
     Subscription::REPORT_SUBSCRIBE : 0;
   const Uint32 tableId = req.tableId;
 
+  bool subDropped = req.subscriptionType & SubCreateReq::NR_Sub_Dropped;
+
+  /**
+   * This 2 options are only allowed during NR
+   */
+  if (subDropped)
+  {
+    ndbrequire(refToNode(senderRef) == c_startup.m_restart_server_node_id);
+  }
+
   Subscription key;
   key.m_subscriptionId  = subId;
   key.m_subscriptionKey = subKey;
@@ -1551,6 +1562,12 @@ Suma::execSUB_CREATE_REQ(Signal* signal)
   subOpPtr.p->m_senderRef = senderRef;
   subOpPtr.p->m_senderData = senderData;
 
+  if (subDropped)
+  {
+    jam();
+    subPtr.p->m_options |= Subscription::MARKED_DROPPED;
+  }
+
   TablePtr tabPtr;
   if (found)
   {
@@ -2343,11 +2360,6 @@ Suma::execSUB_START_REQ(Signal* signal){
   case Subscription::UNDEFINED:
     jam();
     ndbrequire(false);
-  case Subscription::DROPPED:
-    jam();
-    sendSubStartRef(signal,
-                    senderRef, senderData, SubStartRef::Dropped);
-    return;
   case Subscription::DEFINING:
     jam();
     sendSubStartRef(signal,
@@ -2357,6 +2369,23 @@ Suma::execSUB_START_REQ(Signal* signal){
     break;
   }
 
+  if (subPtr.p->m_options & Subscription::MARKED_DROPPED)
+  {
+    jam();
+    if (c_startup.m_restart_server_node_id == 0)
+    {
+      sendSubStartRef(signal,
+                      senderRef, senderData, SubStartRef::Dropped);
+      return;
+    }
+    else
+    {
+      /**
+       * Allow SUB_START_REQ from peer node
+       */
+    }
+  }
+
   if (subPtr.p->m_trigger_state == Subscription::T_ERROR)
   {
     jam();
@@ -2435,7 +2464,6 @@ Suma::execSUB_START_REQ(Signal* signal){
     break;
   case Subscription::T_DEFINED:{
     jam();
-
     report_sub_start_conf(signal, subPtr);
     return;
   }
@@ -2629,8 +2657,6 @@ Suma::report_sub_start_conf(Signal* sign
       Uint32 senderData = subOpPtr.p->m_senderData;
       c_subscriberPool.getPtr(ptr, subOpPtr.p->m_subscriberRef);
 
-      Uint32 nodeId = refToNode(ptr.p->m_senderRef);
-      
       if (check_sub_start(ptr.p->m_senderRef))
       {
         SubStartConf* conf = (SubStartConf*)signal->getDataPtrSend();
@@ -2654,6 +2680,7 @@ Suma::report_sub_start_conf(Signal* sign
         
         list.add(ptr);
         c_subscriber_nodes.set(refToNode(ptr.p->m_senderRef));
+        c_subscriber_per_node[refToNode(ptr.p->m_senderRef)]++;
       }
       else
       {
@@ -2715,27 +2742,40 @@ Suma::drop_triggers(Signal* signal, Subs
   jam();
 
   subPtr.p->m_outstanding_trigger = 0;
-  for(Uint32 j = 0; j<3; j++)
+
+  Ptr<Table> tabPtr;
+  c_tablePool.getPtr(tabPtr, subPtr.p->m_table_ptrI);
+  if (tabPtr.p->m_state == Table::DROPPED)
   {
-    Uint32 triggerId = subPtr.p->m_triggers[j];
-    if (triggerId != ILLEGAL_TRIGGER_ID)
+    jam();
+    subPtr.p->m_triggers[0] = ILLEGAL_TRIGGER_ID;
+    subPtr.p->m_triggers[1] = ILLEGAL_TRIGGER_ID;
+    subPtr.p->m_triggers[2] = ILLEGAL_TRIGGER_ID;
+  }
+  else
+  {
+    for(Uint32 j = 0; j<3; j++)
     {
-      jam();
-      subPtr.p->m_outstanding_trigger++;
-      DropTrigReq * const req = (DropTrigReq*)signal->getDataPtrSend();
-      req->setConnectionPtr(subPtr.i);
-      req->setUserRef(SUMA_REF);
-      req->setRequestType(DropTrigReq::RT_USER);
-      req->setTriggerType(TriggerType::SUBSCRIPTION_BEFORE);
-      req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
-      req->setIndexId(RNIL);
-
-      req->setTableId(subPtr.p->m_tableId);
-      req->setTriggerId(triggerId);
-      req->setTriggerEvent((TriggerEvent::Value)j);
+      Uint32 triggerId = subPtr.p->m_triggers[j];
+      if (triggerId != ILLEGAL_TRIGGER_ID)
+      {
+        jam();
+        subPtr.p->m_outstanding_trigger++;
+        DropTrigReq * const req = (DropTrigReq*)signal->getDataPtrSend();
+        req->setConnectionPtr(subPtr.i);
+        req->setUserRef(SUMA_REF);
+        req->setRequestType(DropTrigReq::RT_USER);
+        req->setTriggerType(TriggerType::SUBSCRIPTION_BEFORE);
+        req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
+        req->setIndexId(RNIL);
+
+        req->setTableId(subPtr.p->m_tableId);
+        req->setTriggerId(triggerId);
+        req->setTriggerEvent((TriggerEvent::Value)j);
 
-      sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ,
-                 signal, DropTrigReq::SignalLength, JBB);
+        sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ,
+                   signal, DropTrigReq::SignalLength, JBB);
+      }
     }
   }
 
@@ -2905,9 +2945,6 @@ Suma::execSUB_STOP_REQ(Signal* signal){
     sendSubStopRef(signal,
                    senderRef, senderData, SubStopRef::Defining);
     return;
-  case Subscription::DROPPED:
-    jam();
-    break;
   case Subscription::DEFINED:
     jam();
     break;
@@ -3121,6 +3158,17 @@ Suma::report_sub_stop_conf(Signal* signa
   conf->senderData= senderData;
   sendSignal(senderRef, GSN_SUB_STOP_CONF, signal,
 	     SubStopConf::SignalLength, JBB);
+
+  Uint32 nodeId = refToNode(ptr.p->m_senderRef);
+  if (c_subscriber_per_node[nodeId])
+  {
+    c_subscriber_per_node[nodeId]--;
+    if (c_subscriber_per_node[nodeId] == 0)
+    {
+      jam();
+      c_subscriber_nodes.clear(nodeId);
+    }
+  }
 }
 
 void
@@ -3760,7 +3808,7 @@ Suma::execSUB_GCP_COMPLETE_REP(Signal* s
   if(m_gcp_complete_rep_count && !c_subscriber_nodes.isclear())
   {
     CRASH_INSERTION(13033);
-    
+
     NodeReceiverGroup rg(API_CLUSTERMGR, c_subscriber_nodes);
     sendSignal(rg, GSN_SUB_GCP_COMPLETE_REP, signal,
 	       SubGcpCompleteRep::SignalLength, JBB);
@@ -3783,12 +3831,13 @@ Suma::execSUB_GCP_COMPLETE_REP(Signal* s
   /**
    * Add GCP COMPLETE REP to buffer
    */
+  bool subscribers = !c_subscriber_nodes.isclear();
   for(Uint32 i = 0; i<c_no_of_buckets; i++)
   {
     if(m_active_buckets.get(i))
       continue;
 
-    if (!c_subscriber_nodes.isclear())
+    if (subscribers || (c_buckets[i].m_state & Bucket::BUCKET_RESEND))
     {
       //Uint32* dst;
       get_buffer_ptr(signal, i, gci, 0);
@@ -3834,6 +3883,14 @@ Suma::execDROP_TAB_CONF(Signal *signal)
   tabPtr.p->m_state = Table::DROPPED;
   c_tables.remove(tabPtr);
 
+  if (tabPtr.p->m_subscriptions.isEmpty())
+  {
+    jam();
+    tabPtr.p->release(* this);
+    c_tablePool.release(tabPtr);
+    return;
+  }
+
   if (senderRef == 0)
   {
     jam();
@@ -3984,8 +4041,10 @@ Suma::execSUB_GCP_COMPLETE_ACK(Signal* s
     return;
   }
 
-  if (refToBlock(senderRef) == SUMA) {
+  if (refToBlock(senderRef) == SUMA) 
+  {
     jam();
+
     // Ack from other SUMA
     Uint32 nodeId= refToNode(senderRef);
     for(Uint32 i = 0; i<c_no_of_buckets; i++)
@@ -4099,18 +4158,20 @@ Suma::execSUB_REMOVE_REQ(Signal* signal)
   case Subscription::DEFINING:
     jam();
     ndbrequire(false);
-  case Subscription::DROPPED:
-    /**
-     * already dropped
-     */
-    jam();
-    sendSubRemoveRef(signal, req, SubRemoveRef::AlreadyDropped);
-    return;
   case Subscription::DEFINED:
+    if (subPtr.p->m_options & Subscription::MARKED_DROPPED)
+    {
+      /**
+       * already dropped
+       */
+      jam();
+      sendSubRemoveRef(signal, req, SubRemoveRef::AlreadyDropped);
+      return;
+    }
     break;
   }
 
-  subPtr.p->m_state = Subscription::DROPPED;
+  subPtr.p->m_options |= Subscription::MARKED_DROPPED;
   check_release_subscription(signal, subPtr);
 
   SubRemoveConf * const conf = (SubRemoveConf*)signal->getDataPtrSend();
@@ -4182,10 +4243,10 @@ do_release:
   if (tabPtr.p->m_state == Table::DROPPED)
   {
     jam();
-    subPtr.p->m_state = Subscription::DROPPED;
+    subPtr.p->m_options |= Subscription::MARKED_DROPPED;
   }
 
-  if (subPtr.p->m_state != Subscription::DROPPED)
+  if ((subPtr.p->m_options & Subscription::MARKED_DROPPED) == 0)
   {
     jam();
     return;
@@ -4376,32 +4437,35 @@ Suma::sendSubCreateReq(Signal* signal, P
     return;
   }
 
-  Ptr<Table> tabPtr;
-  c_tablePool.getPtr(tabPtr, subPtr.p->m_table_ptrI);
+  c_restart.m_waiting_on_self = 0;
+  SubCreateReq * req = (SubCreateReq *)signal->getDataPtrSend();
+  req->senderRef        = reference();
+  req->senderData       = subPtr.i;
+  req->subscriptionId   = subPtr.p->m_subscriptionId;
+  req->subscriptionKey  = subPtr.p->m_subscriptionKey;
+  req->subscriptionType = subPtr.p->m_subscriptionType;
+  req->tableId          = subPtr.p->m_tableId;
 
-  if (subPtr.p->m_state != Subscription::DROPPED &&
-      tabPtr.p->m_state != Table::DROPPED)
+  if (subPtr.p->m_options & Subscription::REPORT_ALL)
   {
-    jam();
-    c_restart.m_waiting_on_self = 0;
-    SubCreateReq * req = (SubCreateReq *)signal->getDataPtrSend();
-    req->senderRef        = reference();
-    req->senderData       = subPtr.i;
-    req->subscriptionId   = subPtr.p->m_subscriptionId;
-    req->subscriptionKey  = subPtr.p->m_subscriptionKey;
-    req->subscriptionType = subPtr.p->m_subscriptionType;
-    req->tableId          = subPtr.p->m_tableId;
+    req->subscriptionType |= SubCreateReq::ReportAll;
+  }
 
-    if (subPtr.p->m_options & Subscription::REPORT_ALL)
-    {
-      req->subscriptionType |= SubCreateReq::ReportAll;
-    }
+  if (subPtr.p->m_options & Subscription::REPORT_SUBSCRIBE)
+  {
+    req->subscriptionType |= SubCreateReq::ReportSubscribe;
+  }
 
-    if (subPtr.p->m_options & Subscription::REPORT_SUBSCRIBE)
-    {
-      req->subscriptionType |= SubCreateReq::ReportSubscribe;
-    }
+  if (subPtr.p->m_options & Subscription::MARKED_DROPPED)
+  {
+    req->subscriptionType |= SubCreateReq::NR_Sub_Dropped;
+    ndbout_c("copying dropped sub: %u", subPtr.i);
+  }
 
+  Ptr<Table> tabPtr;
+  c_tablePool.getPtr(tabPtr, subPtr.p->m_table_ptrI);
+  if (tabPtr.p->m_state != Table::DROPPED)
+  {
     if (!ndbd_suma_dictlock(getNodeInfo(refToNode(c_restart.m_ref)).m_version))
     {
       jam();
@@ -4414,16 +4478,17 @@ Suma::sendSubCreateReq(Signal* signal, P
        *   Thank you Ms. Fortuna
        */
     }
-    
+
     sendSignal(c_restart.m_ref, GSN_SUB_CREATE_REQ, signal,
                SubCreateReq::SignalLength, JBB);
   }
   else
   {
-    /**
-     * No need to copy DROPPED subscription...
-     *   but this introduces a real time break
-     */
+    jam();
+    ndbout_c("not copying sub %u with dropped table: %u/%u",
+             subPtr.i,
+             tabPtr.p->m_tableId, tabPtr.i);
+
     c_restart.m_waiting_on_self = 1;
     SubCreateConf * conf = (SubCreateConf *)signal->getDataPtrSend();
     conf->senderRef        = reference();
@@ -4476,16 +4541,23 @@ Suma::execSUB_CREATE_CONF(Signal* signal
     abort_start_me(signal, subPtr, true);
     return;
   }
+  
+  Ptr<Table> tabPtr;
+  c_tablePool.getPtr(tabPtr, subPtr.p->m_table_ptrI);
 
   Ptr<Subscriber> ptr;
-  if (subPtr.p->m_state != Subscription::DROPPED)
+  if (tabPtr.p->m_state != Table::DROPPED)
   {
+    jam();
     LocalDLList<Subscriber> list(c_subscriberPool, subPtr.p->m_subscribers);
     list.first(ptr);
   }
   else
   {
+    jam();
     ptr.setNull();
+    ndbout_c("not copying subscribers on sub: %u with dropped table %u/%u",
+             subPtr.i, tabPtr.p->m_tableId, tabPtr.i);
   }
 
   copySubscriber(signal, subPtr, ptr);
@@ -4905,7 +4977,8 @@ Suma::release_gci(Signal* signal, Uint32
   if(unlikely(bucket->m_state & mask))
   {
     jam();
-    ndbout_c("release_gci(%d, %llu) -> node failure -> abort", buck, gci);
+    ndbout_c("release_gci(%d, %llu) 0x%x-> node failure -> abort", 
+             buck, gci, bucket->m_state);
     return;
   }
   
@@ -5012,7 +5085,7 @@ Suma::start_resend(Signal* signal, Uint3
   }
 
   Uint64 min= bucket->m_max_acked_gci + 1;
-  Uint64 max = pos.m_max_gci;
+  Uint64 max = m_max_seen_gci;
 
   ndbrequire(max <= m_max_seen_gci);
 
@@ -5021,7 +5094,9 @@ Suma::start_resend(Signal* signal, Uint3
     ndbrequire(pos.m_page_id == bucket->m_buffer_tail);
     m_active_buckets.set(buck);
     m_gcp_complete_rep_count ++;
-    ndbout_c("empty bucket -> active");
+    ndbout_c("empty bucket (%u/%u %u/%u) -> active", 
+             Uint32(min >> 32), Uint32(min),
+             Uint32(max >> 32), Uint32(max));
     return;
   }
 

=== modified file 'storage/ndb/src/kernel/blocks/suma/Suma.hpp'
--- a/storage/ndb/src/kernel/blocks/suma/Suma.hpp	2008-05-21 07:18:45 +0000
+++ b/storage/ndb/src/kernel/blocks/suma/Suma.hpp	2008-06-17 08:49:39 +0000
@@ -228,13 +228,13 @@ public:
 
     enum Options {
       REPORT_ALL       = 0x1,
-      REPORT_SUBSCRIBE = 0x2
+      REPORT_SUBSCRIBE = 0x2,
+      MARKED_DROPPED   = 0x4
     };
 
     enum State {
       UNDEFINED,
       DEFINED,
-      DROPPED,
       DEFINING
     };
 
@@ -578,7 +578,8 @@ private:
   STATIC_CONST( NO_OF_BUCKETS = 24 ); // 24 = 4*3*2*1! 
   Uint32 c_no_of_buckets;
   struct Bucket c_buckets[NO_OF_BUCKETS];
-  
+  Uint32 c_subscriber_per_node[MAX_NODES];
+
   STATIC_CONST( BUCKET_MASK_SIZE = (((NO_OF_BUCKETS+31)>> 5)) );
   typedef Bitmask<BUCKET_MASK_SIZE> Bucket_mask;
   Bucket_mask m_active_buckets;

=== modified file 'storage/ndb/src/kernel/blocks/suma/SumaInit.cpp'
--- a/storage/ndb/src/kernel/blocks/suma/SumaInit.cpp	2008-02-20 09:04:29 +0000
+++ b/storage/ndb/src/kernel/blocks/suma/SumaInit.cpp	2008-06-17 08:49:39 +0000
@@ -124,6 +124,7 @@ Suma::Suma(Block_context& ctx) :
   m_gcp_monitor = 0;
 #endif
   m_missing_data = false;
+  bzero(c_subscriber_per_node, sizeof(c_subscriber_per_node));
 }
 
 Suma::~Suma()

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2008-04-22 19:36:05 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2008-07-29 09:39:57 +0000
@@ -908,12 +908,14 @@ int MgmtSrvr::sendStopMgmd(NodeId nodeId
     if(ndb_mgm_connect(h,1,0,0))
     {
       DBUG_PRINT("info",("failed ndb_mgm_connect"));
+      ndb_mgm_destroy_handle(&h);
       return SEND_OR_RECEIVE_FAILED;
     }
     if(!restart)
     {
       if(ndb_mgm_stop(h, 1, (const int*)&nodeId) < 0)
       {
+        ndb_mgm_destroy_handle(&h);
         return SEND_OR_RECEIVE_FAILED;
       }
     }
@@ -923,6 +925,7 @@ int MgmtSrvr::sendStopMgmd(NodeId nodeId
       nodes[0]= (int)nodeId;
       if(ndb_mgm_restart2(h, 1, nodes, initialStart, nostart, abort) < 0)
       {
+        ndb_mgm_destroy_handle(&h);
         return SEND_OR_RECEIVE_FAILED;
       }
     }

=== modified file 'storage/ndb/src/ndbapi/Ndb.cpp'
--- a/storage/ndb/src/ndbapi/Ndb.cpp	2008-06-03 10:00:31 +0000
+++ b/storage/ndb/src/ndbapi/Ndb.cpp	2008-06-16 12:34:47 +0000
@@ -1894,11 +1894,9 @@ Uint64 Ndb::getLatestGCI()
 
 void Ndb::setReportThreshEventGCISlip(unsigned thresh)
 {
- if (theEventBuffer->m_free_thresh != thresh)
+ if (theEventBuffer->m_gci_slip_thresh != thresh)
  {
-   theEventBuffer->m_free_thresh= thresh;
-   theEventBuffer->m_min_free_thresh= thresh;
-   theEventBuffer->m_max_free_thresh= 100;
+   theEventBuffer->m_gci_slip_thresh= thresh;
  }
 }
 

=== modified file 'storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp	2008-04-22 19:36:05 +0000
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp	2008-06-25 12:49:13 +0000
@@ -1046,10 +1046,10 @@ NdbEventBuffer::NdbEventBuffer(Ndb *ndb)
   m_ndb(ndb),
   m_latestGCI(0), m_latest_complete_GCI(0),
   m_total_alloc(0),
-  m_free_thresh(10),
-  m_min_free_thresh(10),
-  m_max_free_thresh(100),
-  m_gci_slip_thresh(3),
+  m_free_thresh(0),
+  m_min_free_thresh(0),
+  m_max_free_thresh(0),
+  m_gci_slip_thresh(0),
   m_dropped_ev_op(0),
   m_active_op_count(0),
   m_add_drop_mutex(0)
@@ -1957,14 +1957,14 @@ NdbEventBuffer::complete_outof_order_gci
   Uint64 stop_gci = m_latest_complete_GCI;
 
   Uint64 start_gci = array[minpos];
-  g_eventLogger->info("complete_outof_order_gcis from: %u/%u to: %u/%u",
-                      Uint32(start_gci >> 32), Uint32(start_gci),
-                      Uint32(stop_gci >> 32), Uint32(stop_gci));
+  g_eventLogger->info("complete_outof_order_gcis from: %u/%u(%u) to: %u/%u(%u)",
+                      Uint32(start_gci >> 32), Uint32(start_gci), minpos,
+                      Uint32(stop_gci >> 32), Uint32(stop_gci), maxpos);
 
   assert(start_gci <= stop_gci);
   do
   {
-    Uint64 start_gci = array[minpos];
+    start_gci = array[minpos];
     Gci_container* bucket = find_bucket(start_gci);
     assert(bucket);
     assert(maxpos == m_max_gci_index);
@@ -1978,10 +1978,10 @@ NdbEventBuffer::complete_outof_order_gci
 
 #ifdef VM_TRACE
     ndbout_c("complete_outof_order_gcis - completing %u/%u rows: %u",
-             Uint32(start_gci), Uint32(start_gci), bucket->m_data.m_count);
+             Uint32(start_gci >> 32), Uint32(start_gci), bucket->m_data.m_count);
 #else
     ndbout_c("complete_outof_order_gcis - completing %u/%u",
-             Uint32(start_gci), Uint32(start_gci));
+             Uint32(start_gci >> 32), Uint32(start_gci));
 #endif
     
     complete_bucket(bucket);
@@ -3277,28 +3277,32 @@ NdbEventBuffer::reportStatus()
   else
     apply_gci= latest_gci;
 
-  if (100*(Uint64)m_free_data_sz < m_min_free_thresh*(Uint64)m_total_alloc &&
-      m_total_alloc > 1024*1024)
+  if (m_free_thresh)
   {
-    /* report less free buffer than m_free_thresh,
-       next report when more free than 2 * m_free_thresh
-    */
-    m_min_free_thresh= 0;
-    m_max_free_thresh= 2 * m_free_thresh;
-    goto send_report;
-  }
+    if (100*(Uint64)m_free_data_sz < m_min_free_thresh*(Uint64)m_total_alloc &&
+        m_total_alloc > 1024*1024)
+    {
+      /* report less free buffer than m_free_thresh,
+         next report when more free than 2 * m_free_thresh
+      */
+      m_min_free_thresh= 0;
+      m_max_free_thresh= 2 * m_free_thresh;
+      goto send_report;
+    }
   
-  if (100*(Uint64)m_free_data_sz > m_max_free_thresh*(Uint64)m_total_alloc &&
-      m_total_alloc > 1024*1024)
-  {
-    /* report more free than 2 * m_free_thresh
-       next report when less free than m_free_thresh
-    */
-    m_min_free_thresh= m_free_thresh;
-    m_max_free_thresh= 100;
-    goto send_report;
+    if (100*(Uint64)m_free_data_sz > m_max_free_thresh*(Uint64)m_total_alloc &&
+        m_total_alloc > 1024*1024)
+    {
+      /* report more free than 2 * m_free_thresh
+         next report when less free than m_free_thresh
+      */
+      m_min_free_thresh= m_free_thresh;
+      m_max_free_thresh= 100;
+      goto send_report;
+    }
   }
-  if (latest_gci-apply_gci >=  m_gci_slip_thresh)
+  if (m_gci_slip_thresh &&
+      (latest_gci-apply_gci >= m_gci_slip_thresh))
   {
     goto send_report;
   }

=== modified file 'storage/ndb/src/ndbapi/NdbOperationExec.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2008-06-03 10:00:31 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2008-08-04 15:49:01 +0000
@@ -795,6 +795,28 @@ NdbOperation::buildSignalsNdbRecord(Uint
     }
   }
 
+  if (m_use_any_value && 
+      (tOpType == DeleteRequest))
+  {
+    /* Special hack for delete and ANYVALUE pseudo-column
+     * We want to be able set the ANYVALUE pseudo-column as
+     * part of a delete, but deletes don't allow updates
+     * So we perform a 'read' of the column, passing a value.
+     * Code in TUP which handles this 'read' will set the
+     * value when the read is processed.
+     */
+    res= insertATTRINFOHdr_NdbRecord(aTC_ConnectPtr, aTransId,
+                                     AttributeHeader::ANY_VALUE, 4,
+                                     &attrInfoPtr, &remain);
+    if(res)
+      return res;
+    res= insertATTRINFOData_NdbRecord(aTC_ConnectPtr, aTransId,
+                                      (const char *)(&m_any_value), 4,
+                                      &attrInfoPtr, &remain);
+    if(res)
+      return res;
+  }
+
   /* Interpreted program main signal words */
   if (code)
   {
@@ -977,10 +999,9 @@ NdbOperation::buildSignalsNdbRecord(Uint
 
   if ((tOpType == InsertRequest) ||
       (tOpType == WriteRequest) ||
-      (tOpType == UpdateRequest) ||
-      (tOpType == DeleteRequest))
+      (tOpType == UpdateRequest))
   {
-    /* Handle any setAnyValue(). */
+    /* Handle setAnyValue() for all cases except delete */
     if (m_use_any_value)
     {
       res= insertATTRINFOHdr_NdbRecord(aTC_ConnectPtr, aTransId,

=== modified file 'storage/ndb/src/ndbapi/NdbScanFilter.cpp'
--- a/storage/ndb/src/ndbapi/NdbScanFilter.cpp	2008-04-07 09:56:30 +0000
+++ b/storage/ndb/src/ndbapi/NdbScanFilter.cpp	2008-08-06 15:33:19 +0000
@@ -75,7 +75,11 @@ public:
     m_code= code;
     m_associated_op= NULL;
     
-    m_error.code = 0;
+    if (code == NULL)
+      /* NdbInterpretedCode not supported for operation type */
+      m_error.code = 4539;
+    else
+      m_error.code = 0;
   };
 
   /* This method propagates an error code from NdbInterpretedCode
@@ -136,13 +140,22 @@ NdbScanFilter::NdbScanFilter(class NdbOp
 {
   DBUG_ENTER("NdbScanFilter::NdbScanFilter(NdbOperation)");
   
-  /* We ask the NdbScanOperation to allocate an InterpretedCode
-   * object for us.  It will look after freeing it when 
-   * necessary.  This allows the InterpretedCode object to 
-   * survive after the NdbScanFilter has gone out of scope
+  NdbInterpretedCode* code= NULL;
+  NdbOperation::Type opType= op->getType();
+
+  /* If the operation is not of the correct type then
+   * m_impl.init() will set an error on the scan filter
    */
-  NdbInterpretedCode* code= 
-    ((NdbScanOperation *)op)->allocInterpretedCodeOldApi();
+  if (likely((opType == NdbOperation::TableScan) || 
+             (opType == NdbOperation::OrderedIndexScan)))
+  {    
+    /* We ask the NdbScanOperation to allocate an InterpretedCode
+     * object for us.  It will look after freeing it when 
+     * necessary.  This allows the InterpretedCode object to 
+     * survive after the NdbScanFilter has gone out of scope
+     */
+    code= ((NdbScanOperation *)op)->allocInterpretedCodeOldApi();
+  }
 
   m_impl.init(code);
 
@@ -158,6 +171,8 @@ NdbScanFilter::~NdbScanFilter()
 
 int
 NdbScanFilter::begin(Group group){
+  if (m_impl.m_error.code != 0) return -1;
+
   if (m_impl.m_stack2.push_back(m_impl.m_negative))
   {
     /* Memory allocation problem */
@@ -244,6 +259,8 @@ NdbScanFilter::begin(Group group){
 
 int
 NdbScanFilter::end(){
+  if (m_impl.m_error.code != 0) return -1;
+
   if(m_impl.m_stack2.size() == 0){
     /* Invalid set of range scan bounds */
     m_impl.m_error.code= 4259;
@@ -353,6 +370,8 @@ NdbScanFilter::end(){
 
 int
 NdbScanFilter::istrue(){
+  if(m_impl.m_error.code != 0) return -1;
+
   if(m_impl.m_current.m_group < NdbScanFilter::AND || 
      m_impl.m_current.m_group > NdbScanFilter::NOR){
     /* Operator is not defined in NdbScanFilter::Group */
@@ -373,6 +392,7 @@ NdbScanFilter::istrue(){
 
 int
 NdbScanFilter::isfalse(){
+  if (m_impl.m_error.code != 0) return -1;
   if(m_impl.m_current.m_group < NdbScanFilter::AND || 
      m_impl.m_current.m_group > NdbScanFilter::NOR){
     /* Operator is not defined in NdbScanFilter::Group */
@@ -436,6 +456,8 @@ const int tab2_sz = sizeof(table2)/sizeo
 int
 NdbScanFilterImpl::cond_col(Interpreter::UnaryCondition op, Uint32 AttrId){
   
+  if (m_error.code != 0) return -1;
+
   if(op < 0 || op >= tab2_sz){
     /* Condition is out of bounds */
     m_error.code= 4262;
@@ -458,6 +480,8 @@ NdbScanFilterImpl::cond_col(Interpreter:
 
 int
 NdbScanFilter::isnull(int AttrId){
+  if (m_impl.m_error.code != 0) return -1;
+
   if(m_impl.m_negative == 1)
     return m_impl.cond_col(Interpreter::IS_NOT_NULL, AttrId);
   else
@@ -466,6 +490,8 @@ NdbScanFilter::isnull(int AttrId){
 
 int
 NdbScanFilter::isnotnull(int AttrId){
+  if (m_impl.m_error.code != 0) return -1;
+
   if(m_impl.m_negative == 1)
     return m_impl.cond_col(Interpreter::IS_NULL, AttrId);
   else
@@ -568,6 +594,8 @@ int
 NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op, 
 				  Uint32 AttrId, 
 				  const void * value, Uint32 len){
+  if (m_error.code != 0) return -1;
+
   if(op < 0 || op >= tab3_sz){
     /* Condition is out of bounds */
     m_error.code= 4262;

=== modified file 'storage/ndb/src/ndbapi/NdbScanOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2008-06-03 10:00:31 +0000
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2008-08-06 15:33:19 +0000
@@ -53,7 +53,7 @@ NdbScanOperation::NdbScanOperation(Ndb* 
   theSCAN_TABREQ = 0;
   m_executed = false;
   m_scan_buffer= NULL;
-  m_scanUsingOldApi= false;
+  m_scanUsingOldApi= true;
   m_interpretedCodeOldApi= NULL;
 }
 
@@ -119,7 +119,7 @@ NdbScanOperation::init(const NdbTableImp
   m_descending= false;
   m_read_range_no = 0;
   m_executed = false;
-  m_scanUsingOldApi= false;
+  m_scanUsingOldApi= true;
   m_interpretedCodeOldApi= NULL;
 
   m_api_receivers_count = 0;
@@ -951,16 +951,14 @@ NdbScanOperation::readTuples(NdbScanOper
                              Uint32 parallel,
                              Uint32 batch)
 {
-  // It is only possible to call readTuples if 
-  //  1. the scan transaction doesn't already  contain another scan operation
-  //  2. We have not already defined an old Api scan operation.
-  if (theNdbCon->theScanningOp != NULL ||
-      m_scanUsingOldApi ){
+  // It is only possible to call readTuples if the scan transaction 
+  // doesn't already contain a scan operation
+  if (theNdbCon->theScanningOp != NULL)
+  {
     setErrorCode(4605);
     return -1;
   }
-
-  m_scanUsingOldApi= true;
+  
   /* Save parameters for later */
   m_savedLockModeOldApi= lm;
   m_savedScanFlagsOldApi= scan_flags;

=== modified file 'storage/ndb/src/ndbapi/NdbTransaction.cpp'
--- a/storage/ndb/src/ndbapi/NdbTransaction.cpp	2008-05-21 16:39:51 +0000
+++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp	2008-08-06 15:33:19 +0000
@@ -1926,28 +1926,24 @@ from other transactions.
       tGCI_lo = 0;
     }
     Uint64 tGCI = Uint64(tGCI_lo) | (Uint64(tGCI_hi) << 32);
-    if (tCommitFlag == 1) {
+    if (tCommitFlag == 1) 
+    {
       theCommitStatus = Committed;
       theGlobalCheckpointId = tGCI;
       if (tGCI) // Read(dirty) only transaction doesnt get GCI
       {
 	*p_latest_trans_gci = tGCI;
       }
-    } else if ((tNoComp >= tNoSent) &&
-               (theLastExecOpInList->theCommitIndicator == 1)){
-      
-      
-/**********************************************************************/
-// We sent the transaction with Commit flag set and received a CONF with
-// no Commit flag set. This is clearly an anomaly.
-/**********************************************************************/
-      theError.code = 4011;
-      theCompletionStatus = CompletedFailure;
-      theReturnStatus = NdbTransaction::ReturnFailure;
-      theCommitStatus = Aborted;
-      return 0;
+    } 
+    else if (theLastExecOpInList->theCommitIndicator == 1)
+    {  
+      /**
+       * We're waiting for a commit reply...
+       */
+      return -1;
     }//if
-    if (tNoComp >= tNoSent) {
+    if (tNoComp >= tNoSent) 
+    {
       return 0;	// No more operations to wait for
     }//if
      // Not completed the reception yet.
@@ -2107,27 +2103,25 @@ NdbTransaction::receiveTCINDXCONF(const 
     Uint64 tGCI = Uint64(tGCI_lo) | (Uint64(tGCI_hi) << 32);
 
     theNoOfOpCompleted = tNoComp;
-    if (tCommitFlag == 1) {
+    if (tCommitFlag == 1) 
+    {
       theCommitStatus = Committed;
       theGlobalCheckpointId = tGCI;
       if (tGCI) // Read(dirty) only transaction doesnt get GCI
       {
 	*p_latest_trans_gci = tGCI;
       }
-    } else if ((tNoComp >= tNoSent) &&
-               (theLastExecOpInList->theCommitIndicator == 1)){
-
-      /**********************************************************************/
-      // We sent the transaction with Commit flag set and received a CONF with
-      // no Commit flag set. This is clearly an anomaly.
-      /**********************************************************************/
-      theError.code = 4011;
-      theCompletionStatus = NdbTransaction::CompletedFailure;
-      theCommitStatus = NdbTransaction::Aborted;
-      theReturnStatus = NdbTransaction::ReturnFailure;
-      return 0;
+    }
+    else if (theLastExecOpInList->theCommitIndicator == 1)
+    {  
+      /**
+       * We're waiting for a commit reply...
+       */
+      return -1;
     }//if
-    if (tNoComp >= tNoSent) {
+
+    if (tNoComp >= tNoSent) 
+    {
       return 0;	// No more operations to wait for
     }//if
      // Not completed the reception yet.
@@ -2589,6 +2583,8 @@ NdbTransaction::scanTable(const NdbRecor
     DBUG_RETURN(NULL);
   }
 
+  op_idx->m_scanUsingOldApi= false;
+
   /* The real work is done in NdbScanOperation */
   if (op_idx->scanTableImpl(result_record,
                             lock_mode,
@@ -2627,6 +2623,8 @@ NdbTransaction::scanIndex(const NdbRecor
     setOperationErrorCodeAbort(4000);
     return NULL;
   }
+
+  op->m_scanUsingOldApi= false;
 
   /* Defer the rest of the work to NdbIndexScanOperation */
   if (op->scanIndexImpl(key_record,

=== modified file 'storage/ndb/test/ndbapi/testInterpreter.cpp'
--- a/storage/ndb/test/ndbapi/testInterpreter.cpp	2008-05-23 09:07:58 +0000
+++ b/storage/ndb/test/ndbapi/testInterpreter.cpp	2008-06-18 14:55:21 +0000
@@ -206,8 +206,9 @@ int runTestBug19537(NDBT_Context* ctx, N
   // Load 64-bit constant into register 1 and
   // write from register 1 to 32-bit column KOL2
   const Uint64 reg_val = 0x0102030405060708ULL;
-
-  const Uint32* reg_ptr32 = (const Uint32*)&reg_val;
+  Uint32 reg_ptr32[2];
+  memcpy(reg_ptr32+0, (Uint8*)&reg_val, sizeof(Uint32));
+  memcpy(reg_ptr32+1, ((Uint8*)&reg_val)+4, sizeof(Uint32));
   if (reg_ptr32[0] == 0x05060708 && reg_ptr32[1] == 0x01020304) {
     g_err << "runTestBug19537: platform is LITTLE endian" << endl;
   } else if (reg_ptr32[0] == 0x01020304 && reg_ptr32[1] == 0x05060708) {

=== modified file 'storage/ndb/test/ndbapi/testNdbApi.cpp'
--- a/storage/ndb/test/ndbapi/testNdbApi.cpp	2007-07-02 17:08:02 +0000
+++ b/storage/ndb/test/ndbapi/testNdbApi.cpp	2008-06-03 12:37:17 +0000
@@ -1674,6 +1674,60 @@ done:
   return result;
 }
 
+int 
+runBug37158(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result = NDBT_OK;
+  Ndb* pNdb = GETNDB(step);
+
+  for (Uint32 i = 0; i<ctx->getNumLoops(); i++)
+  {
+    HugoOperations hugoOps(*ctx->getTab());
+    hugoOps.startTransaction(pNdb);
+    if (hugoOps.pkWriteRecord(pNdb, 0) != 0)
+    {
+      result = NDBT_FAILED;
+      goto done;
+    }
+    
+
+    if (hugoOps.pkWritePartialRecord(pNdb, 1) != 0)
+    {
+      result = NDBT_FAILED;
+      goto done;
+    }
+    
+    if (hugoOps.pkWriteRecord(pNdb, 2) != 0)
+    {
+      result = NDBT_FAILED;
+      goto done;
+    }
+    
+    if (hugoOps.pkUpdateRecord(pNdb, 0) != 0)
+    {
+      result = NDBT_FAILED;
+      goto done;
+    }
+    
+    if (hugoOps.execute_Commit(pNdb, AO_IgnoreError) == 4011)
+    {
+      result = NDBT_FAILED;
+      goto done;
+    }
+    hugoOps.closeTransaction(pNdb);
+
+    if (runClearTable(ctx, step) != 0)
+    {
+      result = NDBT_FAILED;
+      goto done;
+    }
+  }
+  
+done:
+
+  return result;
+}
+
 NDBT_TESTSUITE(testNdbApi);
 TESTCASE("MaxNdb", 
 	 "Create Ndb objects until no more can be created\n"){ 
@@ -1781,6 +1835,10 @@ TESTCASE("ExecuteAsynch", 
 TESTCASE("Bug28443", 
 	 ""){ 
   INITIALIZER(runBug28443);
+}
+TESTCASE("Bug37158", 
+	 ""){ 
+  INITIALIZER(runBug37158);
 }
 NDBT_TESTSUITE_END(testNdbApi);
 

=== modified file 'storage/ndb/test/ndbapi/testOIBasic.cpp'
--- a/storage/ndb/test/ndbapi/testOIBasic.cpp	2008-04-10 13:08:05 +0000
+++ b/storage/ndb/test/ndbapi/testOIBasic.cpp	2008-07-23 11:15:31 +0000
@@ -612,6 +612,10 @@ getcs(Par par)
       uint n = urandom(maxcsnumber);
       cs = get_charset(n, MYF(0));
       if (cs != 0) {
+        // avoid dodgy internal character sets
+        // see bug# 37554
+        if (cs->state & MY_CS_HIDDEN)
+          continue;
         // prefer complex charsets
         if (cs->mbmaxlen != 1 || urandom(5) == 0)
           break;

=== modified file 'storage/ndb/test/ndbapi/testScanFilter.cpp'
--- a/storage/ndb/test/ndbapi/testScanFilter.cpp	2008-02-19 15:00:29 +0000
+++ b/storage/ndb/test/ndbapi/testScanFilter.cpp	2008-08-06 15:33:19 +0000
@@ -894,6 +894,132 @@ int runMaxScanFilterSize(NDBT_Context* c
   return NDBT_OK;
 }
 
+
+int runScanFilterConstructorFail(NDBT_Context* ctx, NDBT_Step* step)
+{
+  /* We test that failures in the ScanFilter constructor can be
+   * detected by the various ScanFilter methods without
+   * issues
+   */
+  Ndb *myNdb = GETNDB(step);
+  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
+  const NdbDictionary::Table *myTable= myDict->getTable(TABLE_NAME);
+  if(myTable == NULL) 
+    APIERROR(myDict->getNdbError());
+
+  NdbTransaction* trans=myNdb->startTransaction();
+  
+  if (trans == NULL)
+  {
+    APIERROR(trans->getNdbError());
+    return NDBT_FAILED;
+  }
+  
+  /* Create an NdbRecord scan operation */
+  const NdbScanOperation* tabScan=
+    trans->scanTable(myTable->getDefaultRecord());
+  
+  if (tabScan==NULL)
+  {
+    APIERROR(trans->getNdbError());
+    return NDBT_FAILED;
+  }
+
+  /* Now we hackily try to add a ScanFilter after the operation
+   * is defined.  This will cause a failure within the 
+   * constructor
+   */
+  NdbScanFilter brokenSf((NdbScanOperation*) tabScan);
+
+  /* Scan operation should have an error */
+  if (tabScan->getNdbError().code != 4536)
+  {
+    ndbout << "Expected error 4536, had error " << 
+      tabScan->getNdbError().code << " instead" << endl;
+    return NDBT_FAILED;
+  }
+
+  /* ScanFilter should have an error */
+  if (brokenSf.getNdbError().code != 4539)
+  {
+    ndbout  << "Expected error 4539, had error " << 
+      brokenSf.getNdbError().code << " instead" << endl;
+    return NDBT_FAILED;
+  }
+  
+  if (brokenSf.begin() != -1)
+  { ndbout << "Bad rc from begin" << endl; return NDBT_FAILED; }
+
+  if (brokenSf.istrue() != -1)
+  { ndbout << "Bad rc from istrue" << endl; return NDBT_FAILED; }
+
+  if (brokenSf.isfalse() != -1)
+  { ndbout << "Bad rc from isfalse" << endl; return NDBT_FAILED; }
+
+  if (brokenSf.isnull(0) != -1)
+  { ndbout << "Bad rc from isnull" << endl; return NDBT_FAILED; }
+
+  if (brokenSf.isnotnull(0) != -1)
+  { ndbout << "Bad rc from isnotnull" << endl; return NDBT_FAILED; }
+
+  if (brokenSf.cmp(NdbScanFilter::COND_EQ, 0, NULL, 0) != -1)
+  { ndbout << "Bad rc from cmp" << endl; return NDBT_FAILED; }
+
+  if (brokenSf.end() != -1)
+  { ndbout << "Bad rc from begin" << endl; return NDBT_FAILED; }
+
+  trans->close();
+
+  /* Now we check that we can define a ScanFilter before 
+   * calling readTuples() for a scan operation
+   */
+  trans= myNdb->startTransaction();
+  
+  if (trans == NULL)
+  {
+    APIERROR(trans->getNdbError());
+    return NDBT_FAILED;
+  }
+  
+  /* Get an old Api table scan operation */
+  NdbScanOperation* tabScanOp=
+    trans->getNdbScanOperation(myTable);
+
+  if (tabScanOp==NULL)
+  {
+    APIERROR(trans->getNdbError());
+    return NDBT_FAILED;
+  }
+
+  /* Attempt to define a ScanFilter before calling readTuples() */
+  NdbScanFilter sf(tabScanOp);
+
+  /* Should be no problem ... */
+  if (sf.getNdbError().code != 0) 
+  { APIERROR(sf.getNdbError()); return NDBT_FAILED; };
+  
+ 
+  /* Ok, now attempt to define a ScanFilter against a primary key op */
+  NdbOperation* pkOp= trans->getNdbOperation(myTable);
+
+  if (pkOp == NULL)
+  {
+    APIERROR(trans->getNdbError());
+    return NDBT_FAILED;
+  }
+
+  NdbScanFilter sf2(pkOp);
+  
+  if (sf2.getNdbError().code != 4539)
+  {
+    ndbout << "Error, expected 4539" << endl;
+    APIERROR(sf2.getNdbError());
+    return NDBT_FAILED;
+  }
+
+  return NDBT_OK;
+}
+
 NDBT_TESTSUITE(testScanFilter);
 TESTCASE(TEST_NAME, 
 	 "Scan table TABLE_NAME for the records which accord with \
@@ -903,6 +1029,7 @@ TESTCASE(TEST_NAME, 
   INITIALIZER(runPopulate);
   INITIALIZER(runScanRandomFilterTest);
   INITIALIZER(runMaxScanFilterSize);
+  INITIALIZER(runScanFilterConstructorFail);
   FINALIZER(runDropTables);
 }
 

=== modified file 'storage/ndb/test/ndbapi/testSystemRestart.cpp'
--- a/storage/ndb/test/ndbapi/testSystemRestart.cpp	2008-03-25 15:46:12 +0000
+++ b/storage/ndb/test/ndbapi/testSystemRestart.cpp	2008-06-18 14:50:56 +0000
@@ -1276,7 +1276,7 @@ runBug29167(NDBT_Context* ctx, NDBT_Step
   Ndb* pNdb = GETNDB(step);
   const Uint32 nodeCount = restarter.getNumDbNodes();
 
-  if (nodeCount < 2)
+  if (nodeCount < 4)
     return NDBT_OK;
 
   int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_CHECKPOINT, 0 };

=== modified file 'storage/ndb/test/ndbapi/test_event.cpp'
--- a/storage/ndb/test/ndbapi/test_event.cpp	2008-04-25 09:17:15 +0000
+++ b/storage/ndb/test/ndbapi/test_event.cpp	2008-08-04 15:49:01 +0000
@@ -25,14 +25,13 @@
 
 #define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb()
 
-static int createEvent(Ndb *pNdb, 
+static int createEvent(Ndb *pNdb,
                        const NdbDictionary::Table &tab,
-                       NDBT_Context* ctx)
+                       bool merge_events,
+                       bool report)
 {
   char eventName[1024];
   sprintf(eventName,"%s_EVENT",tab.getName());
-  bool merge_events = ctx->getProperty("MergeEvents");
-  bool report = ctx->getProperty("ReportSubscribe");
 
   NdbDictionary::Dictionary *myDict = pNdb->getDictionary();
 
@@ -89,6 +88,16 @@ static int createEvent(Ndb *pNdb, 
   return NDBT_OK;
 }
 
+static int createEvent(Ndb *pNdb, 
+                       const NdbDictionary::Table &tab,
+                       NDBT_Context* ctx)
+{
+  bool merge_events = ctx->getProperty("MergeEvents");
+  bool report = ctx->getProperty("ReportSubscribe");
+
+  return createEvent(pNdb, tab, merge_events, report);
+}
+
 static int dropEvent(Ndb *pNdb, const NdbDictionary::Table &tab)
 {
   char eventName[1024];
@@ -1806,7 +1815,6 @@ runBug31701(NDBT_Context* ctx, NDBT_Step
   int records = ctx->getNumRecords();
   HugoTransactions hugoTrans(*ctx->getTab());
   
-  if(ctx->getPropertyWait("LastGCI", ~(Uint32)0))
   if(ctx->getPropertyWait("LastGCI_hi", ~(Uint32)0))
   {
     g_err << "FAIL " << __LINE__ << endl;
@@ -2515,6 +2523,522 @@ err:
 
 /** Telco 6.3 **/
 
+int
+runBug37279(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbRestarter res;
+  if (res.getNumDbNodes() < 2)
+  {
+    ctx->stopTest();
+    return NDBT_OK;
+  }
+
+  if (runCreateEvent(ctx, step))
+  {
+    return NDBT_FAILED;
+  }
+  
+  Ndb* pNdb = GETNDB(step);
+  NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+  
+  const NdbDictionary::Table* tab = dict->getTable(ctx->getTab()->getName());
+  const NdbDictionary::Table* org = tab;
+  NdbEventOperation* pOp0 = createEventOperation(pNdb, *tab);
+  
+  if (pOp0 == 0)
+  {
+    return NDBT_FAILED;
+  }
+  
+  {
+    Ndb* ndb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
+    if (ndb->init() != 0)
+    {
+      delete ndb;
+      ndbout_c("here: %u", __LINE__);
+      return NDBT_FAILED;
+    }
+    
+    if (ndb->waitUntilReady(30) != 0)
+    {
+      delete ndb;
+      ndbout_c("here: %u", __LINE__);
+      return NDBT_FAILED;
+    }
+    
+    ndb->getDictionary()->dropTable(tab->getName());
+    delete ndb;
+  }
+  
+  int nodeId = res.getDbNodeId(rand() % res.getNumDbNodes());
+  ndbout_c("stopping %u", nodeId);
+  res.restartOneDbNode(nodeId,
+                       /** initial */ false,
+                       /** nostart */ false,
+                       /** abort   */ true);
+  if (res.waitClusterStarted())
+  {
+    return NDBT_FAILED;
+  }
+  
+  pNdb->dropEventOperation(pOp0);
+  runDropEvent(ctx, step);
+
+  return NDBT_OK;
+}
+
+int
+runBug37338(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbRestarter res;
+  if (res.getNumDbNodes() < 2)
+  {
+    ctx->stopTest();
+    return NDBT_OK;
+  }
+
+  int nodeId = res.getDbNodeId(rand() % res.getNumDbNodes());
+
+  Ndb* pNdb = GETNDB(step);
+  NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+  const NdbDictionary::Table* tab = dict->getTable(ctx->getTab()->getName());
+
+  const char * name = "BugXXX";
+  NdbDictionary::Table copy = * tab;
+  copy.setName(name);
+  dict->dropTable(name);
+
+  for (int i = 0; i<ctx->getNumLoops(); i++)
+  {
+    Ndb* ndb0;
+    Ndb_cluster_connection *con0;
+    NdbEventOperation* pOp0;
+    NdbDictionary::Dictionary * dict0;
+
+    cc(&con0, &ndb0);
+    dict0 = ndb0->getDictionary();
+    if (dict0->createTable(copy) != 0)
+    {
+      ndbout << dict0->getNdbError() << endl;
+      return NDBT_FAILED;
+    }
+
+    const NdbDictionary::Table * copyptr = dict0->getTable(name);
+    if (copyptr == 0)
+    {
+      return NDBT_FAILED;
+    }
+    createEvent(ndb0, *copyptr, ctx);
+    pOp0 = createEventOperation(ndb0, *copyptr);
+    dict0 = ndb0->getDictionary();dict->dropTable(name);
+    
+    res.restartOneDbNode(nodeId,
+                         /** initial */ false,
+                         /** nostart */ true,
+                         /** abort   */ true);
+    
+    res.waitNodesNoStart(&nodeId, 1);
+    res.startNodes(&nodeId, 1);
+    if (res.waitClusterStarted())
+    {
+      return NDBT_FAILED;
+    }
+    
+    ndb0->dropEventOperation(pOp0);
+    
+    delete ndb0;
+    delete con0;
+  }
+  
+  return NDBT_OK;
+}
+
+int
+runBug37442(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbRestarter res;
+  if (res.getNumDbNodes() < 2)
+  {
+    ctx->stopTest();
+    return NDBT_OK;
+  }
+
+  int nodeId = res.getDbNodeId(rand() % res.getNumDbNodes());
+
+  Ndb* pNdb = GETNDB(step);
+  NdbDictionary::Dictionary* dict = pNdb->getDictionary();
+  const NdbDictionary::Table* tab = dict->getTable(ctx->getTab()->getName());
+
+  if (runCreateEvent(ctx, step))
+  {
+    return NDBT_FAILED;
+  }
+  
+  for (int i = 0; i<ctx->getNumLoops(); i++)
+  {
+    NdbEventOperation * pOp = createEventOperation(GETNDB(step), *tab);
+    
+    res.restartOneDbNode(nodeId,
+                         /** initial */ false,
+                         /** nostart */ true,
+                         /** abort   */ true);
+    
+    res.waitNodesNoStart(&nodeId, 1);
+
+    GETNDB(step)->dropEventOperation(pOp);
+    
+    res.startNodes(&nodeId, 1);
+    if (res.waitClusterStarted())
+    {
+      return NDBT_FAILED;
+    }
+  }
+
+  runDropEvent(ctx, step);
+  
+  return NDBT_OK;
+}
+
+const NdbDictionary::Table* createBoringTable(const char* name, Ndb* pNdb)
+{
+  NdbDictionary::Table tab;
+
+  tab.setName(name);
+
+  NdbDictionary::Column pk;
+  pk.setName("Key");
+  pk.setType(NdbDictionary::Column::Unsigned);
+  pk.setLength(1); 
+  pk.setNullable(false);
+  pk.setPrimaryKey(true);
+  tab.addColumn(pk);
+
+  NdbDictionary::Column attr;
+  attr.setName("Attr");
+  attr.setType(NdbDictionary::Column::Unsigned);
+  attr.setLength(1);
+  attr.setNullable(true);
+  attr.setPrimaryKey(false);
+  tab.addColumn(attr);
+  
+  pNdb->getDictionary()->dropTable(tab.getName());
+  if(pNdb->getDictionary()->createTable(tab) == 0)
+  {
+    ndbout << (NDBT_Table&)tab << endl;
+    return pNdb->getDictionary()->getTable(tab.getName());
+  }
+  
+  ndbout << "Table create failed, err : " << 
+    pNdb->getDictionary()->getNdbError().code << endl;
+  
+  return NULL;
+}
+
+/* Types of operation which can be tagged via 'setAnyValue */
+enum OpTypes {Insert, Update, Write, Delete, EndOfOpTypes};
+
+/** 
+ * executeOps
+ * Generate a number of PK operations of the supplied type
+ * using the passed operation options and setting the
+ * anyValue tag
+ */
+int
+executeOps(Ndb* pNdb,
+           const NdbDictionary::Table* tab,
+           OpTypes op, 
+           Uint32 rowCount,
+           Uint32 keyOffset,
+           Uint32 anyValueOffset,
+           NdbOperation::OperationOptions opts)
+{
+  NdbTransaction* trans= pNdb->startTransaction();
+  const NdbRecord* record= tab->getDefaultRecord();
+
+  char RowBuf[16];
+  Uint32* keyPtr= (Uint32*) NdbDictionary::getValuePtr(record,
+                                                       RowBuf,
+                                                       0);
+  Uint32* attrPtr= (Uint32*) NdbDictionary::getValuePtr(record,
+                                                       RowBuf,
+                                                       1);
+
+  for (Uint32 i=keyOffset; i < (keyOffset + rowCount); i++)
+  {
+    *keyPtr= *attrPtr= i;
+    opts.optionsPresent |= NdbOperation::OperationOptions::OO_ANYVALUE;
+    opts.anyValue= anyValueOffset + i;
+    bool allowInterpreted= 
+      (op == Update) ||
+      (op == Delete);
+
+    if (!allowInterpreted)
+      opts.optionsPresent &= 
+        ~ (Uint64) NdbOperation::OperationOptions::OO_INTERPRETED;
+
+    switch (op) {
+    case Insert : 
+      if (trans->insertTuple(record, 
+                             RowBuf, 
+                             NULL,
+                             &opts, 
+                             sizeof(opts)) == NULL)
+      {
+        g_err << "Can't create operation : " <<
+          trans->getNdbError().code << endl;
+        return NDBT_FAILED;
+      }
+      break;
+    case Update :
+      if (trans->updateTuple(record,
+                             RowBuf,
+                             record,
+                             RowBuf,
+                             NULL,
+                             &opts,
+                             sizeof(opts)) == NULL)
+      {
+        g_err << "Can't create operation : " <<
+          trans->getNdbError().code << endl;
+        return NDBT_FAILED;
+      }
+      break;
+    case Write : 
+      if (trans->writeTuple(record,
+                            RowBuf,
+                            record,
+                            RowBuf,
+                            NULL,
+                            &opts,
+                            sizeof(opts)) == NULL)
+      {
+        g_err << "Can't create operation : " <<
+          trans->getNdbError().code << endl;
+        return NDBT_FAILED;
+      }
+      break;
+    case Delete : 
+      if (trans->deleteTuple(record,
+                             RowBuf,
+                             record,
+                             NULL,
+                             NULL,
+                             &opts,
+                             sizeof(opts)) == NULL)
+      {
+        g_err << "Can't create operation : " <<
+          trans->getNdbError().code << endl;
+        return NDBT_FAILED;
+      }
+      break;
+    default:
+      g_err << "Bad operation type : " << op << endl;
+      return NDBT_FAILED;
+    }
+  }
+
+  trans->execute(Commit);
+
+  if (trans->getNdbError().code != 0)
+  {
+    g_err << "Error executing operations :" << 
+      trans->getNdbError().code << endl;
+    return NDBT_FAILED;
+  }
+  
+  trans->close();
+
+  return NDBT_OK;
+}
+
+int
+checkAnyValueInEvent(Ndb* pNdb,
+                     NdbRecAttr* preKey,
+                     NdbRecAttr* postKey,
+                     NdbRecAttr* preAttr,
+                     NdbRecAttr* postAttr,
+                     Uint32 num,
+                     Uint32 anyValueOffset,
+                     bool checkPre)
+{
+  Uint32 received= 0;
+
+  while (received < num)
+  {
+    int pollRc;
+
+    if ((pollRc= pNdb->pollEvents(10000)) < 0)
+    {
+      g_err << "Error while polling for events : " <<
+        pNdb->getNdbError().code;
+      return NDBT_FAILED;
+    }
+
+    if (pollRc == 0)
+    {
+      printf("No event, waiting...\n");
+      continue;
+    }
+
+    NdbEventOperation* event;
+    while((event= pNdb->nextEvent()) != NULL)
+    {
+//       printf("Event is %p of type %u\n",
+//              event, event->getEventType());
+//       printf("Got event, prekey is %u predata is %u \n",
+//              preKey->u_32_value(),
+//              preAttr->u_32_value());
+//       printf("           postkey is %u postdata is %u anyvalue is %u\n",
+//              postKey->u_32_value(),
+//              postAttr->u_32_value(),
+//              event->getAnyValue());
+      
+      received ++;
+      Uint32 keyVal= (checkPre? 
+                      preKey->u_32_value() :
+                      postKey->u_32_value());
+      
+      if (event->getAnyValue() != 
+          (anyValueOffset + keyVal))
+      {
+        g_err << "Error : Got event, key is " <<
+          keyVal << " anyValue is " <<
+          event->getAnyValue() <<
+          " expected " << (anyValueOffset + keyVal) 
+              << endl;
+        return NDBT_FAILED;
+      }
+    }
+  }
+
+  return NDBT_OK;
+}
+                      
+                      
+
+int
+runBug37672(NDBT_Context* ctx, NDBT_Step* step)
+{
+  /* InterpretedDelete and setAnyValue failed */
+  /* Let's create a boring, known table for this since 
+   * we don't yet have Hugo tools for NdbRecord
+   */
+  BaseString name; 
+  name.assfmt("TAB_TESTEVENT%d", rand() & 65535);
+  Ndb* pNdb= GETNDB(step);
+  
+  const NdbDictionary::Table* tab= createBoringTable(name.c_str(), pNdb);
+  
+  if (tab == NULL)
+    return NDBT_FAILED;
+  
+  /* Create an event to listen to events on the table */
+  char eventName[1024];
+  sprintf(eventName,"%s_EVENT", tab->getName());
+
+  if (createEvent(pNdb, *tab, false, true) != 0)
+    return NDBT_FAILED;
+
+  /* Now create the event operation to retrieve the events */
+  NdbEventOperation* eventOp;
+  eventOp= pNdb->createEventOperation(eventName);
+
+  if (eventOp == NULL)
+  {
+    g_err << "Failed to create event operation :" << 
+      pNdb->getNdbError().code << endl;
+    return NDBT_FAILED;
+  }
+
+  NdbRecAttr* eventKeyData= eventOp->getValue("Key");
+  NdbRecAttr* eventOldKeyData= eventOp->getPreValue("Key");
+  NdbRecAttr* eventAttrData= eventOp->getValue("Attr");
+  NdbRecAttr* eventOldAttrData= eventOp->getPreValue("Attr");
+  
+  if ((eventKeyData == NULL) || (eventAttrData == NULL))
+  {
+    g_err << "Failed to get NdbRecAttrs for events" << endl;
+    return NDBT_FAILED;
+  };
+  
+  if (eventOp->execute() != 0)
+  {
+    g_err << "Failed to execute event operation :" <<
+      eventOp->getNdbError().code << endl;
+    return NDBT_FAILED;
+  }
+
+  /* Perform some operations on the table, and check
+   * that we get the correct AnyValues propagated
+   * through
+   */
+  NdbOperation::OperationOptions opts;
+  opts.optionsPresent= 0;
+
+  NdbInterpretedCode nonsenseProgram;
+
+  nonsenseProgram.load_const_u32(0, 0);
+  nonsenseProgram.interpret_exit_ok();
+
+  nonsenseProgram.finalise();
+
+  const Uint32 rowCount= 1500;
+  Uint32 keyOffset= 0;
+  Uint32 anyValueOffset= 100;
+
+  printf ("Testing AnyValue with no interpreted program\n");
+  for (int variants= 0; variants < 2; variants ++)
+  {
+    for (int op= Insert; op < EndOfOpTypes; op++)
+    {
+      printf("  Testing opType %d (ko=%d, ao=%d)...", 
+             op, keyOffset, anyValueOffset);
+      
+      if (executeOps(pNdb, 
+                     tab, 
+                     (OpTypes)op, 
+                     rowCount, 
+                     keyOffset, 
+                     anyValueOffset, 
+                     opts))
+        return NDBT_FAILED;
+      
+      if (checkAnyValueInEvent(pNdb, 
+                               eventOldKeyData, eventKeyData,
+                               eventOldAttrData, eventAttrData,
+                               rowCount,
+                               anyValueOffset,
+                               false // always use postKey data
+                               ) != NDBT_OK)
+        return NDBT_FAILED;
+      printf("ok\n");
+    };
+    
+    printf("Testing AnyValue with interpreted program\n");
+    opts.optionsPresent|= NdbOperation::OperationOptions::OO_INTERPRETED;
+    opts.interpretedCode= &nonsenseProgram;
+  }
+    
+  if (dropEventOperations(pNdb) != 0)
+  {
+    g_err << "Dropping event operations failed : " << 
+      pNdb->getNdbError().code << endl;
+    return NDBT_FAILED;
+  }
+  
+  if (dropEvent(pNdb, tab->getName()) != 0)
+  {
+    g_err << "Dropping event failed : " << 
+      pNdb->getDictionary()->getNdbError().code << endl;
+    return NDBT_FAILED;
+  }
+
+  pNdb->getDictionary()->dropTable(tab->getName());
+  
+  return NDBT_OK;
+}
+
+
 NDBT_TESTSUITE(test_event);
 TESTCASE("BasicEventOperation", 
 	 "Verify that we can listen to Events"
@@ -2693,6 +3217,22 @@ TESTCASE("Bug35208", ""){
   FINALIZER(runDropEvent);
   FINALIZER(runVerify);
   FINALIZER(runDropShadowTable);
+}
+TESTCASE("Bug37279", "")
+{
+  INITIALIZER(runBug37279);
+}
+TESTCASE("Bug37338", "")
+{
+  INITIALIZER(runBug37338);
+}
+TESTCASE("Bug37442", "")
+{
+  INITIALIZER(runBug37442);
+}
+TESTCASE("Bug37672", "NdbRecord option OO_ANYVALUE causes interpreted delete to abort.")
+{
+  INITIALIZER(runBug37672);
 }
 NDBT_TESTSUITE_END(test_event);
 

=== modified file 'storage/ndb/test/run-test/autotest-boot.sh'
--- a/storage/ndb/test/run-test/autotest-boot.sh	2007-08-31 14:12:51 +0000
+++ b/storage/ndb/test/run-test/autotest-boot.sh	2008-06-08 05:21:05 +0000
@@ -78,7 +78,7 @@ fi
 # Validate that all interesting
 #   variables where set in conf
 ###############################
-vars="src_clone_base install_dir build_dir"
+vars="src_clone_base install_dir build_dir bzr_src_base"
 for i in $vars
 do
   t=`echo echo \\$$i`
@@ -103,7 +103,8 @@ fi
 # Setup the clone source location  #
 ####################################
 
-src_clone=${src_clone_base}${clone}
+#src_clone=${src_clone_base}/${clone}
+src_clone=${bzr_src_base}/${clone}
 
 #######################################
 # Check to see if the lock file exists#
@@ -152,12 +153,7 @@ fi
 if [ "$do_clone" ]
 then
 	rm -rf $dst_place
-	if [ `echo $src_clone | grep -c 'file:\/\/'` = 1 ]
-	then
-		bk clone -l $extra_clone $src_clone $dst_place
-	else
-		bk clone $extra_clone $src_clone $dst_place
-	fi
+	bzr export $dst_place $extra_clone $src_clone
 fi
 
 ##########################################

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2008-05-29 15:58:58 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2008-08-06 15:33:19 +0000
@@ -467,10 +467,6 @@ args: -n ScanReadWhileNodeIsDown D1 D2 
 
 max-time: 500
 cmd: testScan
-args: -n ScanRestart T1 D1 D2 
-
-max-time: 500
-cmd: testScan
 args: -l 100 -n Scan-bug8262 T6 D1 D2
 
 max-time: 500
@@ -1090,7 +1086,7 @@ max-time: 600
 cmd: test_event
 args: -l 1 -n SubscribeNR T1
 
-max-time: 300
+max-time: 600
 cmd: testNodeRestart
 args: -n Bug34702 T1
 
@@ -1098,6 +1094,18 @@ max-time: 600
 cmd: test_event
 args: -n Bug35208 T1
 
+max-time: 300
+cmd: test_event
+args: -n Bug37279 T1
+
+max-time: 300
+cmd: test_event
+args: -n Bug37338 T1
+
+max-time: 300
+cmd: test_event
+args: -n Bug37442 T1
+
 # 2008-04-22
 max-time: 1500
 cmd: testNodeRestart
@@ -1135,3 +1143,21 @@ cmd: testDict
 args: -l 1 -n FailAddFragment
 
 # EOF 2008-05-29
+# 2008-06-03
+max-time: 1200
+cmd: testNdbApi
+args: -l 100 -n Bug37158
+
+# EOF 2008-06-03
+
+max-time: 500
+cmd: test_event
+args -n bug37672 T1
+
+#EOF 2008-07-04
+
+max-time: 500
+cmd: testScanFilter
+args: 
+
+#EOF 2008-07-09

=== modified file 'storage/ndb/tools/restore/Restore.cpp'
--- a/storage/ndb/tools/restore/Restore.cpp	2008-03-17 16:31:55 +0000
+++ b/storage/ndb/tools/restore/Restore.cpp	2008-08-05 14:08:40 +0000
@@ -1002,13 +1002,19 @@ bool RestoreDataIterator::readFragmentHe
     if (Header.SectionType == BackupFormat::EMPTY_ENTRY)
     {
       void *tmp;
-      buffer_get_ptr(&tmp, Header.SectionLength*4-8, 1);
+      if (Header.SectionLength < 2)
+      {
+        err << "getFragmentFooter:Error reading fragment footer" << endl;
+        return false;
+      }
+      if (Header.SectionLength > 2)
+        buffer_get_ptr(&tmp, Header.SectionLength*4-8, 1);
       continue;
     }
     break;
   }
   /* read rest of header */
-  if (buffer_read(((char*)&Header)+8, sizeof(Header)-8, 1) != 1)
+  if (buffer_read(((char*)&Header)+8, Header.SectionLength*4-8, 1) != 1)
   {
     ret = 0;
     return false;

=== modified file 'storage/ndb/tools/restore/consumer_restore.cpp'
--- a/storage/ndb/tools/restore/consumer_restore.cpp	2007-12-20 15:36:18 +0000
+++ b/storage/ndb/tools/restore/consumer_restore.cpp	2008-06-18 15:03:43 +0000
@@ -21,6 +21,8 @@
 #include <ndb_internal.hpp>
 #include <ndb_logevent.h>
 
+#define NDB_ANYVALUE_FOR_NOLOGGING 0xFFFFFFFF
+
 extern my_bool opt_core;
 
 extern FilteredNdbOut err;
@@ -34,6 +36,8 @@ static Uint32 get_part_id(const NdbDicti
 extern const char * g_connect_string;
 extern BaseString g_options;
 
+extern unsigned int opt_no_binlog;
+
 bool
 BackupRestore::init()
 {
@@ -1314,6 +1318,11 @@ void BackupRestore::tuple_a(restore_call
       exitHandler();
     }
 
+    if (opt_no_binlog)
+    {
+      op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING);
+    }
+
     // Prepare transaction (the transaction is NOT yet sent to NDB)
     cb->n_bytes= n_bytes;
     cb->connection->executeAsynchPrepare(NdbTransaction::Commit,
@@ -1562,6 +1571,10 @@ BackupRestore::logEntry(const LogEntry &
     } // if
   }
   
+  if (opt_no_binlog)
+  {
+    op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING);
+  }
   const int ret = trans->execute(NdbTransaction::Commit);
   if (ret != 0)
   {

=== modified file 'storage/ndb/tools/restore/restore_main.cpp'
--- a/storage/ndb/tools/restore/restore_main.cpp	2007-09-12 12:07:08 +0000
+++ b/storage/ndb/tools/restore/restore_main.cpp	2008-07-24 09:23:05 +0000
@@ -55,6 +55,7 @@ unsigned int g_report_next;
 Vector<BaseString> g_databases;
 Vector<BaseString> g_tables;
 NdbRecordPrintFormat g_ndbrecord_print_format;
+unsigned int opt_no_binlog;
 
 NDB_STD_OPTS_VARS;
 
@@ -89,6 +90,7 @@ enum ndb_restore_options {
   OPT_LINES_TERMINATED_BY,
   OPT_APPEND,
   OPT_PROGRESS_FREQUENCY,
+  OPT_NO_BINLOG,
   OPT_VERBOSE
 };
 static const char *opt_fields_enclosed_by= NULL;
@@ -197,6 +199,10 @@ static struct my_option my_long_options[
     "Print status uf restore periodically in given seconds", 
     (uchar**) &opt_progress_frequency, (uchar**) &opt_progress_frequency, 0,
     GET_INT, REQUIRED_ARG, 0, 0, 65535, 0, 0, 0 },
+  { "no-binlog", OPT_NO_BINLOG,
+    "If a mysqld is connected and has binary log, do not log the restored data", 
+    (uchar**) &opt_no_binlog, (uchar**) &opt_no_binlog, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
   { "verbose", OPT_VERBOSE,
     "verbosity", 
     (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0,
@@ -648,20 +654,20 @@ static void exitHandler(int code)
 
 static void init_progress()
 {
-  struct timeval the_time;
-  gettimeofday(&the_time, 0);
-  g_report_next = the_time.tv_sec + opt_progress_frequency;
+  Uint64 now = NdbTick_CurrentMillisecond() / 1000;
+  g_report_next = now + opt_progress_frequency;
 }
 
 static int check_progress()
 {
   if (!opt_progress_frequency)
     return 0;
-  struct timeval the_time;
-  gettimeofday(&the_time, 0);
-  if (the_time.tv_sec >= g_report_next)
+
+  Uint64 now = NdbTick_CurrentMillisecond() / 1000;
+  
+  if (now  >= g_report_next)
   {
-    g_report_next = the_time.tv_sec + opt_progress_frequency;
+    g_report_next = now + opt_progress_frequency;
     return 1;
   }
   return 0;
@@ -887,7 +893,8 @@ main(int argc, char** argv)
     {
       if (!ga_skip_table_check){
         for(i=0; i < metaData.getNoOfTables(); i++){
-          if (checkSysTable(metaData, i))
+          if (checkSysTable(metaData, i) && 
+             checkDbAndTableName(metaData[i]))
           {
             for(Uint32 j= 0; j < g_consumers.size(); j++)
               if (!g_consumers[j]->table_equal(* metaData[i]))

=== modified file 'storage/ndb/tools/waiter.cpp'
--- a/storage/ndb/tools/waiter.cpp	2008-03-20 09:18:53 +0000
+++ b/storage/ndb/tools/waiter.cpp	2008-06-09 18:40:45 +0000
@@ -21,6 +21,7 @@
 #include <NdbMain.h>
 #include <NdbOut.hpp>
 #include <NdbSleep.h>
+#include <NdbTick.h>
 
 #include <NDBT.hpp>
 
@@ -214,12 +215,11 @@ waitClusterStatus(const char* _addr,
   const int MAX_RESET_ATTEMPTS = 10;
   bool allInState = false;
 
-  struct timeval time_now;
-  gettimeofday(&time_now, 0);
-  Int64 timeout_time = time_now.tv_sec + _timeout;
+  Uint64 time_now = NdbTick_CurrentMillisecond();
+  Uint64 timeout_time = time_now + 1000 * _timeout;
 
   while (allInState == false){
-    if (_timeout > 0 && time_now.tv_sec > timeout_time){
+    if (_timeout > 0 && time_now > timeout_time){
       /**
        * Timeout has expired waiting for the nodes to enter
        * the state we want
@@ -257,7 +257,7 @@ waitClusterStatus(const char* _addr,
 	    << " resetting timeout "
 	    << resetAttempts << endl;
 
-      timeout_time = time_now.tv_sec + _timeout;
+      timeout_time = time_now + 1000 * _timeout;
 
       resetAttempts++;
     }
@@ -290,7 +290,8 @@ waitClusterStatus(const char* _addr,
     }
 
     attempts++;
-    gettimeofday(&time_now, 0);
+    
+    time_now = NdbTick_CurrentMillisecond();
   }
   return 0;
 }

Thread
bzr commit into mysql-5.1-telco-6.2-merge branch (tomas.ulin:2663) Tomas Ulin7 Aug