List:Commits« Previous MessageNext Message »
From:Frazer Clement Date:November 8 2010 12:28pm
Subject:bzr push into mysql-5.1-telco-7.1 branch (frazer:3960 to 3961)
View as plain text  
 3961 Frazer Clement	2010-11-08 [merge]
      Merge 7.0->7.1

    added:
      mysql-test/suite/ndb_binlog/r/ndb_binlog_log_apply_status.result
      mysql-test/suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts_basic.inc
      mysql-test/suite/ndb_binlog/t/ndb_binlog_log_apply_status.test
      mysql-test/suite/rpl_ndb/r/rpl_ndb_break_3_chain.result
      mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.cnf
      mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.test
    modified:
      mysql-test/suite/ndb/r/ndb_basic.result
      mysql-test/suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts.inc
      mysql-test/suite/rpl_ndb/r/rpl_ndb_circular.result
      mysql-test/suite/rpl_ndb/t/rpl_ndb_circular.test
      sql/ha_ndbcluster.cc
      sql/ha_ndbcluster_binlog.cc
      storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
 3960 Maitrayi Sabaratnam	2010-11-08 [merge]
      Merge from 7.0

    modified:
      sql/ha_ndbcluster.cc
      storage/ndb/include/ndbapi/ndb_cluster_connection.hpp
      storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
      storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
=== modified file 'mysql-test/suite/ndb/r/ndb_basic.result'
--- a/mysql-test/suite/ndb/r/ndb_basic.result	2010-11-01 09:13:06 +0000
+++ b/mysql-test/suite/ndb/r/ndb_basic.result	2010-11-08 12:19:51 +0000
@@ -34,6 +34,7 @@ ndb_force_send	#
 ndb_index_stat_cache_entries	#
 ndb_index_stat_enable	#
 ndb_index_stat_update_freq	#
+ndb_log_apply_status	#
 ndb_log_bin	#
 ndb_log_binlog_index	#
 ndb_log_empty_epochs	#

=== added file 'mysql-test/suite/ndb_binlog/r/ndb_binlog_log_apply_status.result'
--- a/mysql-test/suite/ndb_binlog/r/ndb_binlog_log_apply_status.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb_binlog/r/ndb_binlog_log_apply_status.result	2010-11-08 12:19:51 +0000
@@ -0,0 +1,41 @@
+create table test.t1(a int primary key) engine=ndb;
+set global ndb_log_apply_status=Off;
+show variables like '%ndb_log_apply_status%';
+Variable_name	Value
+ndb_log_apply_status	OFF
+reset slave;
+reset master;
+Should have empty apply status table
+select * from mysql.ndb_apply_status;
+server_id	epoch	log_name	start_pos	end_pos
+Dummy incoming ndb_apply_status updates, should not be logged
+begin;
+insert into mysql.ndb_apply_status values (555, 12345, 'binlog.000001', 20, 30);
+insert into mysql.ndb_apply_status values (666, 67890, 'binlog.000001', 50, 60);
+replace into test.t1 values (1);
+commit;
+Should not see ndb_apply_status updates in the Binlog
+show binlog events;
+select txt from binlog_stmts where txt like '%binlog.000001%' order by txt;
+txt
+set global ndb_log_apply_status=On;
+show variables like '%ndb_log_apply_status%';
+Variable_name	Value
+ndb_log_apply_status	ON
+reset slave;
+reset master;
+Should have empty apply status table
+select * from mysql.ndb_apply_status;
+server_id	epoch	log_name	start_pos	end_pos
+Dummy incoming ndb_apply_status updates, should be logged
+begin;
+insert into mysql.ndb_apply_status values (555, 12345, 'binlog.000001', 20, 30);
+insert into mysql.ndb_apply_status values (666, 67890, 'binlog.000001', 50, 60);
+replace into test.t1 values (1);
+commit;
+Should see ndb_apply_status updates in the Binlog
+show binlog events;
+select txt from binlog_stmts where txt like '%binlog.000001%' order by txt;
+txt
+set global ndb_log_apply_status=Off;
+drop table test.t1;

=== modified file 'mysql-test/suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts.inc'
--- a/mysql-test/suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts.inc	2009-09-30 10:17:20 +0000
+++ b/mysql-test/suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts.inc	2010-11-08 12:19:51 +0000
@@ -1,91 +1,3 @@
-# 
-# Get the mysqlbinlog tool --verbose mode to dump the Binlog contents with
-# 'SQL' statements in triple-comments over multiple lines, e.g. :
-#
-### INSERT
-###  SET
-###  @1=1
-###  @2=2
-#
-# Then munch this output into single-line statements
-# e.g. :
-#  INSERT SET @1=1 @2=2
-#
-# Then filter + sort to get deterministic order independent of Ndb table 
-# fragmentation, epoch in ndb_apply_status etc.
-#
+let $Binlog_condition = not like '%ndb_apply_status%';
 
---disable_query_log
-let $MYSQLD_DATADIR= `select @@datadir;`;
---exec $MYSQL_BINLOG --verbose $MYSQLD_DATADIR/mysqld-bin.000001 > $MYSQLTEST_VARDIR/tmp/ndb_binlog_mysqlbinlog.sql
-
-create table raw_binlog_rows (txt varchar(1000));
-
---eval load data local infile '$MYSQLTEST_VARDIR/tmp/ndb_binlog_mysqlbinlog.sql' into table raw_binlog_rows columns terminated by '\n';
-
-create table binlog_stmt_parts_unassoc (txt varchar(1000), line_count int, stmt_boundary int);
-
-set @line_count=0;
-set @stmt_boundary=0;
-
-# Use replace() here to get rid of any unwanted Windows
-# CRs
-insert into binlog_stmt_parts_unassoc
-  select replace(txt, '\r', ''),
-         @line_count:= @line_count + 1,  # So we can preserve order later
-         (txt like '%INSERT%' or         # Identify statement boundaries
-          txt like '%UPDATE%' or
-          txt like '%DELETE%')
-    from raw_binlog_rows
-    where
-      txt like '###%';                   # Discard non verbose output
-
-#select * from binlog_stmt_parts_unassoc;
-
-create table binlog_stmt_parts_assoc (txt varchar(1000), line_count int, stmt_num int);
-
-set @stmt_count = 0;
-
-insert into binlog_stmt_parts_assoc
-  select txt, 
-         line_count, 
-         @stmt_count:= @stmt_count + stmt_boundary   # All rows from same stmt will
-                                                     # have same stmt_num
-    from binlog_stmt_parts_unassoc order by line_count;
-
-
-#select * from binlog_stmt_parts_assoc;
-
-create table binlog_stmts (txt varchar(1000), stmt_num int);
-
-insert into binlog_stmts 
-  select group_concat(right(txt,             # Combine rows in statment into 1
-                            length(txt) - 4) # Trim ### from line start
-                      order by line_count
-                      separator ' '), stmt_num
-    from binlog_stmt_parts_assoc
-    group by stmt_num;
-
-#select * from binlog_stmts;
-
-# Drop ndb_apply_status entries and sort by the statment 
-# text to get a deterministic order.
-#
-# Reasonable order would be sort by (PK-cols, stmt_num)
-# - Sorting by PK-cols would give determinism between events from different
-#   fragments
-# - Multiple ops on same pk would be in order of application
-#
-# However, as that's harder, and unnecessary given that we just want
-# deterministic output, not applicable SQL, we will just sort by
-# the statement text
-#
---enable_query_log
-select txt from binlog_stmts where txt not like '%ndb_apply_status%' order by txt;
-
---disable_query_log
-drop table raw_binlog_rows;
-drop table binlog_stmt_parts_unassoc;
-drop table binlog_stmt_parts_assoc;
-drop table binlog_stmts;
---enable_query_log
\ No newline at end of file
+--source suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts_basic.inc

=== added file 'mysql-test/suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts_basic.inc'
--- a/mysql-test/suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts_basic.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts_basic.inc	2010-11-08 12:19:51 +0000
@@ -0,0 +1,91 @@
+# 
+# Get the mysqlbinlog tool --verbose mode to dump the Binlog contents with
+# 'SQL' statements in triple-comments over multiple lines, e.g. :
+#
+### INSERT
+###  SET
+###  @1=1
+###  @2=2
+#
+# Then munch this output into single-line statements
+# e.g. :
+#  INSERT SET @1=1 @2=2
+#
+# Then filter + sort to get deterministic order independent of Ndb table 
+# fragmentation, epoch in ndb_apply_status etc.
+#
+
+--disable_query_log
+let $MYSQLD_DATADIR= `select @@datadir;`;
+--exec $MYSQL_BINLOG --verbose $MYSQLD_DATADIR/mysqld-bin.000001 > $MYSQLTEST_VARDIR/tmp/ndb_binlog_mysqlbinlog.sql
+
+create table raw_binlog_rows (txt varchar(1000));
+
+--eval load data local infile '$MYSQLTEST_VARDIR/tmp/ndb_binlog_mysqlbinlog.sql' into table raw_binlog_rows columns terminated by '\n';
+
+create table binlog_stmt_parts_unassoc (txt varchar(1000), line_count int, stmt_boundary int);
+
+set @line_count=0;
+set @stmt_boundary=0;
+
+# Use replace() here to get rid of any unwanted Windows
+# CRs
+insert into binlog_stmt_parts_unassoc
+  select replace(txt, '\r', ''),
+         @line_count:= @line_count + 1,  # So we can preserve order later
+         (txt like '%INSERT%' or         # Identify statement boundaries
+          txt like '%UPDATE%' or
+          txt like '%DELETE%')
+    from raw_binlog_rows
+    where
+      txt like '###%';                   # Discard non verbose output
+
+#select * from binlog_stmt_parts_unassoc;
+
+create table binlog_stmt_parts_assoc (txt varchar(1000), line_count int, stmt_num int);
+
+set @stmt_count = 0;
+
+insert into binlog_stmt_parts_assoc
+  select txt, 
+         line_count, 
+         @stmt_count:= @stmt_count + stmt_boundary   # All rows from same stmt will
+                                                     # have same stmt_num
+    from binlog_stmt_parts_unassoc order by line_count;
+
+
+#select * from binlog_stmt_parts_assoc;
+
+create table binlog_stmts (txt varchar(1000), stmt_num int);
+
+insert into binlog_stmts 
+  select group_concat(right(txt,             # Combine rows in statment into 1
+                            length(txt) - 4) # Trim ### from line start
+                      order by line_count
+                      separator ' '), stmt_num
+    from binlog_stmt_parts_assoc
+    group by stmt_num;
+
+#select * from binlog_stmts;
+
+# Drop ndb_apply_status entries and sort by the statment 
+# text to get a deterministic order.
+#
+# Reasonable order would be sort by (PK-cols, stmt_num)
+# - Sorting by PK-cols would give determinism between events from different
+#   fragments
+# - Multiple ops on same pk would be in order of application
+#
+# However, as that's harder, and unnecessary given that we just want
+# deterministic output, not applicable SQL, we will just sort by
+# the statement text
+#
+--enable_query_log
+--eval select txt from binlog_stmts where txt $binlog_condition order by txt
+
+--disable_query_log
+drop table raw_binlog_rows;
+drop table binlog_stmt_parts_unassoc;
+drop table binlog_stmt_parts_assoc;
+drop table binlog_stmts;
+--enable_query_log
\ No newline at end of file

=== added file 'mysql-test/suite/ndb_binlog/t/ndb_binlog_log_apply_status.test'
--- a/mysql-test/suite/ndb_binlog/t/ndb_binlog_log_apply_status.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb_binlog/t/ndb_binlog_log_apply_status.test	2010-11-08 12:19:51 +0000
@@ -0,0 +1,57 @@
+-- source include/have_ndb.inc
+-- source include/have_binlog_format_mixed_or_row.inc
+
+create table test.t1(a int primary key) engine=ndb;
+
+set global ndb_log_apply_status=Off;
+show variables like '%ndb_log_apply_status%';
+
+reset slave;
+reset master;
+--echo Should have empty apply status table
+select * from mysql.ndb_apply_status;
+
+--echo Dummy incoming ndb_apply_status updates, should not be logged
+begin;
+insert into mysql.ndb_apply_status values (555, 12345, 'binlog.000001', 20, 30);
+insert into mysql.ndb_apply_status values (666, 67890, 'binlog.000001', 50, 60);
+replace into test.t1 values (1); # So that epoch is non-empty
+commit;
+
+--echo Should not see ndb_apply_status updates in the Binlog
+
+# Synchronise with Binlog
+--disable_result_log
+show binlog events;
+--enable_result_log
+
+let $Binlog_condition= like '%binlog.000001%';
+--source suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts_basic.inc
+
+set global ndb_log_apply_status=On;
+show variables like '%ndb_log_apply_status%';
+
+reset slave;
+reset master;
+--echo Should have empty apply status table
+select * from mysql.ndb_apply_status;
+
+--echo Dummy incoming ndb_apply_status updates, should be logged
+begin;
+insert into mysql.ndb_apply_status values (555, 12345, 'binlog.000001', 20, 30);
+insert into mysql.ndb_apply_status values (666, 67890, 'binlog.000001', 50, 60);
+replace into test.t1 values (1); # So that epoch is non-empty
+commit;
+
+--echo Should see ndb_apply_status updates in the Binlog
+
+# Synchronise with Binlog
+--disable_result_log
+show binlog events;
+--enable_result_log
+
+let $Binlog_condition= like '%binlog.000001%';
+--source suite/ndb_binlog/t/ndb_binlog_get_binlog_stmts_basic.inc
+
+set global ndb_log_apply_status=Off;
+drop table test.t1;
\ No newline at end of file

=== added file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_break_3_chain.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_break_3_chain.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_break_3_chain.result	2010-11-08 12:19:51 +0000
@@ -0,0 +1,85 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+show variables like 'server_id';
+Variable_name	Value
+server_id	1
+reset master;
+select @cluster1_server_id:=(variable_value+0) 
+from information_schema.global_variables 
+where variable_name like 'server_id';
+@cluster1_server_id:=(variable_value+0)
+1
+show variables like 'server_id';
+Variable_name	Value
+server_id	2
+stop slave;
+reset master;
+reset slave;
+start slave;
+show variables like 'server_id';
+Variable_name	Value
+server_id	3
+stop slave;
+Warnings:
+Note	1255	Slave already has been stopped
+reset master;
+reset slave;
+start slave;
+First show replication 1->2->3
+use test;
+create table t1(a int primary key, b varchar(50)) engine=ndb;
+insert into t1 values (1,'Summertime');
+Cluster2 has insert and apply_status from Cluster1
+show variables like 'server_id';
+Variable_name	Value
+server_id	2
+select * from mysql.ndb_apply_status order by server_id;
+server_id	epoch	log_name	start_pos	end_pos
+1	#	#	#	#
+select * from test.t1;
+a	b
+1	Summertime
+Cluster3 has insert and apply_status from Cluster1+2
+show variables like 'server_id';
+Variable_name	Value
+server_id	3
+select * from mysql.ndb_apply_status order by server_id;
+server_id	epoch	log_name	start_pos	end_pos
+1	#	#	#	#
+2	#	#	#	#
+select * from test.t1;
+a	b
+1	Summertime
+Break Cluster3's link with Cluster2
+stop slave;
+Make further changes on Cluster1
+insert into test.t1 values (2, "The cotton is high");
+insert into test.t1 values (3, "Daddys rich");
+Show changes exist on Cluster2
+select * from test.t1 order by a;
+a	b
+1	Summertime
+2	The cotton is high
+3	Daddys rich
+Check data on Cluster3
+select * from test.t1 order by a;
+a	b
+1	Summertime
+Now change Cluster3 to skip-over Cluster2 and get binlog direct from Cluster1
+select * from mysql.ndb_apply_status order by server_id;
+server_id	epoch	log_name	start_pos	end_pos
+1	#	#	#	#
+2	#	#	#	#
+start slave;
+Now show that cluster 3 is successfully replicating from Cluster1
+select * from test.t1 order by a;
+a	b
+1	Summertime
+2	The cotton is high
+3	Daddys rich
+Clean up
+drop table test.t1;

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_circular.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_circular.result	2010-10-12 14:53:28 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_circular.result	2010-11-08 12:19:51 +0000
@@ -110,3 +110,70 @@ master-bin.000001	#	Write_rows	1	#	table
 master-bin.000001	#	Query	1	#	COMMIT
 STOP SLAVE;
 DROP TABLE t1;
+start slave;
+create table t1 (a int primary key, b int) engine=ndb;
+show variables like '%log_orig%';
+Variable_name	Value
+ndb_log_orig	ON
+'Master' has only slave's serverid entry 
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+server_id	log_name
+2	slave-bin.000001
+set global ndb_log_apply_status=On;
+show variables like 'ndb_log_apply_status';
+Variable_name	Value
+ndb_log_apply_status	ON
+'Slave' has only Master's serverid entry
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+server_id	log_name
+1	master-bin.000001
+'Slave' has following ndb_binlog_index entries
+select inserts, updates, deletes, schemaops, orig_server_id from mysql.ndb_binlog_index order by position;
+inserts	updates	deletes	schemaops	orig_server_id
+1	0	0	0	1
+1	0	0	0	2
+set global ndb_log_apply_status=On;
+show variables like 'ndb_log_apply_status';
+Variable_name	Value
+ndb_log_apply_status	ON
+stop slave;
+insert into t1 values (1,1);
+'Slave' still has only Master's serverid entry
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+server_id	log_name
+1	master-bin.000001
+show binlog events;
+'Slave' has following ndb_binlog_index entries
+select inserts, updates, deletes, schemaops, orig_server_id from mysql.ndb_binlog_index order by position;
+inserts	updates	deletes	schemaops	orig_server_id
+1	0	0	0	1
+1	0	0	0	2
+0	0	0	0	2
+1	0	0	0	1
+'Master' still has only Slave's serverid entry
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+server_id	log_name
+2	slave-bin.000001
+start slave;
+'Master' now has own serverid entry as well.
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+server_id	log_name
+1	master-bin.000001
+2	slave-bin.000001
+'Slave' still only has 'Master''s serverid entry
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+server_id	log_name
+1	master-bin.000001
+Now create event originating at Slave
+insert into t1 values (2,2);
+'Slave' now also has its own serverid entry
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+server_id	log_name
+1	master-bin.000001
+2	slave-bin.000001
+stop slave;
+set global ndb_log_apply_status=off;
+set global ndb_log_apply_status=off;
+stop slave;
+drop table t1;
+drop table t1;

=== added file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.cnf'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.cnf	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.cnf	2010-11-08 12:19:51 +0000
@@ -0,0 +1,118 @@
+!include include/default_mysqld.cnf
+!include include/default_ndbd.cnf
+
+[cluster_config.cluster1]
+NoOfReplicas=                  1
+ndbd=
+ndb_mgmd=
+mysqld=,
+ndbapi=,,,,,,,,,
+
+[cluster_config.cluster2]
+NoOfReplicas=                  1
+ndbd=
+ndb_mgmd=
+mysqld=
+ndbapi=,,,,
+
+[cluster_config.cluster3]
+NoOfReplicas=                  1
+ndbd=
+ndb_mgmd=
+mysqld=
+ndbapi=,,,,
+
+[mysqld]
+# Make all mysqlds use cluster
+ndbcluster
+ndb-wait-connected=20
+ndb-wait-setup=60
+ndb-cluster-connection-pool=3
+slave-allow-batching
+ndb-log-orig
+# Turn on bin logging
+log-bin=                       cluster1-bin
+# for performance reasons
+ndb-table-temporary=1
+ndb-log-apply-status
+ndb-extra-logging=99
+
+[mysqld.1.cluster1]
+
+[mysqld.1.cluster2]
+
+# Connect mysqld in the second cluster as save to  first mysqld
+# Hardcode the host to 127.0.0.1 until running on more
+# than one host and it probably need to be masked anyway
+# master-host=                @mysqld.1.#host
+master-host=                  127.0.0.1
+master-port=                  @mysqld.1.cluster1.port
+master-password=              @mysqld.1.cluster1.#password
+master-user=                  @mysqld.1.cluster1.#user
+master-connect-retry=         1
+
+log-bin=                      cluster2-bin
+relay-log=                    cluster2-relay-bin
+
+init-rpl-role=                slave
+log-slave-updates
+master-retry-count=           10
+ndb-log-apply-status
+
+# Values reported by slave when it connect to master
+# and shows up in SHOW SLAVE STATUS;
+report-host=                  127.0.0.1
+report-port=                  @mysqld.1.cluster2.port
+report-user=                  root
+
+loose-skip-innodb
+skip-slave-start
+
+# Directory where slaves find the dumps generated by "load data"
+# on the server. The path need to have constant length otherwise
+# test results will vary, thus a relative path is used.
+slave-load-tmpdir=            ../../../tmp
+
+rpl-recovery-rank=            @mysqld.1.cluster2.server-id
+
+[mysqld.1.cluster3]
+master-host=                  127.0.0.1
+master-port=                  @mysqld.1.cluster2.port
+master-password=              @mysqld.1.cluster2.#password
+master-user=                  @mysqld.1.cluster2.#user
+master-connect-retry=         1
+
+log-bin=                      cluster3-bin
+relay-log=                    cluster3-relay-bin
+
+init-rpl-role=                slave
+log-slave-updates
+master-retry-count=           10
+ndb-log-apply-status
+
+loose-skip-innodb
+skip-slave-start
+
+# Directory where slaves find the dumps generated by "load data"
+# on the server. The path need to have constant length otherwise
+# test results will vary, thus a relative path is used.
+slave-load-tmpdir=            ../../../tmp
+
+rpl-recovery-rank=            @mysqld.1.cluster3.server-id
+
+[ENV]
+NDB_CONNECTSTRING=            @mysql_cluster.cluster1.ndb_connectstring
+MASTER_MYPORT=                @mysqld.1.cluster1.port
+MASTER_MYPORT1=               @mysqld.2.cluster1.port
+CLUSTER1_HOST=                127.0.0.1
+CLUSTER1_MYPORT=              @mysqld.1.cluster1.port
+CLUSTER1_USER=                @mysqld.1.cluster1.#user
+
+NDB_CONNECTSTRING_SLAVE=      @mysql_cluster.cluster2.ndb_connectstring
+SLAVE_MYPORT=                 @mysqld.1.cluster2.port
+SLAVE_MYSOCK=                 @mysqld.1.cluster2.socket
+CLUSTER2_MYPORT=              @mysqld.1.cluster2.port
+
+CLUSTER3_MYPORT=              @mysqld.1.cluster3.port
+
+NDB_BACKUP_DIR=               @cluster_config.ndbd.1.cluster1.BackupDataDir

=== added file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_break_3_chain.test	2010-11-08 12:19:51 +0000
@@ -0,0 +1,113 @@
+--source include/have_ndb.inc
+--source suite/rpl_ndb/ndb_master-slave.inc
+
+connect (cluster1, 127.0.0.1,root,,test,$CLUSTER1_MYPORT);
+connect (cluster2, 127.0.0.1,root,,test,$CLUSTER2_MYPORT);
+connect (cluster3, 127.0.0.1,root,,test,$CLUSTER3_MYPORT);
+
+
+# set up replication 1->2->3
+--connection cluster1
+show variables like 'server_id';
+reset master;
+select @cluster1_server_id:=(variable_value+0) 
+       from information_schema.global_variables 
+       where variable_name like 'server_id';
+
+let $CLUSTER1_SERVER_ID= query_get_value('select @cluster1_server_id as v',v,1);
+
+--connection cluster2
+show variables like 'server_id';
+stop slave;
+reset master;
+reset slave;
+start slave;
+
+--connection cluster3
+show variables like 'server_id';
+stop slave;
+reset master;
+reset slave;
+start slave;
+
+--echo First show replication 1->2->3
+--connection cluster1
+use test;
+create table t1(a int primary key, b varchar(50)) engine=ndb;
+
+insert into t1 values (1,'Summertime');
+
+--sync_slave_with_master cluster2
+--echo Cluster2 has insert and apply_status from Cluster1
+show variables like 'server_id';
+--replace_column 2 # 3 # 4 # 5 #
+select * from mysql.ndb_apply_status order by server_id;
+select * from test.t1;
+
+--sync_slave_with_master cluster3
+--echo Cluster3 has insert and apply_status from Cluster1+2
+show variables like 'server_id';
+--replace_column 2 # 3 # 4 # 5 #
+select * from mysql.ndb_apply_status order by server_id;
+select * from test.t1;
+
+--echo Break Cluster3's link with Cluster2
+--connection cluster3
+stop slave;
+
+--echo Make further changes on Cluster1
+--connection cluster1
+insert into test.t1 values (2, "The cotton is high");
+insert into test.t1 values (3, "Daddys rich");
+
+--sync_slave_with_master cluster2
+--echo Show changes exist on Cluster2
+select * from test.t1 order by a;
+
+--echo Check data on Cluster3
+--connection cluster3
+select * from test.t1 order by a;
+
+--echo Now change Cluster3 to skip-over Cluster2 and get binlog direct from Cluster1
+
+--replace_column 2 # 3 # 4 # 5 #
+select * from mysql.ndb_apply_status order by server_id;
+
+--disable_query_log
+--disable_result_log
+eval select @binlog_file_name:=log_name from mysql.ndb_apply_status 
+            where server_id = $CLUSTER1_SERVER_ID;
+eval select @binlog_file_pos:=end_pos from mysql.ndb_apply_status
+            where server_id = $CLUSTER1_SERVER_ID;
+
+let $CLUSTER1_LOG_FILE= query_get_value('select @binlog_file_name as v', v, 1);
+let $CLUSTER1_LOG_POS= query_get_value('select @binlog_file_pos as v', v, 1);
+
+eval change master to master_host='$CLUSTER1_HOST', 
+                      master_port=$CLUSTER1_MYPORT, 
+                      master_user='$CLUSTER1_USER',
+                      master_log_file='$CLUSTER1_LOG_FILE',
+                      master_log_pos=$CLUSTER1_LOG_POS;
+--enable_query_log
+--enable_result_log
+
+start slave;
+
+--connection cluster1
+--sync_slave_with_master cluster3
+
+--echo Now show that cluster 3 is successfully replicating from Cluster1
+--connection cluster3
+select * from test.t1 order by a;
+
+
+--echo Clean up
+--connection cluster1
+drop table test.t1;
+
+--sync_slave_with_master cluster2
+--connection cluster1
+--sync_slave_with_master cluster3
+
+
+

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_circular.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_circular.test	2010-10-22 15:16:26 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_circular.test	2010-11-08 12:19:51 +0000
@@ -69,3 +69,82 @@ STOP SLAVE;
 --connection master
 DROP TABLE t1;
 -- sync_slave_with_master
+
+# Test ndb_log_apply_status option
+
+--connection master
+start slave;
+create table t1 (a int primary key, b int) engine=ndb;
+show variables like '%log_orig%';
+
+--echo 'Master' has only slave's serverid entry 
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+
+set global ndb_log_apply_status=On;
+show variables like 'ndb_log_apply_status';
+
+--connection slave
+--echo 'Slave' has only Master's serverid entry
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+--echo 'Slave' has following ndb_binlog_index entries
+select inserts, updates, deletes, schemaops, orig_server_id from mysql.ndb_binlog_index order by position;
+
+set global ndb_log_apply_status=On;
+show variables like 'ndb_log_apply_status';
+
+--connection master
+
+stop slave;
+insert into t1 values (1,1);
+--sync_slave_with_master
+
+--connection slave
+--echo 'Slave' still has only Master's serverid entry
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+
+--disable_result_log
+show binlog events;
+--enable_result_log
+--echo 'Slave' has following ndb_binlog_index entries
+select inserts, updates, deletes, schemaops, orig_server_id from mysql.ndb_binlog_index order by position;
+
+--connection master
+--echo 'Master' still has only Slave's serverid entry
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+
+start slave;
+--connection slave 
+--sync_slave_with_master master
+
+--connection master
+--echo 'Master' now has own serverid entry as well.
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+
+--connection slave
+--echo 'Slave' still only has 'Master''s serverid entry
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+--echo Now create event originating at Slave
+insert into t1 values (2,2);
+--sync_slave_with_master master
+
+--connection master
+--sync_slave_with_master slave
+
+--connection slave
+--echo 'Slave' now also has its own serverid entry
+select server_id, log_name from mysql.ndb_apply_status order by server_id;
+
+
+--connection master
+stop slave;
+set global ndb_log_apply_status=off;
+
+--connection slave
+set global ndb_log_apply_status=off;
+stop slave;
+
+drop table t1;
+
+--connection master
+
+drop table t1;

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2010-11-08 10:41:09 +0000
+++ b/sql/ha_ndbcluster.cc	2010-11-08 12:19:51 +0000
@@ -14545,6 +14545,17 @@ static MYSQL_SYSVAR_BOOL(
   0                                  /* default */
 );
 
+my_bool opt_ndb_log_apply_status;
+static MYSQL_SYSVAR_BOOL(
+  log_apply_status,                 /* name */
+  opt_ndb_log_apply_status,         /* var */
+  PLUGIN_VAR_OPCMDARG,
+  "Log ndb_apply_status updates from Master in the Binlog",
+  NULL,                             /* check func. */
+  NULL,                             /* update func. */
+  0                                 /* default */
+);
+
 
 static MYSQL_SYSVAR_STR(
   connectstring,                    /* name */
@@ -14611,6 +14622,7 @@ static struct st_mysql_sys_var* system_v
   MYSQL_SYSVAR(log_bin),
   MYSQL_SYSVAR(log_binlog_index),
   MYSQL_SYSVAR(log_empty_epochs),
+  MYSQL_SYSVAR(log_apply_status),
   MYSQL_SYSVAR(connectstring),
   MYSQL_SYSVAR(mgmd_host),
   MYSQL_SYSVAR(nodeid),

=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc	2010-10-22 12:35:05 +0000
+++ b/sql/ha_ndbcluster_binlog.cc	2010-11-08 12:19:51 +0000
@@ -42,6 +42,7 @@ extern my_bool opt_ndb_log_empty_epochs;
 extern my_bool opt_ndb_log_update_as_write;
 extern my_bool opt_ndb_log_updated_only;
 extern my_bool opt_ndb_log_binlog_index;
+extern my_bool opt_ndb_log_apply_status;
 extern ulong opt_ndb_extra_logging;
 extern ulong opt_server_id_mask;
 
@@ -3992,6 +3993,30 @@ ndbcluster_read_binlog_replication(THD *
   int error= 0;
   const char *error_str= "<none>";
 
+  /* Override for ndb_apply_status when logging */
+  if (opt_ndb_log_apply_status &&
+      do_set_binlog_flags)
+  {
+    if (strcmp(db, NDB_REP_DB) == 0 &&
+        strcmp(table_name, NDB_APPLY_TABLE) == 0)
+    {
+      /*
+        Ensure that we get all columns from ndb_apply_status updates
+        by forcing FULL event type
+        Also, ensure that ndb_apply_status events are always logged as 
+        WRITES.
+        This is needed so that received ndb_apply_status WRITES can be
+        cleanly propagated.
+      */
+      DBUG_PRINT("info", ("ndb_apply_status defaulting to FULL, USE_WRITE"));
+      sql_print_information("NDB : ndb-log-apply-status forcing "
+                            "%s.%s to FULL USE_WRITE",
+                            NDB_REP_DB, NDB_APPLY_TABLE);
+      set_binlog_flags(share, NBT_FULL);
+      DBUG_RETURN(0);
+    }
+  }
+
   ndb->setDatabaseName(ndb_rep_db);
   NDBDICT *dict= ndb->getDictionary();
   Ndb_table_guard ndbtab_g(dict, ndb_replication_table);
@@ -5372,7 +5397,8 @@ static int
 ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
                                     ndb_binlog_index_row **rows,
                                     injector::transaction &trans,
-                                    unsigned &trans_row_count)
+                                    unsigned &trans_row_count,
+                                    unsigned &trans_slave_row_count)
 {
   Ndb_event_data *event_data= (Ndb_event_data *) pOp->getCustomData();
   TABLE *table= event_data->table;
@@ -5381,15 +5407,49 @@ ndb_binlog_thread_handle_data_event(Ndb 
   {
     return 0;
   }
+
+  uint32 anyValue= pOp->getAnyValue();
+  if (ndbcluster_anyvalue_is_reserved(anyValue))
+  {
+    if (!ndbcluster_anyvalue_is_nologging(anyValue))
+      sql_print_warning("NDB: unknown value for binlog signalling 0x%X, "
+                        "event not logged",
+                        anyValue);
+    return 0;
+  }
+  uint32 originating_server_id= ndbcluster_anyvalue_get_serverid(anyValue);
+  bool log_this_slave_update = g_ndb_log_slave_updates;
+  bool count_this_event = true;
+
   if (share == ndb_apply_status_share)
   {
-    if (opt_ndb_log_orig)
+    /* 
+       Note that option values are read without synchronisation w.r.t. 
+       thread setting option variable or epoch boundaries.
+    */
+    if (opt_ndb_log_apply_status ||
+        opt_ndb_log_orig)
     {
+      Uint32 ndb_apply_status_logging_server_id= originating_server_id;
+      Uint32 ndb_apply_status_server_id= 0;
+      Uint64 ndb_apply_status_epoch= 0;
+      bool event_has_data = false;
+
       switch(pOp->getEventType())
       {
       case NDBEVENT::TE_INSERT:
         // fall through
       case NDBEVENT::TE_UPDATE:
+        event_has_data = true;
+        break;
+      case NDBEVENT::TE_DELETE:
+        break;
+      default:
+        /* We should REALLY never get here */
+        abort();
+      }
+      
+      if (likely( event_has_data ))
       {
         /* unpack data to fetch orig_server_id and orig_epoch */
         uint n_fields= table->s->fields;
@@ -5398,43 +5458,77 @@ ndb_binlog_thread_handle_data_event(Ndb 
         bitmap_init(&b, bitbuf, n_fields, FALSE);
         bitmap_set_all(&b);
         ndb_unpack_record(table, event_data->ndb_value[0], &b, table->record[0]);
-        /* store */
-        ndb_binlog_index_row *row= ndb_find_binlog_index_row
-          (rows, (uint)((Field_long *)table->field[0])->val_int(), 1);
-        row->orig_epoch= ((Field_longlong *)table->field[1])->val_int();
-        break;
-      }
-      case NDBEVENT::TE_DELETE:
-        break;
-      default:
-        /* We should REALLY never get here */
-        abort();
+        ndb_apply_status_server_id= (uint)((Field_long *)table->field[0])->val_int();
+        ndb_apply_status_epoch= ((Field_longlong *)table->field[1])->val_int();
+        
+        if (opt_ndb_log_apply_status)
+        {
+          /* 
+             Determine if event came from our immediate Master server
+             Ignore locally manually sourced and reserved events 
+          */
+          if ((ndb_apply_status_logging_server_id != 0) &&
+              (! ndbcluster_anyvalue_is_reserved(ndb_apply_status_logging_server_id)))
+          {
+            bool isFromImmediateMaster = (ndb_apply_status_server_id ==
+                                          ndb_apply_status_logging_server_id);
+            
+            if (isFromImmediateMaster)
+            {
+              /* 
+                 We log this event with our server-id so that it 
+                 propagates back to the originating Master (our
+                 immediate Master)
+              */
+              assert(ndb_apply_status_logging_server_id != ::server_id);
+              
+              originating_server_id= 0; /* Will be set to our ::serverid below */
+            }
+          }
+        }
+
+        if (opt_ndb_log_orig)
+        {
+          /* store */
+          ndb_binlog_index_row *row= ndb_find_binlog_index_row
+            (rows, ndb_apply_status_server_id, 1);
+          row->orig_epoch= ndb_apply_status_epoch;
+        }
       }
-    }
-    return 0;
-  }
+    } // opt_ndb_log_apply_status || opt_ndb_log_orig)
 
-  uint32 anyValue= pOp->getAnyValue();
-  if (ndbcluster_anyvalue_is_reserved(anyValue))
-  {
-    if (!ndbcluster_anyvalue_is_nologging(anyValue))
-      sql_print_warning("NDB: unknown value for binlog signalling 0x%X, "
-                        "event not logged",
-                        anyValue);
-    return 0;
+    if (opt_ndb_log_apply_status)
+    {
+      /* We are logging ndb_apply_status changes
+       * Don't count this event as making an epoch non-empty
+       * Log this event in the Binlog
+       */
+      count_this_event = false;
+      log_this_slave_update = true;
+    }
+    else
+    {
+      /* Not logging ndb_apply_status updates, discard this event now */
+      return 0;
+    }
   }
   
-  uint32 originating_server_id= ndbcluster_anyvalue_get_serverid(anyValue);
-
   if (originating_server_id == 0)
     originating_server_id= ::server_id;
-  else if (!g_ndb_log_slave_updates)
+  else 
   {
-    /*
-      This event comes from a slave applier since it has an originating
-      server id set. Since option to log slave updates is not set, skip it.
-    */
-    return 0;
+    /* Track that we received a replicated row event */
+    if (likely( count_this_event ))
+      trans_slave_row_count++;
+    
+    if (!log_this_slave_update)
+    {
+      /*
+        This event comes from a slave applier since it has an originating
+        server id set. Since option to log slave updates is not set, skip it.
+      */
+      return 0;
+    }
   }
 
   /* 
@@ -5481,8 +5575,11 @@ ndb_binlog_thread_handle_data_event(Ndb 
   switch(pOp->getEventType())
   {
   case NDBEVENT::TE_INSERT:
-    row->n_inserts++;
-    trans_row_count++;
+    if (likely( count_this_event ))
+    {
+      row->n_inserts++;
+      trans_row_count++;
+    }
     DBUG_PRINT("info", ("INSERT INTO %s.%s",
                         table->s->db.str, table->s->table_name.str));
     {
@@ -5504,8 +5601,11 @@ ndb_binlog_thread_handle_data_event(Ndb 
     }
     break;
   case NDBEVENT::TE_DELETE:
-    row->n_deletes++;
-    trans_row_count++;
+    if (likely( count_this_event ))
+    {
+      row->n_deletes++;
+      trans_row_count++;
+    }
     DBUG_PRINT("info",("DELETE FROM %s.%s",
                        table->s->db.str, table->s->table_name.str));
     {
@@ -5545,8 +5645,11 @@ ndb_binlog_thread_handle_data_event(Ndb 
     }
     break;
   case NDBEVENT::TE_UPDATE:
-    row->n_updates++;
-    trans_row_count++;
+    if (likely( count_this_event ))
+    {
+      row->n_updates++;
+      trans_row_count++;
+    }
     DBUG_PRINT("info", ("UPDATE %s.%s",
                         table->s->db.str, table->s->table_name.str));
     {
@@ -6275,6 +6378,7 @@ restart_cluster_failure:
       ndb_binlog_index_row *rows= &_row;
       injector::transaction trans;
       unsigned trans_row_count= 0;
+      unsigned trans_slave_row_count= 0;
       if (!pOp)
       {
         /*
@@ -6320,6 +6424,7 @@ restart_cluster_failure:
         DBUG_PRINT("info", ("Initializing transaction"));
         inj->new_trans(thd, &trans);
         trans_row_count= 0;
+        trans_slave_row_count= 0;
         // pass table map before epoch
         {
           Uint32 iter= 0;
@@ -6473,7 +6578,7 @@ restart_cluster_failure:
 #endif
           if ((unsigned) pOp->getEventType() <
               (unsigned) NDBEVENT::TE_FIRST_NON_DATA_EVENT)
-            ndb_binlog_thread_handle_data_event(i_ndb, pOp, &rows, trans, trans_row_count);
+            ndb_binlog_thread_handle_data_event(i_ndb, pOp, &rows, trans, trans_row_count, trans_slave_row_count);
           else
           {
             ndb_binlog_thread_handle_non_data_event(thd, pOp, *rows);
@@ -6512,17 +6617,34 @@ restart_cluster_failure:
 
         while (trans.good())
         {
-          if ((trans_row_count == 0) && !opt_ndb_log_empty_epochs)
+          if (!opt_ndb_log_empty_epochs)
           {
-            /* nothing to commit, rollback instead */
-            if (int r= trans.rollback())
+            /*
+              If 
+                - We did not add any 'real' rows to the Binlog AND
+                - We did not apply any slave row updates, only
+                  ndb_apply_status updates
+              THEN
+                Don't write the Binlog transaction which just
+                contains ndb_apply_status updates.
+                (For cicular rep with log_apply_status, ndb_apply_status
+                updates will propagate while some related, real update
+                is propagating)
+            */
+            if ((trans_row_count == 0) &&
+                (! (opt_ndb_log_apply_status &&
+                    trans_slave_row_count) ))
             {
-              sql_print_error("NDB Binlog: "
-                              "Error during ROLLBACK of GCI %u/%u. Error: %d",
-                              uint(gci >> 32), uint(gci), r);
-              /* TODO: Further handling? */
+              /* 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;
             }
-            break;
           }
       commit_to_binlog:
           thd->proc_info= "Committing events to binlog";

=== modified file 'storage/ndb/src/ndbapi/ndb_cluster_connection.cpp'
--- a/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp	2010-11-03 11:56:56 +0000
+++ b/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp	2010-11-08 12:22:42 +0000
@@ -204,7 +204,7 @@ Ndb_cluster_connection_impl::get_next_al
   if (tp == 0 || tp->ownId() == 0)
     return 0;
 
-  while (id = get_next_node(iter))
+  while ((id = get_next_node(iter)))
   {
     tp->lock_mutex();
     if (tp->get_node_alive(id) != 0)


Attachment: [text/bzr-bundle] bzr/frazer@mysql.com-20101108122710-jz63jis5tcv47f0o.bundle
Thread
bzr push into mysql-5.1-telco-7.1 branch (frazer:3960 to 3961) Frazer Clement8 Nov