List:Commits« Previous MessageNext Message »
From:Frazer Clement Date:October 3 2010 1:43am
Subject:bzr push into mysql-5.1-telco-7.0 branch (frazer:3820 to 3821)
View as plain text  
 3821 Frazer Clement	2010-10-03
      WL5353 Reflected GCI
      
      Test commit4 for CluB build/test cycle
      
      - Makefile modified to include missing files
      - Test output variations corrected

    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/include/
      mysql-test/suite/rpl_ndb/include/ndb_init_slave_counts.inc
      mysql-test/suite/rpl_ndb/include/ndb_slave_counts.inc
      mysql-test/suite/rpl_ndb/r/rpl_ndb_break_3_chain.result
      mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_epoch.result
      mysql-test/suite/rpl_ndb/r/rpl_ndb_init_rep_status.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
      mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch.cnf
      mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch.test
      mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch_1.inc
      mysql-test/suite/rpl_ndb/t/rpl_ndb_init_rep_status.test
    modified:
      mysql-test/Makefile.am
      mysql-test/include/ndb_conflict_info.inc
      mysql-test/include/ndb_conflict_info_init.inc
      mysql-test/suite/ndb/r/ndb_basic.result
      mysql-test/suite/ndb/r/ndb_native_default_support.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/r/rpl_ndb_conflict_max.result
      mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_max_delete_win.result
      mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_old.result
      mysql-test/suite/rpl_ndb/r/rpl_ndb_rep_error.result
      mysql-test/suite/rpl_ndb/t/rpl_ndb_circular.test
      mysql-test/suite/rpl_ndb/t/rpl_ndb_rep_error.test
      sql/ha_ndbcluster.cc
      sql/ha_ndbcluster.h
      sql/ha_ndbcluster_binlog.cc
      sql/ha_ndbcluster_binlog.h
      storage/ndb/include/kernel/AttributeHeader.hpp
      storage/ndb/include/kernel/kernel_types.h
      storage/ndb/include/kernel/signaldata/CreateTab.hpp
      storage/ndb/include/kernel/signaldata/CreateTable.hpp
      storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
      storage/ndb/include/ndb_version.h.in
      storage/ndb/include/ndbapi/NdbDictionary.hpp
      storage/ndb/include/ndbapi/NdbOperation.hpp
      storage/ndb/include/ndbapi/NdbTransaction.hpp
      storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
      storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
      storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
      storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
      storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
      storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
      storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
      storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
      storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
      storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
      storage/ndb/src/kernel/vm/LongSignal.cpp
      storage/ndb/src/kernel/vm/LongSignalImpl.hpp
      storage/ndb/src/kernel/vm/SimulatedBlock.cpp
      storage/ndb/src/kernel/vm/SimulatedBlock.hpp
      storage/ndb/src/ndbapi/NdbDictionary.cpp
      storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
      storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
      storage/ndb/src/ndbapi/NdbOperationExec.cpp
      storage/ndb/src/ndbapi/NdbTransaction.cpp
      storage/ndb/src/ndbapi/ndberror.c
      storage/ndb/test/include/HugoOperations.hpp
      storage/ndb/test/include/HugoTransactions.hpp
      storage/ndb/test/ndbapi/testRestartGci.cpp
      storage/ndb/test/src/HugoOperations.cpp
      storage/ndb/test/src/HugoTransactions.cpp
      storage/ndb/test/src/NDBT_Table.cpp
      storage/ndb/test/tools/hugoPkUpdate.cpp
      storage/ndb/tools/select_all.cpp
 3820 Jonas Oreland	2010-10-01
      ndb - move ArbitMgr-object from TransporterFacade to ClusterMgr

    modified:
      storage/ndb/src/ndbapi/ClusterMgr.cpp
      storage/ndb/src/ndbapi/ClusterMgr.hpp
      storage/ndb/src/ndbapi/TransporterFacade.cpp
      storage/ndb/src/ndbapi/TransporterFacade.hpp
=== modified file 'mysql-test/Makefile.am'
--- a/mysql-test/Makefile.am	2010-08-23 14:33:15 +0000
+++ b/mysql-test/Makefile.am	2010-10-03 01:41:32 +0000
@@ -106,7 +106,7 @@ TEST_DIRS = t r include std_data std_dat
 	suite/ndb_big \
 	suite/ndb_binlog suite/ndb_binlog/t suite/ndb_binlog/r \
 	suite/ndb_team suite/ndb_team/t suite/ndb_team/r \
-	suite/rpl_ndb suite/rpl_ndb/t suite/rpl_ndb/r \
+	suite/rpl_ndb suite/rpl_ndb/t suite/rpl_ndb/r suite/rpl_ndb/include \
 	suite/parts suite/parts/t suite/parts/r suite/parts/inc \
 	suite/innodb suite/innodb/t suite/innodb/r suite/innodb/include \
         suite/innodb_plugin suite/innodb_plugin/t suite/innodb_plugin/r \

=== modified file 'mysql-test/include/ndb_conflict_info.inc'
--- a/mysql-test/include/ndb_conflict_info.inc	2009-02-16 15:54:40 +0000
+++ b/mysql-test/include/ndb_conflict_info.inc	2010-10-03 01:41:32 +0000
@@ -1,5 +1,7 @@
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
 --replace_column 3 # 5 # 6 #
 --error 0,1146
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;

=== modified file 'mysql-test/include/ndb_conflict_info_init.inc'
--- a/mysql-test/include/ndb_conflict_info_init.inc	2009-02-16 15:54:40 +0000
+++ b/mysql-test/include/ndb_conflict_info_init.inc	2010-10-03 01:41:32 +0000
@@ -2,6 +2,8 @@
 --disable_result_log
 SELECT @init_ndb_conflict_fn_max:=(VARIABLE_VALUE+0) FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 SELECT @init_ndb_conflict_fn_old:=(VARIABLE_VALUE+0) FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+SELECT @init_ndb_conflict_fn_max_del_win:=(VARIABLE_VALUE+0) FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+SELECT @init_ndb_conflict_fn_epoch:=(VARIABLE_VALUE+0) FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
 --error 0,1146
 DELETE FROM `t1$EX`;
 --enable_query_log

=== modified file 'mysql-test/suite/ndb/r/ndb_basic.result'
--- a/mysql-test/suite/ndb/r/ndb_basic.result	2010-06-16 20:49:05 +0000
+++ b/mysql-test/suite/ndb/r/ndb_basic.result	2010-10-03 01:41:32 +0000
@@ -21,12 +21,21 @@ Ndb_pruned_scan_count	#
 Ndb_cluster_connection_pool	#
 Ndb_conflict_fn_max	#
 Ndb_conflict_fn_old	#
+Ndb_conflict_fn_max_del_win	#
+Ndb_conflict_fn_epoch	#
+Ndb_slave_max_replicated_epoch	#
+Ndb_slave_write_row_count	#
+Ndb_slave_update_row_count	#
+Ndb_slave_delete_row_count	#
+Ndb_slave_execute_count	#
+Ndb_slave_commit_count	#
 SHOW GLOBAL VARIABLES LIKE 'ndb\_%';
 Variable_name	Value
 ndb_autoincrement_prefetch_sz	#
 ndb_batch_size	#
 ndb_cache_check_time	#
 ndb_cluster_connection_pool	#
+ndb_cluster_server_ids	#
 ndb_connectstring	#
 ndb_distribution	#
 ndb_extra_logging	#
@@ -34,6 +43,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	#

=== modified file 'mysql-test/suite/ndb/r/ndb_native_default_support.result'
--- a/mysql-test/suite/ndb/r/ndb_native_default_support.result	2010-08-19 13:35:45 +0000
+++ b/mysql-test/suite/ndb/r/ndb_native_default_support.result	2010-10-03 01:41:32 +0000
@@ -140,6 +140,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 i Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
@@ -178,6 +180,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 pk Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
@@ -246,6 +250,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 i Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
@@ -283,6 +289,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 pk Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
@@ -360,6 +368,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 i Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
@@ -450,6 +460,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 i Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR
@@ -497,6 +509,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -538,6 +552,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -587,6 +603,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -630,6 +648,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -672,6 +692,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -714,6 +736,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -758,6 +782,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -805,6 +831,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -847,6 +875,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -891,6 +921,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -936,6 +968,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -985,6 +1019,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -1028,6 +1064,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -1070,6 +1108,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -1112,6 +1152,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -1154,6 +1196,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -1198,6 +1242,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -1245,6 +1291,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
@@ -1333,6 +1381,8 @@ Row GCI: 1
 SingleUserMode: 0
 ForceVarPart: 1
 FragmentCount: 2
+ExtraRowGciBits: 0
+ExtraRowAuthorBits: 0
 TableStatus: Retrieved
 -- Attributes -- 
 i Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY AUTO_INCR

=== 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-10-03 01:41:32 +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-10-03 01:41:32 +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-10-03 01:41:32 +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-10-03 01:41:32 +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 directory 'mysql-test/suite/rpl_ndb/include'
=== added file 'mysql-test/suite/rpl_ndb/include/ndb_init_slave_counts.inc'
--- a/mysql-test/suite/rpl_ndb/include/ndb_init_slave_counts.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/include/ndb_init_slave_counts.inc	2010-10-03 01:41:32 +0000
@@ -0,0 +1,9 @@
+--disable_query_log
+--disable_result_log
+select @ndb_slave_init_write_row_count:=VARIABLE_VALUE from information_schema.session_status where variable_name like 'NDB_SLAVE_WRITE_ROW_COUNT';
+select @ndb_slave_init_update_row_count:=VARIABLE_VALUE from information_schema.session_status where variable_name like 'NDB_SLAVE_UPDATE_ROW_COUNT';
+select @ndb_slave_init_delete_row_count:=VARIABLE_VALUE from information_schema.session_status where variable_name like 'NDB_SLAVE_DELETE_ROW_COUNT';
+select @ndb_slave_init_execute_count:=VARIABLE_VALUE from information_schema.session_status where variable_name like 'NDB_SLAVE_EXECUTE_COUNT';
+select @ndb_slave_init_commit_count:=VARIABLE_VALUE from information_schema.session_status where variable_name like 'NDB_SLAVE_COMMIT_COUNT';
+--enable_query_log
+--enable_result_log

=== added file 'mysql-test/suite/rpl_ndb/include/ndb_slave_counts.inc'
--- a/mysql-test/suite/rpl_ndb/include/ndb_slave_counts.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/include/ndb_slave_counts.inc	2010-10-03 01:41:32 +0000
@@ -0,0 +1,7 @@
+--disable_query_log
+select @ndb_slave_write_row_count:=VARIABLE_VALUE-@ndb_slave_init_write_row_count as ndb_slave_write_row_count from information_schema.session_status where variable_name like 'NDB_SLAVE_WRITE_ROW_COUNT';
+select @ndb_slave_update_row_count:=VARIABLE_VALUE-@ndb_slave_init_update_row_count as ndb_slave_update_row_count from information_schema.session_status where variable_name like 'NDB_SLAVE_UPDATE_ROW_COUNT';
+select @ndb_slave_delete_row_count:=VARIABLE_VALUE-@ndb_slave_init_delete_row_count as ndb_slave_delete_row_count from information_schema.session_status where variable_name like 'NDB_SLAVE_DELETE_ROW_COUNT';
+select @ndb_slave_execute_count:=VARIABLE_VALUE-@ndb_slave_init_execute_count as ndb_slave_execute_count from information_schema.session_status where variable_name like 'NDB_SLAVE_EXECUTE_COUNT';
+select @ndb_slave_commit_count:=VARIABLE_VALUE-@ndb_slave_init_commit_count as ndb_slave_commit_count from information_schema.session_status where variable_name like 'NDB_SLAVE_COMMIT_COUNT';
+--enable_query_log

=== 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-10-03 01:41:32 +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;
+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	2009-12-16 14:19:40 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_circular.result	2010-10-03 01:41:32 +0000
@@ -150,3 +150,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/r/rpl_ndb_conflict_epoch.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_epoch.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_epoch.result	2010-10-03 01:41:32 +0000
@@ -0,0 +1,2876 @@
+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;
+Setup circular replication
+RESET MASTER;
+select @slave_server_id:=(variable_value+0) 
+from information_schema.global_variables 
+where variable_name like 'server_id';
+@slave_server_id:=(variable_value+0)
+3
+CHANGE MASTER TO master_host="127.0.0.1",master_port=SLAVE_PORT,master_user="root";
+START SLAVE;
+select @master_server_id:=(variable_value+0) 
+from information_schema.global_variables 
+where variable_name like 'server_id';
+@master_server_id:=(variable_value+0)
+1
+Setup ndb_replication and t1 exceptions table
+Populate ndb_replication table as necessary
+-- 0 extra gci bits
+replace into mysql.ndb_replication values 
+("test", "t1", 3, 7, NULL), 
+("test", "t1", 1, 7, "NDB$EPOCH(0)");
+create table `test`.`t1$EX`
+  (server_id int unsigned,
+master_server_id int unsigned,
+master_epoch bigint unsigned,
+count int unsigned,
+a int not null,
+d int,
+primary key(server_id, master_server_id, master_epoch, count)) engine ndb;
+Create table
+create table test.t1(a int primary key, b varchar(255)) engine = ndb;
+Create other table
+create table test.t2(a int primary key, b int) engine = ndb;
+----------------------------------
+Test 1 : Basic two-way replication
+----------------------------------
+insert into test.t1 values (1, "Metropole");
+-- Give time for a new epoch on the Master
+-- Insert something to ensure the new epoch is noticed
+replace into test.t2 values (2, 1);
+-- Flushed to slave
+select * from test.t1 order by a;
+a	b
+1	Metropole
+-- Flushed back to Master
+select * from test.t1 order by a;
+a	b
+1	Metropole
+-- Now update data on slave
+update test.t1 set b="Favorit" where a=1;
+-- Now check data on master
+select * from test.t1 order by a;
+a	b
+1	Favorit
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Now perform multiple consecutive updates on the slave
+update test.t1 set b="Elephant house" where a=1;
+update test.t1 set b="Beach house" where a=1;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-- Now check they've applied on the master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+--------------------------------------------
+Test 2 : Normal Insert from Secondary Master
+--------------------------------------------
+-- Insert a new row on the Slave
+insert into test.t1 values (2, "Forrest");
+-- Check it exists on the Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Forrest
+-- Update from the slave
+update test.t1 set b="Reds" where a=2;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Reds
+delete from test.t1 where a=2;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-------------------------------
+Test 3 : Insert-Insert conflict
+-------------------------------
+stop slave;
+-- Insert a row on the Primary Master
+insert into test.t1 values (2, "Loopy Lornas");
+-- Insert a row on the secondary Master
+insert into test.t1 values (2, "Cloisters");
+-- Examine data on Primary Master (should be unaffected)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Loopy Lornas
+-- Examine conflict indicators on Primary Master
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+1
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on isolated secondary Master (should be as-set)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Cloisters
+-- Restart secondary Masters slave
+start slave;
+-- Reexamine secondary Master's data (should be same as Primary Masters)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Loopy Lornas
+-------------------------------
+Test 4 : Update-Update conflict
+-------------------------------
+-- Stop replication to secondary master
+stop slave;
+-- Update row on Primary Master
+update test.t1 set b="Peters Yard" where a=2;
+-- Show data on Primary Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+1
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Update row on Secondary Master
+update test.t1 set b="Toast" where a=2;
+-- Examine data on Primary Master - should be unaffected
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+2
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Check data on secondary - should be as set
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Toast
+-- Now restart slave, will re-align row
+start slave;
+-- Check that Secondary is re-aligned
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+-------------------------------
+Test 5 : Update-Delete conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Update on Primary Master
+update test.t1 set b="Pear tree" where a = 2;
+-- Delete on Secondary Master
+delete from test.t1 where a = 2;
+-- Examine data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Pear tree
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+3
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, still missing
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, aligned with Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Pear tree
+-------------------------------
+Test 6 : Delete-Update conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Delete on Primary Master
+delete from test.t1 where a=2;
+-- Update on Secondary Master
+update test.t1 set b="Black pig" where a=2;
+-- Examine data on Primary Master, should be unaffected (no row)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+4
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, should be as inserted
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Black pig
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, aligned with Master (deleted)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-------------------------------
+Test 7 : Delete-Delete conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Delete on Primary Master
+delete from test.t1 where a=1;
+-- Delete on Secondary Master
+delete from test.t1 where a=1;
+-- Examine data on Primary Master, no row
+select * from test.t1 order by a;
+a	b
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+5
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, no row
+select * from test.t1 order by a;
+a	b
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, no row
+select * from test.t1 order by a;
+a	b
+------------------------------------------------
+Test 8 : Delete-Delete, Insert conflict exposure
+------------------------------------------------
+-- Insert a row on Secondary Master
+insert into test.t1 values (3, "Espy");
+-- Check it's present on Primary Master
+select * from test.t1 order by a;
+a	b
+3	Espy
+-- Stop replication in both directions
+stop slave;
+stop slave;
+-- Delete row from both clusters
+delete from test.t1 where a=3;
+delete from test.t1 where a=3;
+-- Follow up with Insert from Secondary master
+insert into test.t1 values (3, "Dalriada");
+-- Restart replication in both directions
+start slave;
+start slave;
+-- Check data on both sites - diverged
+-- Secondary master :
+select * from test.t1 order by a;
+a	b
+-- Primary master :
+select * from test.t1 order by a;
+a	b
+3	Dalriada
+--Remove extra row
+delete from test.t1 where a=3;
+-- Note that Delete-Delete conflict detected below
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+6
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+------------------------------------------------
+Test 9 : Insert, Insert-Update-Delete conflict
+------------------------------------------------
+-- Stop replication on Secondary Master
+stop slave;
+-- Insert row on Primary Master
+insert into test.t1 values (4, "Haymarket");
+-- Insert row on Secondary Master
+insert into test.t1 values (4, "Outhouse");
+-- Update row on Secondary Master
+update test.t1 set b="Mathers" where a = 4;
+-- Delete row on Secondary Master
+delete from test.t1 where a=4;
+-- Examine data (none) on Secondary Master
+select * from test.t1 order by a;
+a	b
+-- Examine data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+4	Haymarket
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+9
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master (none)
+select * from test.t1 order by a;
+a	b
+-- Restart Secondary Master's slave
+start slave;
+-- Check data on Secondary Master, should be same as Primary Master
+select * from test.t1;
+a	b
+4	Haymarket
+------------------------------------------------
+Test 10 : Update, Delete-Insert-Update conflict  
+------------------------------------------------
+-- Stop replication on Secondary Master 
+stop slave;
+-- Update row on Primary Master
+update test.t1 set b="Blind poet" where a=4;
+-- Delete row on Secondary Master
+delete from test.t1 where a=4;
+-- Insert row on Secondary Master
+insert into test.t1 values (4, "Drouthy Neebors");
+-- Update row on Secondary Master
+update test.t1 set b="The Tankard" where a=4;
+-- Check data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Check data on Secondary Master, as set
+select * from test.t1 order by a;
+a	b
+4	The Tankard
+-- Restart Secondary Master slave
+start slave;
+-- Check data on Secondary Master - should be as Primary
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+------------------------------------------------------------------------
+Test 11 : Test Secondary insert-update-delete accepted
+------------------------------------------------------------------------
+Insert row on Secondary
+insert into test.t1 values (5, "Minders");
+Update row on Secondary
+update test.t1 set b="Southsider" where a=5;
+Delete row on Secondary
+delete from test.t1 where a=5;
+Check data on Primary, should be none.  No new conflicts
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+drop table test.t1;
+drop table test.t2;
+drop table test.t1$EX;
+Populate ndb_replication table as necessary
+-- 1 extra gci bits
+replace into mysql.ndb_replication values 
+("test", "t1", 3, 7, NULL), 
+("test", "t1", 1, 7, "NDB$EPOCH(1)");
+create table `test`.`t1$EX`
+  (server_id int unsigned,
+master_server_id int unsigned,
+master_epoch bigint unsigned,
+count int unsigned,
+a int not null,
+d int,
+primary key(server_id, master_server_id, master_epoch, count)) engine ndb;
+Create table
+create table test.t1(a int primary key, b varchar(255)) engine = ndb;
+Create other table
+create table test.t2(a int primary key, b int) engine = ndb;
+----------------------------------
+Test 1 : Basic two-way replication
+----------------------------------
+insert into test.t1 values (1, "Metropole");
+-- Give time for a new epoch on the Master
+-- Insert something to ensure the new epoch is noticed
+replace into test.t2 values (2, 1);
+-- Flushed to slave
+select * from test.t1 order by a;
+a	b
+1	Metropole
+-- Flushed back to Master
+select * from test.t1 order by a;
+a	b
+1	Metropole
+-- Now update data on slave
+update test.t1 set b="Favorit" where a=1;
+-- Now check data on master
+select * from test.t1 order by a;
+a	b
+1	Favorit
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Now perform multiple consecutive updates on the slave
+update test.t1 set b="Elephant house" where a=1;
+update test.t1 set b="Beach house" where a=1;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-- Now check they've applied on the master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+--------------------------------------------
+Test 2 : Normal Insert from Secondary Master
+--------------------------------------------
+-- Insert a new row on the Slave
+insert into test.t1 values (2, "Forrest");
+-- Check it exists on the Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Forrest
+-- Update from the slave
+update test.t1 set b="Reds" where a=2;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Reds
+delete from test.t1 where a=2;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-------------------------------
+Test 3 : Insert-Insert conflict
+-------------------------------
+stop slave;
+-- Insert a row on the Primary Master
+insert into test.t1 values (2, "Loopy Lornas");
+-- Insert a row on the secondary Master
+insert into test.t1 values (2, "Cloisters");
+-- Examine data on Primary Master (should be unaffected)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Loopy Lornas
+-- Examine conflict indicators on Primary Master
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+1
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on isolated secondary Master (should be as-set)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Cloisters
+-- Restart secondary Masters slave
+start slave;
+-- Reexamine secondary Master's data (should be same as Primary Masters)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Loopy Lornas
+-------------------------------
+Test 4 : Update-Update conflict
+-------------------------------
+-- Stop replication to secondary master
+stop slave;
+-- Update row on Primary Master
+update test.t1 set b="Peters Yard" where a=2;
+-- Show data on Primary Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+1
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Update row on Secondary Master
+update test.t1 set b="Toast" where a=2;
+-- Examine data on Primary Master - should be unaffected
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+2
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Check data on secondary - should be as set
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Toast
+-- Now restart slave, will re-align row
+start slave;
+-- Check that Secondary is re-aligned
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+-------------------------------
+Test 5 : Update-Delete conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Update on Primary Master
+update test.t1 set b="Pear tree" where a = 2;
+-- Delete on Secondary Master
+delete from test.t1 where a = 2;
+-- Examine data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Pear tree
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+3
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, still missing
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, aligned with Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Pear tree
+-------------------------------
+Test 6 : Delete-Update conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Delete on Primary Master
+delete from test.t1 where a=2;
+-- Update on Secondary Master
+update test.t1 set b="Black pig" where a=2;
+-- Examine data on Primary Master, should be unaffected (no row)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+4
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, should be as inserted
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Black pig
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, aligned with Master (deleted)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-------------------------------
+Test 7 : Delete-Delete conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Delete on Primary Master
+delete from test.t1 where a=1;
+-- Delete on Secondary Master
+delete from test.t1 where a=1;
+-- Examine data on Primary Master, no row
+select * from test.t1 order by a;
+a	b
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+5
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, no row
+select * from test.t1 order by a;
+a	b
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, no row
+select * from test.t1 order by a;
+a	b
+------------------------------------------------
+Test 8 : Delete-Delete, Insert conflict exposure
+------------------------------------------------
+-- Insert a row on Secondary Master
+insert into test.t1 values (3, "Espy");
+-- Check it's present on Primary Master
+select * from test.t1 order by a;
+a	b
+3	Espy
+-- Stop replication in both directions
+stop slave;
+stop slave;
+-- Delete row from both clusters
+delete from test.t1 where a=3;
+delete from test.t1 where a=3;
+-- Follow up with Insert from Secondary master
+insert into test.t1 values (3, "Dalriada");
+-- Restart replication in both directions
+start slave;
+start slave;
+-- Check data on both sites - diverged
+-- Secondary master :
+select * from test.t1 order by a;
+a	b
+-- Primary master :
+select * from test.t1 order by a;
+a	b
+3	Dalriada
+--Remove extra row
+delete from test.t1 where a=3;
+-- Note that Delete-Delete conflict detected below
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+6
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+------------------------------------------------
+Test 9 : Insert, Insert-Update-Delete conflict
+------------------------------------------------
+-- Stop replication on Secondary Master
+stop slave;
+-- Insert row on Primary Master
+insert into test.t1 values (4, "Haymarket");
+-- Insert row on Secondary Master
+insert into test.t1 values (4, "Outhouse");
+-- Update row on Secondary Master
+update test.t1 set b="Mathers" where a = 4;
+-- Delete row on Secondary Master
+delete from test.t1 where a=4;
+-- Examine data (none) on Secondary Master
+select * from test.t1 order by a;
+a	b
+-- Examine data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+4	Haymarket
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+9
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master (none)
+select * from test.t1 order by a;
+a	b
+-- Restart Secondary Master's slave
+start slave;
+-- Check data on Secondary Master, should be same as Primary Master
+select * from test.t1;
+a	b
+4	Haymarket
+------------------------------------------------
+Test 10 : Update, Delete-Insert-Update conflict  
+------------------------------------------------
+-- Stop replication on Secondary Master 
+stop slave;
+-- Update row on Primary Master
+update test.t1 set b="Blind poet" where a=4;
+-- Delete row on Secondary Master
+delete from test.t1 where a=4;
+-- Insert row on Secondary Master
+insert into test.t1 values (4, "Drouthy Neebors");
+-- Update row on Secondary Master
+update test.t1 set b="The Tankard" where a=4;
+-- Check data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Check data on Secondary Master, as set
+select * from test.t1 order by a;
+a	b
+4	The Tankard
+-- Restart Secondary Master slave
+start slave;
+-- Check data on Secondary Master - should be as Primary
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+------------------------------------------------------------------------
+Test 11 : Test Secondary insert-update-delete accepted
+------------------------------------------------------------------------
+Insert row on Secondary
+insert into test.t1 values (5, "Minders");
+Update row on Secondary
+update test.t1 set b="Southsider" where a=5;
+Delete row on Secondary
+delete from test.t1 where a=5;
+Check data on Primary, should be none.  No new conflicts
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+drop table test.t1;
+drop table test.t2;
+drop table test.t1$EX;
+Populate ndb_replication table as necessary
+-- 31 extra gci bits
+replace into mysql.ndb_replication values 
+("test", "t1", 3, 7, NULL), 
+("test", "t1", 1, 7, "NDB$EPOCH(31)");
+create table `test`.`t1$EX`
+  (server_id int unsigned,
+master_server_id int unsigned,
+master_epoch bigint unsigned,
+count int unsigned,
+a int not null,
+d int,
+primary key(server_id, master_server_id, master_epoch, count)) engine ndb;
+Create table
+create table test.t1(a int primary key, b varchar(255)) engine = ndb;
+Create other table
+create table test.t2(a int primary key, b int) engine = ndb;
+----------------------------------
+Test 1 : Basic two-way replication
+----------------------------------
+insert into test.t1 values (1, "Metropole");
+-- Give time for a new epoch on the Master
+-- Insert something to ensure the new epoch is noticed
+replace into test.t2 values (2, 1);
+-- Flushed to slave
+select * from test.t1 order by a;
+a	b
+1	Metropole
+-- Flushed back to Master
+select * from test.t1 order by a;
+a	b
+1	Metropole
+-- Now update data on slave
+update test.t1 set b="Favorit" where a=1;
+-- Now check data on master
+select * from test.t1 order by a;
+a	b
+1	Favorit
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Now perform multiple consecutive updates on the slave
+update test.t1 set b="Elephant house" where a=1;
+update test.t1 set b="Beach house" where a=1;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-- Now check they've applied on the master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+--------------------------------------------
+Test 2 : Normal Insert from Secondary Master
+--------------------------------------------
+-- Insert a new row on the Slave
+insert into test.t1 values (2, "Forrest");
+-- Check it exists on the Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Forrest
+-- Update from the slave
+update test.t1 set b="Reds" where a=2;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Reds
+delete from test.t1 where a=2;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-------------------------------
+Test 3 : Insert-Insert conflict
+-------------------------------
+stop slave;
+-- Insert a row on the Primary Master
+insert into test.t1 values (2, "Loopy Lornas");
+-- Insert a row on the secondary Master
+insert into test.t1 values (2, "Cloisters");
+-- Examine data on Primary Master (should be unaffected)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Loopy Lornas
+-- Examine conflict indicators on Primary Master
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+1
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on isolated secondary Master (should be as-set)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Cloisters
+-- Restart secondary Masters slave
+start slave;
+-- Reexamine secondary Master's data (should be same as Primary Masters)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Loopy Lornas
+-------------------------------
+Test 4 : Update-Update conflict
+-------------------------------
+-- Stop replication to secondary master
+stop slave;
+-- Update row on Primary Master
+update test.t1 set b="Peters Yard" where a=2;
+-- Show data on Primary Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+1
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Update row on Secondary Master
+update test.t1 set b="Toast" where a=2;
+-- Examine data on Primary Master - should be unaffected
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+2
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Check data on secondary - should be as set
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Toast
+-- Now restart slave, will re-align row
+start slave;
+-- Check that Secondary is re-aligned
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+-------------------------------
+Test 5 : Update-Delete conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Update on Primary Master
+update test.t1 set b="Pear tree" where a = 2;
+-- Delete on Secondary Master
+delete from test.t1 where a = 2;
+-- Examine data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Pear tree
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+3
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, still missing
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, aligned with Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Pear tree
+-------------------------------
+Test 6 : Delete-Update conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Delete on Primary Master
+delete from test.t1 where a=2;
+-- Update on Secondary Master
+update test.t1 set b="Black pig" where a=2;
+-- Examine data on Primary Master, should be unaffected (no row)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+4
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, should be as inserted
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Black pig
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, aligned with Master (deleted)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-------------------------------
+Test 7 : Delete-Delete conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Delete on Primary Master
+delete from test.t1 where a=1;
+-- Delete on Secondary Master
+delete from test.t1 where a=1;
+-- Examine data on Primary Master, no row
+select * from test.t1 order by a;
+a	b
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+5
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, no row
+select * from test.t1 order by a;
+a	b
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, no row
+select * from test.t1 order by a;
+a	b
+------------------------------------------------
+Test 8 : Delete-Delete, Insert conflict exposure
+------------------------------------------------
+-- Insert a row on Secondary Master
+insert into test.t1 values (3, "Espy");
+-- Check it's present on Primary Master
+select * from test.t1 order by a;
+a	b
+3	Espy
+-- Stop replication in both directions
+stop slave;
+stop slave;
+-- Delete row from both clusters
+delete from test.t1 where a=3;
+delete from test.t1 where a=3;
+-- Follow up with Insert from Secondary master
+insert into test.t1 values (3, "Dalriada");
+-- Restart replication in both directions
+start slave;
+start slave;
+-- Check data on both sites - diverged
+-- Secondary master :
+select * from test.t1 order by a;
+a	b
+-- Primary master :
+select * from test.t1 order by a;
+a	b
+3	Dalriada
+--Remove extra row
+delete from test.t1 where a=3;
+-- Note that Delete-Delete conflict detected below
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+6
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+------------------------------------------------
+Test 9 : Insert, Insert-Update-Delete conflict
+------------------------------------------------
+-- Stop replication on Secondary Master
+stop slave;
+-- Insert row on Primary Master
+insert into test.t1 values (4, "Haymarket");
+-- Insert row on Secondary Master
+insert into test.t1 values (4, "Outhouse");
+-- Update row on Secondary Master
+update test.t1 set b="Mathers" where a = 4;
+-- Delete row on Secondary Master
+delete from test.t1 where a=4;
+-- Examine data (none) on Secondary Master
+select * from test.t1 order by a;
+a	b
+-- Examine data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+4	Haymarket
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+9
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master (none)
+select * from test.t1 order by a;
+a	b
+-- Restart Secondary Master's slave
+start slave;
+-- Check data on Secondary Master, should be same as Primary Master
+select * from test.t1;
+a	b
+4	Haymarket
+------------------------------------------------
+Test 10 : Update, Delete-Insert-Update conflict  
+------------------------------------------------
+-- Stop replication on Secondary Master 
+stop slave;
+-- Update row on Primary Master
+update test.t1 set b="Blind poet" where a=4;
+-- Delete row on Secondary Master
+delete from test.t1 where a=4;
+-- Insert row on Secondary Master
+insert into test.t1 values (4, "Drouthy Neebors");
+-- Update row on Secondary Master
+update test.t1 set b="The Tankard" where a=4;
+-- Check data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Check data on Secondary Master, as set
+select * from test.t1 order by a;
+a	b
+4	The Tankard
+-- Restart Secondary Master slave
+start slave;
+-- Check data on Secondary Master - should be as Primary
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+------------------------------------------------------------------------
+Test 11 : Test Secondary insert-update-delete accepted
+------------------------------------------------------------------------
+Insert row on Secondary
+insert into test.t1 values (5, "Minders");
+Update row on Secondary
+update test.t1 set b="Southsider" where a=5;
+Delete row on Secondary
+delete from test.t1 where a=5;
+Check data on Primary, should be none.  No new conflicts
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+drop table test.t1;
+drop table test.t2;
+drop table test.t1$EX;
+Populate ndb_replication table as necessary
+-- Default extra Gci bits
+replace into mysql.ndb_replication values 
+("test", "t1", 3, 7, NULL), 
+("test", "t1", 1, 7, "NDB$EPOCH()");
+create table `test`.`t1$EX`
+  (server_id int unsigned,
+master_server_id int unsigned,
+master_epoch bigint unsigned,
+count int unsigned,
+a int not null,
+d int,
+primary key(server_id, master_server_id, master_epoch, count)) engine ndb;
+Create table
+create table test.t1(a int primary key, b varchar(255)) engine = ndb;
+Create other table
+create table test.t2(a int primary key, b int) engine = ndb;
+----------------------------------
+Test 1 : Basic two-way replication
+----------------------------------
+insert into test.t1 values (1, "Metropole");
+-- Give time for a new epoch on the Master
+-- Insert something to ensure the new epoch is noticed
+replace into test.t2 values (2, 1);
+-- Flushed to slave
+select * from test.t1 order by a;
+a	b
+1	Metropole
+-- Flushed back to Master
+select * from test.t1 order by a;
+a	b
+1	Metropole
+-- Now update data on slave
+update test.t1 set b="Favorit" where a=1;
+-- Now check data on master
+select * from test.t1 order by a;
+a	b
+1	Favorit
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Now perform multiple consecutive updates on the slave
+update test.t1 set b="Elephant house" where a=1;
+update test.t1 set b="Beach house" where a=1;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-- Now check they've applied on the master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+--------------------------------------------
+Test 2 : Normal Insert from Secondary Master
+--------------------------------------------
+-- Insert a new row on the Slave
+insert into test.t1 values (2, "Forrest");
+-- Check it exists on the Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Forrest
+-- Update from the slave
+update test.t1 set b="Reds" where a=2;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Reds
+delete from test.t1 where a=2;
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-------------------------------
+Test 3 : Insert-Insert conflict
+-------------------------------
+stop slave;
+-- Insert a row on the Primary Master
+insert into test.t1 values (2, "Loopy Lornas");
+-- Insert a row on the secondary Master
+insert into test.t1 values (2, "Cloisters");
+-- Examine data on Primary Master (should be unaffected)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Loopy Lornas
+-- Examine conflict indicators on Primary Master
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+1
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on isolated secondary Master (should be as-set)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Cloisters
+-- Restart secondary Masters slave
+start slave;
+-- Reexamine secondary Master's data (should be same as Primary Masters)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Loopy Lornas
+-------------------------------
+Test 4 : Update-Update conflict
+-------------------------------
+-- Stop replication to secondary master
+stop slave;
+-- Update row on Primary Master
+update test.t1 set b="Peters Yard" where a=2;
+-- Show data on Primary Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+1
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Update row on Secondary Master
+update test.t1 set b="Toast" where a=2;
+-- Examine data on Primary Master - should be unaffected
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+2
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Check data on secondary - should be as set
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Toast
+-- Now restart slave, will re-align row
+start slave;
+-- Check that Secondary is re-aligned
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Peters Yard
+-------------------------------
+Test 5 : Update-Delete conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Update on Primary Master
+update test.t1 set b="Pear tree" where a = 2;
+-- Delete on Secondary Master
+delete from test.t1 where a = 2;
+-- Examine data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Pear tree
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+3
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, still missing
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, aligned with Master
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Pear tree
+-------------------------------
+Test 6 : Delete-Update conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Delete on Primary Master
+delete from test.t1 where a=2;
+-- Update on Secondary Master
+update test.t1 set b="Black pig" where a=2;
+-- Examine data on Primary Master, should be unaffected (no row)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+4
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, should be as inserted
+select * from test.t1 order by a;
+a	b
+1	Beach house
+2	Black pig
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, aligned with Master (deleted)
+select * from test.t1 order by a;
+a	b
+1	Beach house
+-------------------------------
+Test 7 : Delete-Delete conflict
+-------------------------------
+-- Stop Secondary slave
+stop slave;
+-- Delete on Primary Master
+delete from test.t1 where a=1;
+-- Delete on Secondary Master
+delete from test.t1 where a=1;
+-- Examine data on Primary Master, no row
+select * from test.t1 order by a;
+a	b
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+5
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master before slave restart, no row
+select * from test.t1 order by a;
+a	b
+-- Restart Secondary Master slave
+start slave;
+-- Examine data on Secondary Master after slave restart, no row
+select * from test.t1 order by a;
+a	b
+------------------------------------------------
+Test 8 : Delete-Delete, Insert conflict exposure
+------------------------------------------------
+-- Insert a row on Secondary Master
+insert into test.t1 values (3, "Espy");
+-- Check it's present on Primary Master
+select * from test.t1 order by a;
+a	b
+3	Espy
+-- Stop replication in both directions
+stop slave;
+stop slave;
+-- Delete row from both clusters
+delete from test.t1 where a=3;
+delete from test.t1 where a=3;
+-- Follow up with Insert from Secondary master
+insert into test.t1 values (3, "Dalriada");
+-- Restart replication in both directions
+start slave;
+start slave;
+-- Check data on both sites - diverged
+-- Secondary master :
+select * from test.t1 order by a;
+a	b
+-- Primary master :
+select * from test.t1 order by a;
+a	b
+3	Dalriada
+--Remove extra row
+delete from test.t1 where a=3;
+-- Note that Delete-Delete conflict detected below
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+6
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+------------------------------------------------
+Test 9 : Insert, Insert-Update-Delete conflict
+------------------------------------------------
+-- Stop replication on Secondary Master
+stop slave;
+-- Insert row on Primary Master
+insert into test.t1 values (4, "Haymarket");
+-- Insert row on Secondary Master
+insert into test.t1 values (4, "Outhouse");
+-- Update row on Secondary Master
+update test.t1 set b="Mathers" where a = 4;
+-- Delete row on Secondary Master
+delete from test.t1 where a=4;
+-- Examine data (none) on Secondary Master
+select * from test.t1 order by a;
+a	b
+-- Examine data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+4	Haymarket
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+9
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Examine data on Secondary Master (none)
+select * from test.t1 order by a;
+a	b
+-- Restart Secondary Master's slave
+start slave;
+-- Check data on Secondary Master, should be same as Primary Master
+select * from test.t1;
+a	b
+4	Haymarket
+------------------------------------------------
+Test 10 : Update, Delete-Insert-Update conflict  
+------------------------------------------------
+-- Stop replication on Secondary Master 
+stop slave;
+-- Update row on Primary Master
+update test.t1 set b="Blind poet" where a=4;
+-- Delete row on Secondary Master
+delete from test.t1 where a=4;
+-- Insert row on Secondary Master
+insert into test.t1 values (4, "Drouthy Neebors");
+-- Update row on Secondary Master
+update test.t1 set b="The Tankard" where a=4;
+-- Check data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+-- Check data on Secondary Master, as set
+select * from test.t1 order by a;
+a	b
+4	The Tankard
+-- Restart Secondary Master slave
+start slave;
+-- Check data on Secondary Master - should be as Primary
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+------------------------------------------------------------------------
+Test 11 : Test Secondary insert-update-delete accepted
+------------------------------------------------------------------------
+Insert row on Secondary
+insert into test.t1 values (5, "Minders");
+Update row on Secondary
+update test.t1 set b="Southsider" where a=5;
+Delete row on Secondary
+delete from test.t1 where a=5;
+Check data on Primary, should be none.  No new conflicts
+select * from test.t1 order by a;
+a	b
+4	Blind poet
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+12
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+1	3	#	1	#	#
+1	3	#	2	#	#
+1	3	#	3	#	#
+1	3	#	4	#	#
+1	3	#	5	#	#
+1	3	#	6	#	#
+1	3	#	7	#	#
+1	3	#	8	#	#
+1	3	#	9	#	#
+1	3	#	10	#	#
+1	3	#	11	#	#
+1	3	#	12	#	#
+SELECT * FROM `t1$EX` ORDER BY a, d;
+server_id	master_server_id	master_epoch	count	a	d
+1	3	#	#	1	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	2	NULL
+1	3	#	#	3	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+1	3	#	#	4	NULL
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+drop table test.t1;
+drop table test.t2;
+drop table test.t1$EX;
+Now test batched conflict detection/handling
+create table test.t1 (
+a int primary key,
+b int,
+c varchar(2000)) engine=ndb;
+-- Stop replication from Primary -> Secondary
+stop slave;
+-- Insert a row on Primary
+insert into test.t1 values (1,1,repeat('B', 2000));
+-- Generate a large batch of inserts with early + late conflicts
+create procedure test.doit (rows int)
+begin
+set @x = 0;
+START TRANSACTION;
+repeat
+insert into test.t1 values (@x, @x, repeat('B', 2000));
+set @x = @x + 1;
+until @x = rows  
+end repeat;
+COMMIT;
+START TRANSACTION;
+update test.t1 set b=999, c=repeat('E',2000) where a=1;
+COMMIT;
+START TRANSACTION;
+delete from test.t1 where a=1;
+COMMIT;
+START TRANSACTION;
+insert into test.t1 values (1,1,'A');
+COMMIT;
+end%
+call test.doit(100);
+drop procedure test.doit;
+-- Look at Primary status, expect 4 conflicts
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
+VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+4
+SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t1$EX` ORDER BY a, d;
+SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
+SELECT * FROM `t2$EX` ORDER BY a, d;
+start slave;
+-- Look at Seconday row
+select a,b,sha1(c) from test.t1 where a=1;
+a	b	sha1(c)
+1	1	6d41e1d402596dff36396d1f0f288d17a4b9800a
+-- Check it's the same on the Secondary
+select a,b,sha1(c) from test.t1 where a=1;
+a	b	sha1(c)
+1	1	6d41e1d402596dff36396d1f0f288d17a4b9800a
+Test batching of DELETE vs DELETE with following INSERT
+delete from test.t1;
+insert into test.t1 values (1, 1, "Ma Brows");
+-- Stop Slave in both directions
+stop slave;
+stop slave;
+-- Delete row on Primary Cluster
+delete from test.t1 where a=1;
+-- Delete row on Secondary Cluster, followed by Insert in later 'batch'
+create procedure test.doit (rows int)
+begin
+set @x = 2;
+START TRANSACTION;
+delete from test.t1 where a=1;
+repeat
+insert into test.t1 values (@x, @x, repeat('B', 2000));
+set @x = @x + 1;
+until @x = (rows + 2)  
+end repeat;
+COMMIT;
+START TRANSACTION;
+insert into test.t1 values (1, 1, 'Malleny arms');
+COMMIT;
+end%
+call test.doit(200);
+-- Restart slave on Primary Cluster
+start slave;
+-- Verify that batching occurred when replicating the above
+select (@ndb_slave_execute_count - @ndb_slave_commit_count) > 1;
+(@ndb_slave_execute_count - @ndb_slave_commit_count) > 1
+1
+-- Show data on Primary Cluster (should have row inserted on Secondary)
+select * from test.t1 where a=1;
+a	b	c
+1	1	Malleny arms
+-- Show data on Secondary Cluster (should have row inserted on Secondary)
+select * from test.t1 where a=1;
+a	b	c
+1	1	Malleny arms
+--Restart slave on Secondary Cluster
+start slave;
+-- Show data on Secondary Cluster (should be missing)
+Clusters are diverged as expected with delete vs delete conflict
+followed closely by Insert
+select * from test.t1 where a=1;
+a	b	c
+drop procedure test.doit;
+drop table test.t1;
+delete from mysql.ndb_replication;
+insert into mysql.ndb_replication values
+("test", "t3", 0, 7, "NDB\$EPOCH(32)"),
+("test", "t4", 0, 7, "NDB\$EPOCH(-1)");
+create table test.t3 (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'test.t3' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$EPOCH(32), Too many extra Gci bits at ')'
+Error	1005	Can't create table 'test.t3' (errno: 1627)
+create table test.t4 (a int primary key) engine=ndb;
+ERROR HY000: Can't create table 'test.t4' (errno: 1627)
+show warnings;
+Level	Code	Message
+Error	1627	Error in parsing conflict function. Message: NDB$EPOCH(-1), Too many extra Gci bits at ')'
+Error	1005	Can't create table 'test.t4' (errno: 1627)
+drop table mysql.ndb_replication;

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_max.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_max.result	2010-01-27 09:29:10 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_max.result	2010-10-03 01:41:32 +0000
@@ -45,6 +45,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -71,6 +77,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -91,6 +103,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -118,6 +136,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -166,10 +190,22 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
 *** slave - check update some data that causes conflicts
@@ -202,10 +238,22 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
 *** slave - check higer timestamp
@@ -263,6 +311,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -289,6 +343,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -309,6 +369,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -336,6 +402,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -384,10 +456,22 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
 *** slave - check update some data that causes conflicts
@@ -420,10 +504,22 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
 *** slave - check higer timestamp
@@ -477,10 +573,16 @@ a	b	c	d
 3	Master t2 c=2	2	123
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-0
+3
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
-3
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	1	#	#
@@ -509,10 +611,16 @@ a	b	c	d
 3	Master t2 a=3 at c=3	3	123
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-0
+4
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
-4
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	1	#	#
@@ -537,10 +645,16 @@ select * from t2 order by a, d;
 a	b	c	d
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-0
+4
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
-4
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	1	#	#
@@ -576,6 +690,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -620,15 +740,21 @@ commit;
 *** slave - check conflict info, there should be some
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-0
+3
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
-3
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
-2	1	#	1	#	#
-2	1	#	2	#	#
-2	1	#	3	#	#
+2	1	#	5	#	#
+2	1	#	6	#	#
+2	1	#	7	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
 2	1	#	#	1	111
@@ -662,18 +788,24 @@ commit;
 *** slave - check conflict info, change depends on calling test
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-0
+6
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
-6
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
-2	1	#	1	#	#
-2	1	#	2	#	#
-2	1	#	3	#	#
-2	1	#	4	#	#
 2	1	#	5	#	#
 2	1	#	6	#	#
+2	1	#	7	#	#
+2	1	#	8	#	#
+2	1	#	9	#	#
+2	1	#	10	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
 2	1	#	#	1	111
@@ -737,6 +869,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -763,6 +901,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -783,6 +927,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -810,6 +960,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -854,15 +1010,27 @@ commit;
 *** slave - check conflict info, there should be some
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-3
+4
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
-1
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
-2	1	#	-9	#	#
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
+2	1	#	4	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 2	1	#	#	4	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
@@ -893,15 +1061,27 @@ commit;
 *** slave - check conflict info, change depends on calling test
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-3
+4
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
-1
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
-2	1	#	-9	#	#
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
+2	1	#	4	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 2	1	#	#	4	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_max_delete_win.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_max_delete_win.result	2010-01-27 09:29:10 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_max_delete_win.result	2010-10-03 01:41:32 +0000
@@ -45,6 +45,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -71,6 +77,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -91,6 +103,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -118,6 +136,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -162,14 +186,26 @@ commit;
 *** slave - check conflict info, there should be some
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-3
+0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
 *** slave - check update some data that causes conflicts
@@ -198,14 +234,26 @@ commit;
 *** slave - check conflict info, change depends on calling test
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-3
+0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
 *** slave - check higer timestamp
@@ -263,6 +311,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -289,6 +343,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -309,6 +369,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -336,6 +402,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -380,14 +452,26 @@ commit;
 *** slave - check conflict info, there should be some
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-3
+0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
 *** slave - check update some data that causes conflicts
@@ -416,14 +500,26 @@ commit;
 *** slave - check conflict info, change depends on calling test
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-3
+0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
 *** slave - check higer timestamp
@@ -480,7 +576,13 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
 3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	1	#	#
@@ -512,7 +614,13 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
 4
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	1	#	#
@@ -540,7 +648,13 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
 4
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	1	#	#
@@ -576,6 +690,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -623,12 +743,18 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
 3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
-2	1	#	1	#	#
-2	1	#	2	#	#
-2	1	#	3	#	#
+2	1	#	5	#	#
+2	1	#	6	#	#
+2	1	#	7	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
 2	1	#	#	1	111
@@ -665,15 +791,21 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
 6
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
-2	1	#	1	#	#
-2	1	#	2	#	#
-2	1	#	3	#	#
-2	1	#	4	#	#
 2	1	#	5	#	#
 2	1	#	6	#	#
+2	1	#	7	#	#
+2	1	#	8	#	#
+2	1	#	9	#	#
+2	1	#	10	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
 2	1	#	#	1	111
@@ -737,6 +869,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -763,6 +901,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -783,6 +927,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -810,6 +960,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -854,14 +1010,26 @@ commit;
 *** slave - check conflict info, there should be some
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-3
+0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
 *** slave - check update some data that causes conflicts
@@ -890,14 +1058,26 @@ commit;
 *** slave - check conflict info, change depends on calling test
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX";
 VARIABLE_VALUE-@init_ndb_conflict_fn_max
-3
+0
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
+2	1	#	1	#	#
+2	1	#	2	#	#
+2	1	#	3	#	#
 SELECT * FROM `t1$EX` ORDER BY a, d;
 server_id	master_server_id	master_epoch	count	a	d
+2	1	#	#	1	111
+2	1	#	#	2	111222
+2	1	#	#	3	111222333
 SELECT * FROM `t2$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 SELECT * FROM `t2$EX` ORDER BY a, d;
 *** slave - check higer timestamp

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_old.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_old.result	2010-01-27 09:29:10 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_conflict_old.result	2010-10-03 01:41:32 +0000
@@ -45,6 +45,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -71,6 +77,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -91,6 +103,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -118,6 +136,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -166,6 +190,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	1	#	#
@@ -208,6 +238,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 5
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	1	#	#
@@ -279,6 +315,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -305,6 +347,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -325,6 +373,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -352,6 +406,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -400,6 +460,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	-4	#	#
@@ -442,6 +508,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 5
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	-4	#	#
@@ -513,6 +585,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	-9	#	#
@@ -545,6 +623,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 4
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	-9	#	#
@@ -573,6 +657,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 4
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	-9	#	#
@@ -608,6 +698,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -656,6 +752,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 3
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	-9	#	#
@@ -698,6 +800,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 6
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	-9	#	#
@@ -769,6 +877,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -795,6 +909,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -815,6 +935,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -842,6 +968,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 SELECT * FROM `t1$EX` ORDER BY a, d;
@@ -890,6 +1022,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 4
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	-19	#	#
@@ -935,6 +1073,12 @@ VARIABLE_VALUE-@init_ndb_conflict_fn_max
 SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_old FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_OLD";
 VARIABLE_VALUE-@init_ndb_conflict_fn_old
 6
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_MAX_DEL_WIN";
+VARIABLE_VALUE-@init_ndb_conflict_fn_max_del_win
+0
+SELECT VARIABLE_VALUE-@init_ndb_conflict_fn_epoch FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE "NDB_CONFLICT_FN_EPOCH";
+VARIABLE_VALUE-@init_ndb_conflict_fn_epoch
+0
 SELECT server_id, master_server_id, master_epoch, count-@init_ndb_conflict_fn_old, a, d FROM `t1$EX` ORDER BY server_id, master_server_id, master_epoch, count;
 server_id	master_server_id	master_epoch	count-@init_ndb_conflict_fn_old	a	d
 2	1	#	-19	#	#

=== added file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_init_rep_status.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_init_rep_status.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_init_rep_status.result	2010-10-03 01:41:32 +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;
+reset master;
+stop slave;
+Generate something in the Masters Binlog
+use test;
+create table t1 (a int primary key, b int) engine=ndb;
+insert into t1 values (1,1);
+Initial state
+select * from mysql.ndb_apply_status;
+server_id	epoch	log_name	start_pos	end_pos
+show variables like 'Ndb_cluster_server_ids';
+Variable_name	Value
+ndb_cluster_server_ids	
+select variable_value from information_schema.global_status 
+where variable_name like '%Ndb_slave_max_replicated_epoch%';
+variable_value
+0
+select @slave_server_id:=(variable_value+0) from information_schema.global_variables 
+where variable_name like 'server_id';
+@slave_server_id:=(variable_value+0)
+2
+Default, no data, max replicated epoch will be 0.
+reset slave;
+start slave;
+select server_id from mysql.ndb_apply_status order by server_id;
+server_id
+1
+select variable_value from information_schema.global_status 
+where variable_name like 'Ndb_slave_max_replicated_epoch';
+variable_value
+0
+Default, load of own serverid from ndb_apply_status, should be 111
+drop table test.t1;
+stop slave;
+reset slave;
+insert into mysql.ndb_apply_status values (@slave_server_id, 111, 'Fictional log', 222, 333);
+start slave;
+select server_id from mysql.ndb_apply_status order by server_id;
+server_id
+1
+2
+select variable_value from information_schema.global_status 
+where variable_name like 'Ndb_slave_max_replicated_epoch';
+variable_value
+111
+drop table test.t1;
+Check that reset slave resets Ndb_slave_max_replicated_epoch
+stop slave;
+select variable_value from information_schema.global_status 
+where variable_name like 'Ndb_slave_max_replicated_epoch';
+variable_value
+111
+reset slave;
+select variable_value from information_schema.global_status 
+where variable_name like 'Ndb_slave_max_replicated_epoch';
+variable_value
+0
+Multiple-channel, load highest of configured serverids, should be 222
+set @other_local_server_id=@slave_server_id+1;
+set @other_remote_server_id=@slave_server_id+2;
+insert into mysql.ndb_apply_status values (@slave_server_id, 111, 'Fictional log', 222, 333);
+insert into mysql.ndb_apply_status values (@other_local_server_id, 222, 'Fictional log', 222, 333);
+insert into mysql.ndb_apply_status values (@other_remote_server_id, 111, 'Fictional log', 222, 333);
+set global ndb_cluster_server_ids=concat_ws(',', @slave_server_id, @other_local_server_id);
+show variables like 'ndb_cluster_server_ids';
+Variable_name	Value
+ndb_cluster_server_ids	2,3
+start slave;
+select server_id from mysql.ndb_apply_status order by server_id;
+server_id
+1
+2
+3
+4
+select variable_value from information_schema.global_status 
+where variable_name like 'Ndb_slave_max_replicated_epoch';
+variable_value
+222
+set global ndb_cluster_server_ids='';
+drop table test.t1;

=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_rep_error.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_rep_error.result	2009-09-24 11:05:08 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_rep_error.result	2010-10-03 01:41:32 +0000
@@ -10,9 +10,7 @@ Error	1626	Bad schema for mysql.ndb_repl
 drop table t1;
 insert into mysql.ndb_replication values ("test", "t1", 0, NULL, "NDB$X(X)");
 create table t1 (a int key, X int) engine ndb;
-Warnings:
-Error	1627	Error in parsing conflict function. Message: NDB$X(X), unknown conflict resolution function at 'NDB$X(X)'
-drop table t1;
+ERROR HY000: Can't create table 'test.t1' (errno: 1627)
 delete from mysql.ndb_replication;
 insert into mysql.ndb_replication values ("test", "t1", 0, NULL, "NDB$MAX(X)");
 create table t1 (a int key, X int) engine ndb;
@@ -22,13 +20,9 @@ drop table t1;
 delete from mysql.ndb_replication;
 insert into mysql.ndb_replication values ("test", "t1", 0, NULL, "NDB$MAX()");
 create table t1 (a int key, X int) engine ndb;
-Warnings:
-Error	1627	Error in parsing conflict function. Message: NDB$MAX(), missing function argument at ')'
-drop table t1;
+ERROR HY000: Can't create table 'test.t1' (errno: 1627)
 delete from mysql.ndb_replication;
 insert into mysql.ndb_replication values ("test", "t1", 0, NULL, "NDB$MAX(X Y)");
 create table t1 (a int key, X int) engine ndb;
-Warnings:
-Error	1627	Error in parsing conflict function. Message: NDB$MAX(X Y), missing ')' at 'Y)'
-drop table t1;
+ERROR HY000: Can't create table 'test.t1' (errno: 1627)
 delete from mysql.ndb_replication;

=== 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-10-03 01:41:32 +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-10-03 01:41:32 +0000
@@ -0,0 +1,113 @@
+--source include/have_ndb.inc
+--source include/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;
+
+--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	2009-12-17 10:14:52 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_circular.test	2010-10-03 01:41:32 +0000
@@ -74,3 +74,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;

=== added file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch.cnf'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch.cnf	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch.cnf	2010-10-03 01:41:32 +0000
@@ -0,0 +1,40 @@
+!include ../my.cnf
+
+# 2 clusters, each with 2 MySQLDs
+# All MySQLDs log-slave-updates
+# Potential infinite loops are broken by both servers 
+# on each cluster having the same server-id
+
+[mysqld]
+log-slave-updates
+ndb-log-apply-status
+
+[mysqld.1.1]
+server-id= 1
+log-bin = pref-master-1
+
+[mysqld.2.1]
+server-id= 2
+log-bin = pref-master-2
+
+[mysqld.1.slave]
+server-id= 3
+log-bin = sec-master-1
+skip-slave-start
+
+[mysqld.2.slave]
+server-id= 4
+log-bin = sec-master-2
+master-host=		127.0.0.1
+master-port=		@mysqld.2.1.port
+master-password=	@mysqld.2.1.#password
+master-user=		@mysqld.2.1.#user
+master-connect-retry=	1
+init-rpl-role=		slave
+skip-slave-start
+ndb_connectstring=	@mysql_cluster.slave.ndb_connectstring
+
+[ENV]
+
+SLAVE_MYPORT1=		@mysqld.2.slave.port
+SLAVE_MYSOCK1=		@mysqld.2.slave.socket

=== added file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch.test	2010-10-03 01:41:32 +0000
@@ -0,0 +1,240 @@
+#
+# Test engine native conflict resolution for ndb
+#   NDB$EPOCH() function
+#
+#
+--source include/have_ndb.inc
+--source include/have_binlog_format_mixed_or_row.inc
+--source include/ndb_master-slave.inc
+
+--echo Setup circular replication
+
+--connection slave
+RESET MASTER;
+select @slave_server_id:=(variable_value+0) 
+       from information_schema.global_variables 
+       where variable_name like 'server_id';
+let $SLAVE_SERVER_ID= query_get_value('select @slave_server_id as v',v,1);
+
+--connection master
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+--eval CHANGE MASTER TO master_host="127.0.0.1",master_port=$SLAVE_MYPORT,master_user="root"
+START SLAVE;
+select @master_server_id:=(variable_value+0) 
+       from information_schema.global_variables 
+       where variable_name like 'server_id';
+let $MASTER_SERVER_ID= query_get_value('select @master_server_id as v',v,1);
+
+--echo Setup ndb_replication and t1$EX exceptions table
+
+--disable_warnings
+--disable_query_log
+--connection master
+drop table if exists mysql.ndb_replication;
+CREATE TABLE mysql.ndb_replication
+  (db VARBINARY(63),
+   table_name VARBINARY(63),
+   server_id INT UNSIGNED,
+   binlog_type INT UNSIGNED,
+   conflict_fn VARBINARY(128),
+   PRIMARY KEY USING HASH (db,table_name,server_id))
+  ENGINE=NDB PARTITION BY KEY(db,table_name);
+--enable_warnings
+--enable_query_log
+
+--echo Populate ndb_replication table as necessary
+--echo -- 0 extra gci bits
+eval replace into mysql.ndb_replication values 
+  ("test", "t1", $SLAVE_SERVER_ID, 7, NULL), 
+  ("test", "t1", $MASTER_SERVER_ID, 7, "NDB\$EPOCH(0)");
+
+--source suite/rpl_ndb/t/rpl_ndb_conflict_epoch_1.inc
+
+--echo Populate ndb_replication table as necessary
+--echo -- 1 extra gci bits
+eval replace into mysql.ndb_replication values 
+  ("test", "t1", $SLAVE_SERVER_ID, 7, NULL), 
+  ("test", "t1", $MASTER_SERVER_ID, 7, "NDB\$EPOCH(1)");
+
+--source suite/rpl_ndb/t/rpl_ndb_conflict_epoch_1.inc
+
+--echo Populate ndb_replication table as necessary
+--echo -- 31 extra gci bits
+eval replace into mysql.ndb_replication values 
+  ("test", "t1", $SLAVE_SERVER_ID, 7, NULL), 
+  ("test", "t1", $MASTER_SERVER_ID, 7, "NDB\$EPOCH(31)");
+
+--source suite/rpl_ndb/t/rpl_ndb_conflict_epoch_1.inc
+
+--echo Populate ndb_replication table as necessary
+--echo -- Default extra Gci bits
+eval replace into mysql.ndb_replication values 
+  ("test", "t1", $SLAVE_SERVER_ID, 7, NULL), 
+  ("test", "t1", $MASTER_SERVER_ID, 7, "NDB\$EPOCH()");
+
+--source suite/rpl_ndb/t/rpl_ndb_conflict_epoch_1.inc
+
+--source include/ndb_conflict_info_init.inc
+
+--echo Now test batched conflict detection/handling
+--connection master
+
+create table test.t1 (
+  a int primary key,
+  b int,
+  c varchar(2000)) engine=ndb;
+
+--sync_slave_with_master slave
+--connection slave
+--echo -- Stop replication from Primary -> Secondary
+stop slave;
+--connection master
+--echo -- Insert a row on Primary
+insert into test.t1 values (1,1,repeat('B', 2000));
+
+--connection slave
+--echo -- Generate a large batch of inserts with early + late conflicts
+delimiter %;
+
+create procedure test.doit (rows int)
+begin
+  set @x = 0;
+  START TRANSACTION;
+    repeat
+      insert into test.t1 values (@x, @x, repeat('B', 2000));
+      set @x = @x + 1;
+    until @x = rows  
+    end repeat;
+  COMMIT;
+  START TRANSACTION;
+    update test.t1 set b=999, c=repeat('E',2000) where a=1;
+  COMMIT;
+  START TRANSACTION;
+    delete from test.t1 where a=1;
+  COMMIT;
+  START TRANSACTION;
+    insert into test.t1 values (1,1,'A');
+  COMMIT;
+end%
+
+delimiter ;%
+
+call test.doit(100);
+
+drop procedure test.doit;
+
+--sync_slave_with_master master
+--connection master
+
+--echo -- Look at Primary status, expect 4 conflicts
+--source include/ndb_conflict_info.inc
+
+--connection slave
+start slave;
+
+--connection master
+--echo -- Look at Seconday row
+select a,b,sha1(c) from test.t1 where a=1;
+
+--sync_slave_with_master slave
+--echo -- Check it's the same on the Secondary
+select a,b,sha1(c) from test.t1 where a=1;
+
+--connection master
+--echo Test batching of DELETE vs DELETE with following INSERT
+--connection master
+delete from test.t1;
+insert into test.t1 values (1, 1, "Ma Brows");
+--sync_slave_with_master slave
+--connection slave
+--sync_slave_with_master master
+--connection master
+--echo -- Stop Slave in both directions
+stop slave;
+--connection slave
+stop slave;
+--connection master
+--echo -- Delete row on Primary Cluster
+delete from test.t1 where a=1;
+
+--connection slave
+--echo -- Delete row on Secondary Cluster, followed by Insert in later 'batch'
+delimiter %;
+
+create procedure test.doit (rows int)
+begin
+  set @x = 2;
+  START TRANSACTION;
+    delete from test.t1 where a=1;
+    repeat
+      insert into test.t1 values (@x, @x, repeat('B', 2000));
+      set @x = @x + 1;
+    until @x = (rows + 2)  
+    end repeat;
+  COMMIT;
+  START TRANSACTION;
+    insert into test.t1 values (1, 1, 'Malleny arms');
+  COMMIT;
+end%
+
+delimiter ;%
+
+call test.doit(200);
+
+--echo -- Restart slave on Primary Cluster
+--connection master
+--source suite/rpl_ndb/include/ndb_init_slave_counts.inc
+start slave;
+
+--connection slave
+--sync_slave_with_master master
+
+--connection master
+--disable_result_log
+# Don't include results as they vary depending on epoch boundaries
+--source suite/rpl_ndb/include/ndb_slave_counts.inc
+--enable_result_log
+--echo -- Verify that batching occurred when replicating the above
+select (@ndb_slave_execute_count - @ndb_slave_commit_count) > 1;
+--echo -- Show data on Primary Cluster (should have row inserted on Secondary)
+select * from test.t1 where a=1;
+
+--echo -- Show data on Secondary Cluster (should have row inserted on Secondary)
+--connection slave
+select * from test.t1 where a=1;
+
+--echo --Restart slave on Secondary Cluster
+start slave;
+--connection master
+--sync_slave_with_master slave
+--connection slave
+
+--echo -- Show data on Secondary Cluster (should be missing)
+--echo    Clusters are diverged as expected with delete vs delete conflict
+--echo    followed closely by Insert
+--connection slave
+select * from test.t1 where a=1;
+
+--connection master
+
+drop procedure test.doit;
+drop table test.t1;
+
+delete from mysql.ndb_replication;
+insert into mysql.ndb_replication values
+  ("test", "t3", 0, 7, "NDB\$EPOCH(32)"),
+  ("test", "t4", 0, 7, "NDB\$EPOCH(-1)");
+
+--error 1005
+create table test.t3 (a int primary key) engine=ndb;
+show warnings;
+
+--error 1005
+create table test.t4 (a int primary key) engine=ndb;
+show warnings;
+
+--connection master
+drop table mysql.ndb_replication;
+
+--sync_slave_with_master slave
+

=== added file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch_1.inc'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch_1.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_conflict_epoch_1.inc	2010-10-03 01:41:32 +0000
@@ -0,0 +1,490 @@
+#
+# Include file for testing ndb$epoch conflict function 
+#
+#
+
+create table `test`.`t1$EX`
+  (server_id int unsigned,
+   master_server_id int unsigned,
+   master_epoch bigint unsigned,
+   count int unsigned,
+   a int not null,
+   d int,
+   primary key(server_id, master_server_id, master_epoch, count)) engine ndb;
+
+
+--echo Create table
+create table test.t1(a int primary key, b varchar(255)) engine = ndb;
+
+--echo Create other table
+create table test.t2(a int primary key, b int) engine = ndb; 
+
+--source include/ndb_conflict_info_init.inc
+
+--echo ----------------------------------
+--echo Test 1 : Basic two-way replication
+--echo ----------------------------------
+
+insert into test.t1 values (1, "Metropole");
+
+--echo -- Give time for a new epoch on the Master
+# This is 3 seconds to be > GCP_Save time, so that the next epoch
+# will be visibly greater than the one inserted above
+# (e.g. if we have 4 bits of extra GCI resolution, the max
+#  representable GCI is XXX/15.  If we insert at XXX/16, we
+#  need to wait until we get to XXX+1/0 at least, to avoid
+#  the Primary Master undoing the update)
+#
+--sleep 3
+
+--echo -- Insert something to ensure the new epoch is noticed
+#
+# Required in case our initial insert's epoch gets rounded up to
+# 0xffffffff, in which case 'later' updates from the slave will
+# be in conflict until some newer gci_hi is the MaxReplicatedEpoch
+#
+replace into test.t2 values (2, 1);
+--sync_slave_with_master slave
+--connection slave
+--echo -- Flushed to slave
+select * from test.t1 order by a;
+--sync_slave_with_master master
+--connection master
+--echo -- Flushed back to Master
+select * from test.t1 order by a;
+--connection slave
+
+--echo -- Now update data on slave
+update test.t1 set b="Favorit" where a=1;
+
+--sync_slave_with_master master
+
+--connection master
+--echo -- Now check data on master
+select * from test.t1 order by a;
+
+--source include/ndb_conflict_info.inc
+
+--connection slave
+--echo -- Now perform multiple consecutive updates on the slave
+
+update test.t1 set b="Elephant house" where a=1;
+update test.t1 set b="Beach house" where a=1;
+
+select * from test.t1 order by a;
+
+--sync_slave_with_master master
+--connection master
+--echo -- Now check they've applied on the master
+select * from test.t1 order by a;
+
+--source include/ndb_conflict_info.inc
+
+--echo --------------------------------------------
+--echo Test 2 : Normal Insert from Secondary Master
+--echo --------------------------------------------
+
+--connection slave
+--echo -- Insert a new row on the Slave
+insert into test.t1 values (2, "Forrest");
+
+--sync_slave_with_master master
+--connection master
+--echo -- Check it exists on the Master
+select * from test.t1 order by a;
+
+--connection slave
+--echo -- Update from the slave
+update test.t1 set b="Reds" where a=2;
+
+--sync_slave_with_master master
+--connection master
+select * from test.t1 order by a;
+
+--connection slave
+delete from test.t1 where a=2;
+
+--sync_slave_with_master master
+--connection master
+select * from test.t1 order by a;
+
+--source include/ndb_conflict_info.inc
+
+--echo -------------------------------
+--echo Test 3 : Insert-Insert conflict
+--echo -------------------------------
+
+--connection slave
+stop slave;
+--connection master
+
+--echo -- Insert a row on the Primary Master
+insert into test.t1 values (2, "Loopy Lornas");
+
+--connection slave
+--echo -- Insert a row on the secondary Master
+insert into test.t1 values (2, "Cloisters");
+
+--sync_slave_with_master master
+--connection master
+--echo -- Examine data on Primary Master (should be unaffected)
+select * from test.t1 order by a;
+
+--echo -- Examine conflict indicators on Primary Master
+--source include/ndb_conflict_info.inc
+
+--echo -- Examine data on isolated secondary Master (should be as-set)
+--connection slave
+select * from test.t1 order by a;
+
+--echo -- Restart secondary Masters slave
+start slave;
+
+--connection master
+--sync_slave_with_master slave
+--connection slave
+
+--echo -- Reexamine secondary Master's data (should be same as Primary Masters)
+select * from test.t1 order by a;
+
+--echo -------------------------------
+--echo Test 4 : Update-Update conflict
+--echo -------------------------------
+
+--connection slave
+--echo -- Stop replication to secondary master
+stop slave;
+
+--connection master
+--echo -- Update row on Primary Master
+
+update test.t1 set b="Peters Yard" where a=2;
+
+--echo -- Show data on Primary Master
+
+select * from test.t1 order by a;
+--source include/ndb_conflict_info.inc
+
+--connection slave
+
+--echo -- Update row on Secondary Master
+update test.t1 set b="Toast" where a=2;
+
+--sync_slave_with_master master
+
+--echo -- Examine data on Primary Master - should be unaffected
+
+select * from test.t1 order by a;
+--source include/ndb_conflict_info.inc
+
+--connection slave
+--echo -- Check data on secondary - should be as set
+
+select * from test.t1 order by a;
+
+--echo -- Now restart slave, will re-align row
+start slave;
+
+--connection master
+--sync_slave_with_master slave
+
+--connection slave
+--echo -- Check that Secondary is re-aligned
+
+select * from test.t1 order by a;
+
+
+--echo -------------------------------
+--echo Test 5 : Update-Delete conflict
+--echo -------------------------------
+
+--connection slave
+--echo -- Stop Secondary slave
+stop slave;
+
+--connection master
+--echo -- Update on Primary Master
+
+update test.t1 set b="Pear tree" where a = 2;
+
+--connection slave
+--echo -- Delete on Secondary Master
+
+delete from test.t1 where a = 2;
+
+--sync_slave_with_master master
+
+--echo -- Examine data on Primary Master, should be unaffected
+
+select * from test.t1 order by a;
+--source include/ndb_conflict_info.inc
+
+--echo -- Examine data on Secondary Master before slave restart, still missing
+--connection slave
+select * from test.t1 order by a;
+
+--echo -- Restart Secondary Master slave
+start slave;
+
+--connection master
+--sync_slave_with_master slave
+--connection slave
+
+--echo -- Examine data on Secondary Master after slave restart, aligned with Master
+select * from test.t1 order by a;
+
+--echo -------------------------------
+--echo Test 6 : Delete-Update conflict
+--echo -------------------------------
+
+--connection slave
+--echo -- Stop Secondary slave
+stop slave;
+
+--connection master
+--echo -- Delete on Primary Master
+
+delete from test.t1 where a=2;
+
+--connection slave
+--echo -- Update on Secondary Master
+
+update test.t1 set b="Black pig" where a=2;
+
+--sync_slave_with_master master
+
+--echo -- Examine data on Primary Master, should be unaffected (no row)
+
+select * from test.t1 order by a;
+--source include/ndb_conflict_info.inc
+
+--echo -- Examine data on Secondary Master before slave restart, should be as inserted
+--connection slave
+select * from test.t1 order by a;
+
+--echo -- Restart Secondary Master slave
+start slave;
+
+--connection master
+--sync_slave_with_master slave
+--connection slave
+
+--echo -- Examine data on Secondary Master after slave restart, aligned with Master (deleted)
+select * from test.t1 order by a;
+
+--echo -------------------------------
+--echo Test 7 : Delete-Delete conflict
+--echo -------------------------------
+
+--connection slave
+--echo -- Stop Secondary slave
+stop slave;
+
+--connection master
+--echo -- Delete on Primary Master
+
+delete from test.t1 where a=1;
+
+--connection slave
+--echo -- Delete on Secondary Master
+
+delete from test.t1 where a=1;
+
+--sync_slave_with_master master
+
+--echo -- Examine data on Primary Master, no row
+
+select * from test.t1 order by a;
+--source include/ndb_conflict_info.inc
+
+--echo -- Examine data on Secondary Master before slave restart, no row
+--connection slave
+select * from test.t1 order by a;
+
+--echo -- Restart Secondary Master slave
+start slave;
+
+--connection master
+--sync_slave_with_master slave
+--connection slave
+
+--echo -- Examine data on Secondary Master after slave restart, no row
+select * from test.t1 order by a;
+
+
+--echo ------------------------------------------------
+--echo Test 8 : Delete-Delete, Insert conflict exposure
+--echo ------------------------------------------------
+# This occurs as the Primary Master's Delete is still
+# in-flight when the Secondary Master's Insert arrives, 
+# but as there is no knowledge of this at the Primary
+# Master, it accepts the Insert.
+# 
+
+--connection slave
+--echo -- Insert a row on Secondary Master
+insert into test.t1 values (3, "Espy");
+--sync_slave_with_master master
+
+--connection master
+--echo -- Check it's present on Primary Master
+select * from test.t1 order by a;
+
+--echo -- Stop replication in both directions
+stop slave;
+
+--connection slave
+stop slave;
+
+--echo -- Delete row from both clusters
+delete from test.t1 where a=3;
+
+--connection master
+delete from test.t1 where a=3;
+
+--echo -- Follow up with Insert from Secondary master
+--connection slave
+
+insert into test.t1 values (3, "Dalriada");
+
+--echo -- Restart replication in both directions
+start slave;
+
+--connection master
+start slave;
+
+--sync_slave_with_master slave
+--connection slave
+--sync_slave_with_master master
+
+--connection slave
+--echo -- Check data on both sites - diverged
+--echo -- Secondary master :
+select * from test.t1 order by a;
+--echo -- Primary master :
+--connection master
+select * from test.t1 order by a;
+
+--echo --Remove extra row
+delete from test.t1 where a=3;
+
+--echo -- Note that Delete-Delete conflict detected below
+--source include/ndb_conflict_info.inc
+
+--echo ------------------------------------------------
+--echo Test 9 : Insert, Insert-Update-Delete conflict
+--echo ------------------------------------------------
+
+--connection slave
+--echo -- Stop replication on Secondary Master
+stop slave;
+
+--connection master
+--echo -- Insert row on Primary Master
+insert into test.t1 values (4, "Haymarket");
+
+--connection slave
+--echo -- Insert row on Secondary Master
+insert into test.t1 values (4, "Outhouse");
+--echo -- Update row on Secondary Master
+update test.t1 set b="Mathers" where a = 4;
+--echo -- Delete row on Secondary Master
+delete from test.t1 where a=4;
+
+--echo -- Examine data (none) on Secondary Master
+select * from test.t1 order by a;
+
+--sync_slave_with_master master
+--connection master
+--echo -- Examine data on Primary Master, should be unaffected
+
+select * from test.t1 order by a;
+--source include/ndb_conflict_info.inc
+
+--connection slave
+--echo -- Examine data on Secondary Master (none)
+select * from test.t1 order by a;
+
+--echo -- Restart Secondary Master's slave
+start slave;
+
+--connection master
+--sync_slave_with_master slave
+--connection slave
+--echo -- Check data on Secondary Master, should be same as Primary Master
+select * from test.t1;
+
+--echo ------------------------------------------------
+--echo Test 10 : Update, Delete-Insert-Update conflict  
+--echo ------------------------------------------------
+--connection slave
+--echo -- Stop replication on Secondary Master 
+stop slave;
+
+--connection master
+--echo -- Update row on Primary Master
+update test.t1 set b="Blind poet" where a=4;
+
+--connection slave
+--echo -- Delete row on Secondary Master
+delete from test.t1 where a=4;
+
+--echo -- Insert row on Secondary Master
+insert into test.t1 values (4, "Drouthy Neebors");
+
+--echo -- Update row on Secondary Master
+update test.t1 set b="The Tankard" where a=4;
+
+--sync_slave_with_master master
+
+--connection master
+
+--echo -- Check data on Primary Master, should be unaffected
+select * from test.t1 order by a;
+--source include/ndb_conflict_info.inc
+
+--connection slave
+--echo -- Check data on Secondary Master, as set
+
+select * from test.t1 order by a;
+
+--echo -- Restart Secondary Master slave
+start slave;
+
+--connection master
+--sync_slave_with_master slave
+--connection slave
+
+--echo -- Check data on Secondary Master - should be as Primary
+select * from test.t1 order by a; 
+
+--sync_slave_with_master master
+
+--echo ------------------------------------------------------------------------
+--echo Test 11 : Test Secondary insert-update-delete accepted
+--echo ------------------------------------------------------------------------
+--connection slave
+--echo Insert row on Secondary
+insert into test.t1 values (5, "Minders");
+--echo Update row on Secondary
+update test.t1 set b="Southsider" where a=5;
+--echo Delete row on Secondary
+delete from test.t1 where a=5;
+
+--sync_slave_with_master master
+
+--connection master
+--echo Check data on Primary, should be none.  No new conflicts
+select * from test.t1 order by a;
+--source include/ndb_conflict_info.inc
+
+--connection master
+--source include/ndb_conflict_info.inc
+
+drop table test.t1;
+drop table test.t2;
+drop table test.t1$EX;
+
+--sync_slave_with_master slave
+
+--connection master
\ No newline at end of file

=== added file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_init_rep_status.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_init_rep_status.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_init_rep_status.test	2010-10-03 01:41:32 +0000
@@ -0,0 +1,83 @@
+--source include/have_ndb.inc
+--source include/ndb_master-slave.inc
+
+# Test Slave initialisation of Ndb_slave_max_replicated_epoch status var
+
+--connection slave
+reset master;
+stop slave;
+
+--connection master
+--echo Generate something in the Masters Binlog
+use test;
+create table t1 (a int primary key, b int) engine=ndb;
+
+insert into t1 values (1,1);
+
+--connection slave
+--echo Initial state
+select * from mysql.ndb_apply_status;
+show variables like 'Ndb_cluster_server_ids';
+select variable_value from information_schema.global_status 
+  where variable_name like '%Ndb_slave_max_replicated_epoch%';
+select @slave_server_id:=(variable_value+0) from information_schema.global_variables 
+  where variable_name like 'server_id';
+
+--echo Default, no data, max replicated epoch will be 0.
+reset slave;
+start slave;
+--connection master
+--sync_slave_with_master
+--connection slave
+--replace_column 3 # 4 # 5 #
+select server_id from mysql.ndb_apply_status order by server_id;
+select variable_value from information_schema.global_status 
+  where variable_name like 'Ndb_slave_max_replicated_epoch';
+
+--echo Default, load of own serverid from ndb_apply_status, should be 111
+drop table test.t1;
+stop slave;
+reset slave;
+insert into mysql.ndb_apply_status values (@slave_server_id, 111, 'Fictional log', 222, 333);
+start slave;
+--connection master
+--sync_slave_with_master
+--connection slave
+--replace_column 3 # 4 # 5 #
+select server_id from mysql.ndb_apply_status order by server_id;
+select variable_value from information_schema.global_status 
+  where variable_name like 'Ndb_slave_max_replicated_epoch';
+
+drop table test.t1;
+
+--echo Check that reset slave resets Ndb_slave_max_replicated_epoch
+stop slave;
+select variable_value from information_schema.global_status 
+  where variable_name like 'Ndb_slave_max_replicated_epoch';
+reset slave;
+select variable_value from information_schema.global_status 
+  where variable_name like 'Ndb_slave_max_replicated_epoch';
+
+--echo Multiple-channel, load highest of configured serverids, should be 222
+set @other_local_server_id=@slave_server_id+1;
+set @other_remote_server_id=@slave_server_id+2;
+insert into mysql.ndb_apply_status values (@slave_server_id, 111, 'Fictional log', 222, 333);
+insert into mysql.ndb_apply_status values (@other_local_server_id, 222, 'Fictional log', 222, 333);
+insert into mysql.ndb_apply_status values (@other_remote_server_id, 111, 'Fictional log', 222, 333);
+
+set global ndb_cluster_server_ids=concat_ws(',', @slave_server_id, @other_local_server_id);
+show variables like 'ndb_cluster_server_ids';
+start slave;
+--connection master
+--sync_slave_with_master
+--connection slave
+--replace_column 3 # 4 # 5 #
+select server_id from mysql.ndb_apply_status order by server_id;
+select variable_value from information_schema.global_status 
+  where variable_name like 'Ndb_slave_max_replicated_epoch';
+
+# Clean up
+set global ndb_cluster_server_ids='';
+--connection master
+drop table test.t1;
+--sync_slave_with_master

=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_rep_error.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_rep_error.test	2007-11-06 10:07:03 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_rep_error.test	2010-10-03 01:41:32 +0000
@@ -47,10 +47,10 @@ CREATE TABLE mysql.ndb_replication
 --enable_query_log
 
 # Non existant conflict_fn
-# gives warning when creating table
+# gives error when creating table
 insert into mysql.ndb_replication values ("test", "t1", 0, NULL, "NDB$X(X)");
+--error 1005
 create table t1 (a int key, X int) engine ndb;
-drop table t1;
 delete from mysql.ndb_replication;
 
 # Column type cannot be used for this function
@@ -61,17 +61,17 @@ drop table t1;
 delete from mysql.ndb_replication;
 
 # Too few arguments
-# gives warning when creating table
+# gives error when creating table
 insert into mysql.ndb_replication values ("test", "t1", 0, NULL, "NDB$MAX()");
+--error 1005
 create table t1 (a int key, X int) engine ndb;
-drop table t1;
 delete from mysql.ndb_replication;
 
 # Too many arguments
-# gives warning when creating table
+# gives error when creating table
 insert into mysql.ndb_replication values ("test", "t1", 0, NULL, "NDB$MAX(X Y)");
+--error 1005
 create table t1 (a int key, X int) engine ndb;
-drop table t1;
 delete from mysql.ndb_replication;
 
 --disable_query_log

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2010-09-22 12:10:34 +0000
+++ b/sql/ha_ndbcluster.cc	2010-10-03 01:41:32 +0000
@@ -45,6 +45,7 @@
 
 #include <mysql/plugin.h>
 #include <ndb_version.h>
+#include <util/Vector.hpp>
 
 #ifdef ndb_dynamite
 #undef assert
@@ -67,6 +68,8 @@ static uint opt_ndb_cluster_connection_p
 static char* opt_ndb_connectstring;
 static uint opt_ndb_nodeid;
 extern ulong opt_server_id_mask;
+char* opt_ndb_cluster_server_ids;
+Vector<Uint32> cluster_server_ids;
 
 static MYSQL_THDVAR_UINT(
   autoincrement_prefetch_sz,         /* name */
@@ -330,6 +333,20 @@ pthread_cond_t COND_ndb_util_thread;
 pthread_cond_t COND_ndb_util_ready;
 pthread_handler_t ndb_util_thread_func(void *arg);
 
+/* Slave thread Ndb-specific state */
+struct st_ndb_slave_state
+{
+  st_ndb_slave_state() { bzero(this, sizeof(struct st_ndb_slave_state)); }
+  
+  long write_row_count;
+  long update_row_count;
+  long delete_row_count;
+  long execute_count;
+  long commit_count;
+};
+
+static struct st_ndb_slave_state g_ndb_slave_state;
+
 /* Status variables shown with 'show status like 'Ndb%' */
 
 struct st_ndb_status {
@@ -349,8 +366,9 @@ struct st_ndb_status {
 };
 
 static struct st_ndb_status g_ndb_status;
-static long g_ndb_status_conflict_fn_max= 0;
-static long g_ndb_status_conflict_fn_old= 0;
+static long g_ndb_status_conflict_fn[CFT_NUMBER_OF_CFTS] = {0,0,0};
+
+Uint64 g_ndb_status_max_rep_epoch= 0;
 
 static int update_status_variables(Thd_ndb *thd_ndb,
                                    st_ndb_status *ns,
@@ -408,8 +426,20 @@ SHOW_VAR ndb_status_variables_fixed[]= {
 };
 
 SHOW_VAR ndb_status_conflict_variables[]= {
-  {"fn_max",     (char*) &g_ndb_status_conflict_fn_max, SHOW_LONG},
-  {"fn_old",     (char*) &g_ndb_status_conflict_fn_old, SHOW_LONG},
+  {"fn_max",       (char*) &g_ndb_status_conflict_fn[CFT_NDB_MAX], SHOW_LONG},
+  {"fn_old",       (char*) &g_ndb_status_conflict_fn[CFT_NDB_OLD], SHOW_LONG},
+  {"fn_max_del_win", (char*) &g_ndb_status_conflict_fn[CFT_NDB_MAX_DEL_WIN], SHOW_LONG},
+  {"fn_epoch",     (char*) &g_ndb_status_conflict_fn[CFT_NDB_EPOCH], SHOW_LONG},
+  {NullS, NullS, SHOW_LONG}
+};
+
+SHOW_VAR ndb_status_variables_slave[]= {
+  {"max_replicated_epoch", (char*) &g_ndb_status_max_rep_epoch, SHOW_LONGLONG},
+  {"write_row_count", (char*) &g_ndb_slave_state.write_row_count, SHOW_LONGLONG},
+  {"update_row_count", (char*) &g_ndb_slave_state.update_row_count, SHOW_LONGLONG},
+  {"delete_row_count", (char*) &g_ndb_slave_state.delete_row_count, SHOW_LONGLONG},
+  {"execute_count", (char*) &g_ndb_slave_state.execute_count, SHOW_LONGLONG},
+  {"commit_count", (char*) &g_ndb_slave_state.commit_count, SHOW_LONGLONG},
   {NullS, NullS, SHOW_LONG}
 };
 
@@ -524,6 +554,21 @@ static int write_conflict_row(NDB_SHARE 
 }
 #endif
 
+#ifdef HAVE_NDB_BINLOG
+int
+handle_row_conflict(enum_conflict_fn_type cft,
+                    NDB_CONFLICT_FN_SHARE* cfn_share,
+                    const NdbRecord* key_rec,
+                    const uchar* pk_row,
+                    enum_conflicting_op_type op_type,
+                    enum_conflict_cause conflict_cause,
+                    const NdbError& conflict_error,
+                    NdbTransaction* conflict_trans,
+                    NdbError& err);
+#endif
+
+static const Uint32 error_op_after_refresh_op = 920; 
+
 inline int
 check_completed_operations_pre_commit(Thd_ndb *thd_ndb, NdbTransaction *trans,
                                       const NdbOperation *first,
@@ -536,7 +581,7 @@ check_completed_operations_pre_commit(Th
     or exceptions to report
   */
 #ifdef HAVE_NDB_BINLOG
-  uint conflict_rows_written= 0;
+  uint conflict_operations_defined= 0;
 #endif
   while (first)
   {
@@ -550,74 +595,138 @@ check_completed_operations_pre_commit(Th
     {
 #ifdef HAVE_NDB_BINLOG
       DBUG_PRINT("info", ("ndb error: %d", err.code));
-      if (err.code == (int) error_conflict_fn_max_violation)
-      {
-        DBUG_PRINT("info", ("err.code == (int) error_conflict_fn_max_violation"));
-        thd_ndb->m_max_violation_count++;
-      }
-      else if (err.code == (int) error_conflict_fn_old_violation ||
-               err.classification == NdbError::ConstraintViolation ||
-               err.classification == NdbError::NoDataFound)
+      if ((err.code == (int) error_conflict_fn_violation) ||
+          (err.code == (int) error_op_after_refresh_op) ||
+          (err.classification == NdbError::ConstraintViolation) ||
+          (err.classification == NdbError::NoDataFound))
       {
         DBUG_PRINT("info",
-                   ("err.code %s (int) error_conflict_fn_old_violation, "
-                    "err.classification %s",
-                    err.code == (int) error_conflict_fn_old_violation ? "==" : "!=",
-                    err.classification
-                    == NdbError::ConstraintViolation
-                    ? "== NdbError::ConstraintViolation"
-                    : (err.classification == NdbError::NoDataFound
-                       ? "== NdbError::NoDataFound" : "!=")));
-        thd_ndb->m_old_violation_count++;
+                  ("err.code %s (int) error_conflict_fn_violation, "
+                   "err.classification %s",
+                   err.code == (int) error_conflict_fn_violation ? "==" : "!=",
+                   err.classification
+                   == NdbError::ConstraintViolation
+                   ? "== NdbError::ConstraintViolation"
+                   : (err.classification == NdbError::NoDataFound
+                      ? "== NdbError::NoDataFound" : "!=")));
+
+        enum_conflict_cause conflict_cause;
+        
+        if ((err.code == (int) error_conflict_fn_violation) ||
+            (err.code == (int) error_op_after_refresh_op))
+        {
+          conflict_cause= ROW_IN_CONFLICT;
+        }
+        else if (err.classification == NdbError::ConstraintViolation)
+        {
+          conflict_cause= ROW_ALREADY_EXISTS;
+        }
+        else
+        {
+          assert(err.classification == NdbError::NoDataFound);
+          conflict_cause= ROW_DOES_NOT_EXIST;
+        }
+
         const void* buffer= first->getCustomData();
         if (buffer != NULL)
         {
           Ndb_exceptions_data ex_data;
           memcpy(&ex_data, buffer, sizeof(ex_data));
           NDB_SHARE *share= ex_data.share;
+          const NdbRecord* key_rec= ex_data.key_rec;
           const uchar* row= ex_data.row;
+          enum_conflicting_op_type op_type = ex_data.op_type;
           DBUG_ASSERT(share != NULL && row != NULL);
 
           NDB_CONFLICT_FN_SHARE* cfn_share= share->m_cfn_share;
-          if (cfn_share && cfn_share->m_ex_tab)
+          if (cfn_share)
           {
-            NdbError ex_err;
-            if (write_conflict_row(share, trans, row, ex_err))
+            enum_conflict_fn_type cft = cfn_share->m_resolve_cft;
+            bool haveExTable = cfn_share->m_ex_tab != NULL;
+            
+            thd_ndb->m_violation_count[cft]++;
+            
             {
-              char msg[FN_REFLEN];
-              my_snprintf(msg, sizeof(msg), "table %s NDB error %d '%s'",
-                          cfn_share->m_ex_tab->getName(),
-                          ex_err.code, ex_err.message);
-
-              NdbDictionary::Dictionary* dict= thd_ndb->ndb->getDictionary();
-
-              if (ex_err.classification == NdbError::SchemaError)
-              {
-                dict->removeTableGlobal(*(cfn_share->m_ex_tab), false);
-                cfn_share->m_ex_tab= NULL;
-              }
-              else if (ex_err.status == NdbError::TemporaryError)
+              NdbError handle_error;
+              if (handle_row_conflict(cft,
+                                      cfn_share,
+                                      key_rec,
+                                      row,
+                                      op_type,
+                                      conflict_cause,
+                                      err,
+                                      trans,
+                                      handle_error))
               {
-                /* Slave will roll back and retry entire transaction. */
-                ERR_RETURN(ex_err);
+                /* Error with function-specific handling of row conflict */
+                char msg[FN_REFLEN];
+                my_snprintf(msg, sizeof(msg), "Row conflict handling "
+                            "on table %s hit Ndb error %d '%s'",
+                            cfn_share->m_tab->getName(),
+                            handle_error.code,
+                            handle_error.message);
+                
+                if (handle_error.status == NdbError::TemporaryError)
+                {
+                  /* Slave will roll back and retry entire transaction. */
+                  ERR_RETURN(handle_error);
+                }
+                else
+                {
+                  push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+                                      ER_EXCEPTIONS_WRITE_ERROR,
+                                      ER(ER_EXCEPTIONS_WRITE_ERROR), msg);
+                  /* Slave will stop replication. */
+                  DBUG_RETURN(ER_EXCEPTIONS_WRITE_ERROR);
+                }
               }
               else
               {
-                push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
-                                    ER_EXCEPTIONS_WRITE_ERROR,
-                                    ER(ER_EXCEPTIONS_WRITE_ERROR), msg);
-                /* Slave will stop replication. */
-                DBUG_RETURN(ER_EXCEPTIONS_WRITE_ERROR);
+                conflict_operations_defined++;
               }
             }
-            else
+              
+
+            if (haveExTable)
             {
-              conflict_rows_written++;
+              NdbError ex_err;
+              if (write_conflict_row(share, trans, row, ex_err))
+              {
+                char msg[FN_REFLEN];
+                my_snprintf(msg, sizeof(msg), "table %s NDB error %d '%s'",
+                            cfn_share->m_ex_tab->getName(),
+                            ex_err.code, ex_err.message);
+                
+                NdbDictionary::Dictionary* dict= thd_ndb->ndb->getDictionary();
+                
+                if (ex_err.classification == NdbError::SchemaError)
+                {
+                  dict->removeTableGlobal(*(cfn_share->m_ex_tab), false);
+                  cfn_share->m_ex_tab= NULL;
+                }
+                else if (ex_err.status == NdbError::TemporaryError)
+                {
+                  /* Slave will roll back and retry entire transaction. */
+                  ERR_RETURN(ex_err);
+                }
+                else
+                {
+                  push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+                                      ER_EXCEPTIONS_WRITE_ERROR,
+                                      ER(ER_EXCEPTIONS_WRITE_ERROR), msg);
+                  /* Slave will stop replication. */
+                  DBUG_RETURN(ER_EXCEPTIONS_WRITE_ERROR);
+                }
+              }
+              else
+              {
+                conflict_operations_defined++;
+              }
             }
           }
           else
           {
-            DBUG_PRINT("info", ("missing %s", !cfn_share ? "cfn_share" : "ex_tab"));
+            DBUG_PRINT("info", ("missing cfn_share"));
           }
         }
         else
@@ -639,8 +748,10 @@ check_completed_operations_pre_commit(Th
   if (ignore_count)
     *ignore_count= ignores;
 #ifdef HAVE_NDB_BINLOG
-  if (conflict_rows_written)
+  if (conflict_operations_defined)
   {
+    const NdbOperation* last_conflict_op = trans->getLastDefinedOperation();
+    
     if (trans->execute(NdbTransaction::NoCommit,
                        NdbOperation::AO_IgnoreError,
                        thd_ndb->m_force_send))
@@ -648,9 +759,26 @@ check_completed_operations_pre_commit(Th
       abort();
       //err= trans->getNdbError();
     }
+
     if (trans->getNdbError().code)
     {
-      sql_print_error("NDB slave: write conflict row error code %d", trans->getNdbError().code);
+      /* Check the result codes of the operations we added */
+      const NdbOperation* conflict_op = NULL;
+      do
+      {
+        conflict_op = trans->getNextCompletedOperation(conflict_op);
+        assert(conflict_op != NULL);
+        /* We will ignore 920 which represents a refreshOp or other op
+         * arriving after a refreshOp
+         */
+        Uint32 conflict_op_error = conflict_op->getNdbError().code;
+        
+        if ((conflict_op_error != 0) &&
+            (conflict_op_error != error_op_after_refresh_op))
+        {
+          sql_print_error("NDB slave: conflict handling error code %d", conflict_op->getNdbError().code);
+        }
+      } while (conflict_op != last_conflict_op);
     }
   }
 #endif
@@ -749,19 +877,34 @@ int execute_commit(Thd_ndb *thd_ndb, Ndb
   }
   const NdbOperation *first= trans->getFirstDefinedOperation();
   thd_ndb->m_execute_count++;
+  if (thd_ndb->m_slave_thread)
+  {
+    g_ndb_slave_state.commit_count++;
+    g_ndb_slave_state.execute_count+= thd_ndb->m_execute_count;
+    thd_ndb->m_execute_count= 0;
+  }
   DBUG_PRINT("info", ("execute_count: %u", thd_ndb->m_execute_count));
   if (trans->execute(NdbTransaction::Commit, ao, force_send))
   {
-    thd_ndb->m_max_violation_count= 0;
-    thd_ndb->m_old_violation_count= 0;
+    bzero(thd_ndb->m_violation_count, sizeof(thd_ndb->m_violation_count));
+    thd_ndb->m_max_replicated_epoch = 0;
     thd_ndb->m_conflict_fn_usage_count= 0;
     thd_ndb->m_unsent_bytes= 0;
     DBUG_RETURN(-1);
   }
-  g_ndb_status_conflict_fn_max+= thd_ndb->m_max_violation_count;
-  g_ndb_status_conflict_fn_old+= thd_ndb->m_old_violation_count;
-  thd_ndb->m_max_violation_count= 0;
-  thd_ndb->m_old_violation_count= 0;
+  for(int i=0; i< CFT_NUMBER_OF_CFTS; i++)
+  {
+    g_ndb_status_conflict_fn[i]+= thd_ndb->m_violation_count[i];
+    thd_ndb->m_violation_count[i]= 0;
+  }
+  if (thd_ndb->m_max_replicated_epoch > g_ndb_status_max_rep_epoch)
+  {
+    DBUG_PRINT("info", ("Max replicated epoch increases from %llu to %llu",
+                        g_ndb_status_max_rep_epoch,
+                        thd_ndb->m_max_replicated_epoch));
+    g_ndb_status_max_rep_epoch = thd_ndb->m_max_replicated_epoch;
+  }
+  thd_ndb->m_max_replicated_epoch = 0;
   thd_ndb->m_conflict_fn_usage_count= 0;
   thd_ndb->m_unsent_bytes= 0;
   if (!ignore_error || trans->getNdbError().code == 0)
@@ -819,15 +962,16 @@ Thd_ndb::Thd_ndb()
   m_execute_count= 0;
   m_scan_count= 0;
   m_pruned_scan_count= 0;
-  m_max_violation_count= 0;
-  m_old_violation_count= 0;
+  bzero(m_violation_count, sizeof(m_violation_count));
   m_conflict_fn_usage_count= 0;
   bzero(m_transaction_no_hint_count, sizeof(m_transaction_no_hint_count));
   bzero(m_transaction_hint_count, sizeof(m_transaction_hint_count));
   global_schema_lock_trans= NULL;
   global_schema_lock_count= 0;
   global_schema_lock_error= 0;
+  m_max_replicated_epoch= 0;
   init_alloc_root(&m_batch_mem_root, BATCH_FLUSH_SIZE/4, 0);
+  m_slave_thread= false;
 }
 
 Thd_ndb::~Thd_ndb()
@@ -2700,8 +2844,8 @@ int ha_ndbcluster::ndb_pk_update_row(THD
     DBUG_PRINT("info", ("insert failed"));
     if (trans->commitStatus() == NdbConnection::Started)
     {
-      m_thd_ndb->m_max_violation_count= 0;
-      m_thd_ndb->m_old_violation_count= 0;
+      bzero(m_thd_ndb->m_violation_count, sizeof(m_thd_ndb->m_violation_count));
+      m_thd_ndb->m_max_replicated_epoch= 0;
       m_thd_ndb->m_conflict_fn_usage_count= 0;
       m_thd_ndb->m_unsent_bytes= 0;
       m_thd_ndb->m_execute_count++;
@@ -3631,6 +3775,25 @@ bool ha_ndbcluster::isManualBinlogExec(T
 
 }
 
+/*
+  is_serverid_local
+
+  Check the list of cluster-local serverids to see
+  whether the passed serverid is local.
+*/
+bool is_serverid_local(Uint32 serverid)
+{
+  for (Uint32 i=0; i< cluster_server_ids.size(); i++)
+  {
+    if (cluster_server_ids[i] == serverid)
+      return true;
+  }
+
+  assert(serverid != ::server_id);
+
+  return false;
+}
+
 int ha_ndbcluster::write_row(uchar *record)
 {
   DBUG_ENTER("ha_ndbcluster::write_row");
@@ -3645,6 +3808,26 @@ int ha_ndbcluster::write_row(uchar *reco
       memcpy(&master_epoch, table->field[1]->ptr + (record - table->record[0]),
              sizeof(master_epoch));
       active_mi->master_epoch= master_epoch;
+      assert(! is_serverid_local(sid));
+    }
+    else if (is_serverid_local(sid))
+    {
+      Uint64 applied_epoch;
+      memcpy(&applied_epoch, table->field[1]->ptr + (record - table->record[0]),
+             sizeof(applied_epoch));
+      DBUG_PRINT("info", ("Recording application of local server %u epoch %llu "
+                          " which is %s.",
+                          sid, applied_epoch,
+                          (applied_epoch > g_ndb_status_max_rep_epoch)?
+                          " new highest." : " older than previously applied"));
+      if (applied_epoch > g_ndb_status_max_rep_epoch)
+      {
+        /* 
+           Store new highest epoch in thdvar.  If we commit successfully
+           then this becomes the new global max
+        */
+        m_thd_ndb->m_max_replicated_epoch = applied_epoch;
+      }
     }
   }
 #endif /* HAVE_NDB_BINLOG */
@@ -3665,10 +3848,16 @@ int ha_ndbcluster::ndb_write_row(uchar *
   NdbTransaction *trans;
   uint32 part_id;
   int error;
-  NdbOperation::SetValueSpec sets[2];
+  NdbOperation::SetValueSpec sets[3];
   Uint32 num_sets= 0;
   DBUG_ENTER("ha_ndbcluster::ndb_write_row");
 
+  if (thd_ndb->m_slave_thread)
+  {
+    check_slave_status(thd);
+    g_ndb_slave_state.write_row_count++;
+  }
+
   has_auto_increment= (table->next_number_field && record == table->record[0]);
 
   if (has_auto_increment && table_share->primary_key != MAX_KEY) 
@@ -3790,6 +3979,16 @@ int ha_ndbcluster::ndb_write_row(uchar *
   eventSetAnyValue(thd, &options); 
   bool need_flush= add_row_check_if_batch_full(thd_ndb);
 
+  const Uint32 authorValue = 1;
+  if ((thd->slave_thread) &&
+      (m_table->getExtraRowAuthorBits()))
+  {
+    /* Set author to indicate slave updated last */
+    sets[num_sets].column= NdbDictionary::Column::ROW_AUTHOR;
+    sets[num_sets].value= &authorValue;
+    num_sets++;
+  } 
+
   if (m_user_defined_partitioning)
   {
     options.optionsPresent |= NdbOperation::OperationOptions::OO_PARTITION_ID;
@@ -3873,6 +4072,8 @@ int ha_ndbcluster::ndb_write_row(uchar *
         
         Ndb_exceptions_data ex_data;
         ex_data.share= m_share;
+        ex_data.key_rec= key_rec;
+        ex_data.op_type= WRITE_ROW;
         /*
           We need to save the row data for possible conflict resolution after
           execute().
@@ -3907,6 +4108,8 @@ int ha_ndbcluster::ndb_write_row(uchar *
 
       Ndb_exceptions_data ex_data;
       ex_data.share= m_share;
+      ex_data.key_rec= key_rec;
+      ex_data.op_type= WRITE_ROW;
       /*
         We need to save the row data for possible conflict resolution after
         execute().
@@ -4142,7 +4345,7 @@ ha_ndbcluster::row_conflict_fn_max(const
    */
   r= code->branch_gt(RegNewValue, RegCurrentValue, label_0);
   DBUG_ASSERT(r == 0);
-  r= code->interpret_exit_nok(error_conflict_fn_max_violation);
+  r= code->interpret_exit_nok(error_conflict_fn_violation);
   DBUG_ASSERT(r == 0);
   r= code->def_label(label_0);
   DBUG_ASSERT(r == 0);
@@ -4227,7 +4430,7 @@ ha_ndbcluster::row_conflict_fn_old(const
    */
   r= code->branch_eq(RegOldValue, RegCurrentValue, label_0);
   DBUG_ASSERT(r == 0);
-  r= code->interpret_exit_nok(error_conflict_fn_old_violation);
+  r= code->interpret_exit_nok(error_conflict_fn_violation);
   DBUG_ASSERT(r == 0);
   r= code->def_label(label_0);
   DBUG_ASSERT(r == 0);
@@ -4238,6 +4441,66 @@ ha_ndbcluster::row_conflict_fn_old(const
   return r;
 }
 
+/**
+  CFT_NDB_EPOCH
+
+  To perform conflict detection, an interpreted program is used to read
+  the existing row's epoch (if present) and compare it with the current
+  maximum replicated epoch.
+  If the row has a higher epoch than the current maximum replicated epoch
+  then it has been updated in conflict with this replication event.
+  In this case an error for this operation (9999) will be raised,
+  and new row will not be applied. The error codes for the operations will
+  be checked on return.  For this to work is is vital that the operation
+  is run with ignore error option.
+*/
+int
+ha_ndbcluster::row_conflict_fn_epoch(NdbInterpretedCode *code)
+{
+  DBUG_PRINT("info", ("interpreted update/delete check that "
+                      "if locally updated last, "
+                      "ROW$GCI64 <= Maximum Replicated Epoch (%llu)",
+                      g_ndb_status_max_rep_epoch));
+
+  const uint label_0= 0;
+  const Uint32 
+    RegAuthor= 1, RegZero= 2, 
+    RegMaxRepEpoch= 1, RegRowEpoch= 2;
+  int r;
+
+  r= code->load_const_u32(RegZero, 0);
+  assert(r == 0);
+  r= code->read_attr(RegAuthor, NdbDictionary::Column::ROW_AUTHOR);
+  assert(r == 0);
+  /* If last author was not local, assume no conflict */ 
+  r= code->branch_ne(RegZero, RegAuthor, label_0);
+  assert(r == 0);
+
+  /*
+   * Load registers RegMaxRepEpoch and RegRowEpoch
+   */
+  r= code->load_const_u64(RegMaxRepEpoch, g_ndb_status_max_rep_epoch);
+  assert(r == 0);
+  r= code->read_attr(RegRowEpoch, NdbDictionary::Column::ROW_GCI64);
+  assert(r == 0);
+
+  /*
+   * if RegRowEpoch <= RegMaxRepEpoch goto label_0
+   * else raise error for this row
+   */
+  r= code->branch_le(RegRowEpoch, RegMaxRepEpoch, label_0);
+  assert(r == 0);
+  r= code->interpret_exit_nok(error_conflict_fn_violation);
+  assert(r == 0);
+  r= code->def_label(label_0);
+  assert(r == 0);
+  r= code->interpret_exit_ok();
+  assert(r == 0);
+  r= code->finalise();
+  assert(r == 0);
+  return r;
+}
+
 int
 ha_ndbcluster::update_row_conflict_fn(enum_conflict_fn_type cft,
                                       const uchar *old_data,
@@ -4250,7 +4513,10 @@ ha_ndbcluster::update_row_conflict_fn(en
     return row_conflict_fn_max(new_data, code);
   case CFT_NDB_OLD:
     return row_conflict_fn_old(old_data, code);
+  case CFT_NDB_EPOCH:
+    return row_conflict_fn_epoch(code);
   case CFT_NDB_UNDEF:
+  case CFT_NUMBER_OF_CFTS:
     abort();
   }
   DBUG_ASSERT(false);
@@ -4273,6 +4539,11 @@ ha_ndbcluster::write_row_conflict_fn(enu
       already exists
      */
     return 1;
+  case CFT_NDB_EPOCH:
+    /*
+      Detect if tuple already exists
+    */
+    return 1;
   case CFT_NDB_UNDEF:
     abort();
   }
@@ -4307,12 +4578,146 @@ ha_ndbcluster::delete_row_conflict_fn(en
   }
   case CFT_NDB_OLD:
     return row_conflict_fn_old(old_data, code);
+  case CFT_NDB_EPOCH:
+    return row_conflict_fn_epoch(code);
   case CFT_NDB_UNDEF:
+  case CFT_NUMBER_OF_CFTS:
     abort();
   }
   DBUG_ASSERT(false);
   return 1;
 }
+
+int
+handle_row_conflict_fn_epoch(NDB_CONFLICT_FN_SHARE* cfn_share,
+                             const NdbRecord* key_rec,
+                             const uchar* pk_row,
+                             enum_conflicting_op_type op_type,
+                             enum_conflict_cause conflict_cause,
+                             const NdbError& conflict_error,
+                             NdbTransaction* conflict_trans,
+                             NdbError& err)
+{
+  DBUG_ENTER("handle_row_conflict_fn_epoch");
+  /* A conflict has been detected between an applied replicated operation
+   * and the data in the DB.
+   * The attempt to change the local DB will have been rejected.
+   * We now take steps to generate a refresh Binlog event so that
+   * other clusters will be re-aligned.
+   */
+  DBUG_PRINT("info", ("Conflict on table %s.  Operation type : %s, "
+                      "conflict cause :%s, conflict error : %u : %s",
+                      cfn_share->m_tab->getName(),
+                      ((op_type == WRITE_ROW)? "WRITE_ROW":
+                       (op_type == UPDATE_ROW)? "UPDATE_ROW":
+                       "DELETE_ROW"),
+                      ((conflict_cause == ROW_ALREADY_EXISTS)?"ROW_ALREADY_EXISTS":
+                       (conflict_cause == ROW_DOES_NOT_EXIST)?"ROW_DOES_NOT_EXIST":
+                       "ROW_IN_CONFLICT"),
+                      conflict_error.code,
+                      conflict_error.message));
+
+  assert(cfn_share->m_tab != NULL);
+  assert(key_rec != NULL);
+  assert(pk_row != NULL);
+  
+  /* When the slave splits an epoch into batches, a conflict row detected
+   * and refreshed in an early batch can be written to by operations in 
+   * a later batch.  As the operations will not have applied, and the
+   * row has already been refreshed, we need not attempt to refresh
+   * it again
+   */
+  if ((conflict_cause == ROW_IN_CONFLICT) &&
+      (conflict_error.code == (int) error_op_after_refresh_op))
+  {
+    /* Attempt to apply an operation after the row was refreshed
+     * Ignore the error
+     */
+    DBUG_PRINT("info", ("Operation after refresh error - ignoring"));
+    DBUG_RETURN(0);
+  }
+
+  /* When a delete operation finds that the row does not exist, it indicates
+   * a DELETE vs DELETE conflict.  If we refresh the row then we can get 
+   * non deterministic behaviour depending on slave batching as follows :
+   *   Row is deleted
+   *
+   *     Case 1
+   *       Slave applied DELETE, INSERT in 1 batch
+   *
+   *         After first batch, the row is present (due to INSERT), it is
+   *         refreshed.
+   * 
+   *     Case 2
+   *       Slave applied DELETE in 1 batch, INSERT in 2nd batch
+   *         
+   *         After first batch, the row is not present, it is refreshed
+   *         INSERT is then rejected.
+   *
+   * The problem of not being able to 'record' a DELETE vs DELETE conflict
+   * is known.  We attempt at least to give consistent behaviour for 
+   * DELETE vs DELETE conflicts by : 
+   *   NOT refreshing a row when a DELETE vs DELETE conflict is detected
+   * This should map all batching scenarios onto Case1.
+   */
+  if ((op_type == DELETE_ROW) &&
+      (conflict_cause == ROW_DOES_NOT_EXIST))
+  {
+    DBUG_PRINT("info", ("Delete vs Delete detected, NOT refreshing"));
+    DBUG_RETURN(0);
+  }
+
+  /* Create a refresh to operation to realign other clusters */
+  // TODO AnyValue
+  // TODO Do we ever get non-PK key?
+  //      Keyless table?
+  //      Unique index
+  const NdbOperation* refresh_op= conflict_trans->refreshTuple(key_rec, 
+                                                               (const char*) pk_row);
+  
+  if (!refresh_op)
+  {
+    err= conflict_trans->getNdbError();
+    DBUG_RETURN(1);
+  }
+
+  DBUG_RETURN(0);
+}
+
+int
+handle_row_conflict(enum_conflict_fn_type cft,
+                    NDB_CONFLICT_FN_SHARE* cfn_share,
+                    const NdbRecord* key_rec,
+                    const uchar* pk_row,
+                    enum_conflicting_op_type op_type,
+                    enum_conflict_cause conflict_cause,
+                    const NdbError& conflict_error,
+                    NdbTransaction* conflict_trans,
+                    NdbError& err)
+{
+  switch (cft) {
+  case CFT_NDB_MAX:
+  case CFT_NDB_MAX_DEL_WIN:
+  case CFT_NDB_OLD:
+    /* No special handling */
+    return 0;
+  case CFT_NDB_EPOCH:
+    return handle_row_conflict_fn_epoch(cfn_share,
+                                        key_rec,
+                                        pk_row,
+                                        op_type,
+                                        conflict_cause,
+                                        conflict_error,
+                                        conflict_trans,
+                                        err);
+  case CFT_NDB_UNDEF:
+  case CFT_NUMBER_OF_CFTS:
+    abort();
+  }
+  assert(false);
+  return 1;
+}
+
 #endif /* HAVE_NDB_BINLOG */
 
 /**
@@ -4429,10 +4834,18 @@ int ha_ndbcluster::ndb_update_row(const 
                    bitmap_is_overlapping(table->write_set, m_pk_bitmap_p) &&
                    primary_key_cmp(old_data, new_data));
   bool batch_allowed= is_bulk_update || (thd->options & OPTION_ALLOW_BATCH);
-  NdbOperation::SetValueSpec sets[1];
+  NdbOperation::SetValueSpec sets[2];
+  Uint32 num_sets= 0;
 
   DBUG_ENTER("ndb_update_row");
   DBUG_ASSERT(trans);
+
+  if (thd_ndb->m_slave_thread)
+  {
+    check_slave_status(thd);
+    g_ndb_slave_state.update_row_count++;
+  }
+
   /*
    * If IGNORE the ignore constraint violations on primary and unique keys,
    * but check that it is not part of INSERT ... ON DUPLICATE KEY UPDATE
@@ -4531,11 +4944,9 @@ int ha_ndbcluster::ndb_update_row(const 
       func_value_uint32= INT_MAX32;
     else
       func_value_uint32= (uint32)func_value;
-    sets[0].column= get_partition_id_column();
-    sets[0].value= &func_value_uint32;
-    options.optionsPresent|= NdbOperation::OperationOptions::OO_SETVALUE;
-    options.extraSetValues= sets;
-    options.numExtraSetValues= 1;
+    sets[num_sets].column= get_partition_id_column();
+    sets[num_sets].value= &func_value_uint32;
+    num_sets++;
 
     if (!cursor)
     {
@@ -4548,6 +4959,23 @@ int ha_ndbcluster::ndb_update_row(const 
   
   bool need_flush= add_row_check_if_batch_full(thd_ndb);
 
+  const Uint32 authorValue = 1;
+  if ((thd->slave_thread) &&
+      (m_table->getExtraRowAuthorBits()))
+  {
+    /* Set author to indicate slave updated last */
+    sets[num_sets].column= NdbDictionary::Column::ROW_AUTHOR;
+    sets[num_sets].value= &authorValue;
+    num_sets++;
+  } 
+
+  if (num_sets)
+  {
+    options.optionsPresent|= NdbOperation::OperationOptions::OO_SETVALUE;
+    options.extraSetValues= sets;
+    options.numExtraSetValues= num_sets;
+  }
+
   if (cursor)
   {
     /*
@@ -4602,6 +5030,8 @@ int ha_ndbcluster::ndb_update_row(const 
 
       Ndb_exceptions_data ex_data;
       ex_data.share= m_share;
+      ex_data.key_rec= key_rec;
+      ex_data.op_type= UPDATE_ROW;
       /*
         We need to save the row data for possible conflict resolution after
         execute().
@@ -4725,6 +5155,12 @@ int ha_ndbcluster::ndb_delete_row(const 
   DBUG_ENTER("ndb_delete_row");
   DBUG_ASSERT(trans);
 
+  if (thd_ndb->m_slave_thread)
+  {
+    check_slave_status(thd);
+    g_ndb_slave_state.delete_row_count++;
+  }
+
   ha_statistic_increment(&SSV::ha_delete_count);
   m_rows_changed++;
 
@@ -4836,6 +5272,8 @@ int ha_ndbcluster::ndb_delete_row(const 
 
       Ndb_exceptions_data ex_data;
       ex_data.share= m_share;
+      ex_data.key_rec= key_rec;
+      ex_data.op_type= DELETE_ROW;
       /*
         We need to save the row data for possible conflict resolution after
         execute().
@@ -6146,6 +6584,7 @@ static int ndbcluster_update_apply_statu
 
 static void transaction_checks(THD *thd, Thd_ndb *thd_ndb)
 {
+  thd_ndb->m_slave_thread= thd->slave_thread;
   if (thd->lex->sql_command == SQLCOM_LOAD)
     thd_ndb->trans_options|= TNTO_TRANSACTIONS_OFF;
   else if (!thd->transaction.on)
@@ -6795,8 +7234,8 @@ static int ndbcluster_rollback(handlerto
     DBUG_RETURN(0);
   }
   thd_ndb->save_point_count= 0;
-  thd_ndb->m_max_violation_count= 0;
-  thd_ndb->m_old_violation_count= 0;
+  bzero(thd_ndb->m_violation_count, sizeof(thd_ndb->m_violation_count));
+  thd_ndb->m_max_replicated_epoch= 0;
   thd_ndb->m_conflict_fn_usage_count= 0;
   thd_ndb->m_unsent_bytes= 0;
   thd_ndb->m_execute_count++;
@@ -7462,6 +7901,62 @@ int ha_ndbcluster::create(const char *na
     ndbtab_g.reinit();
   }
 
+#ifdef HAVE_NDB_BINLOG
+  /* Read ndb_replication entry for this table, if any */
+  Uint32 binlog_flags;
+  st_conflict_fn_def* conflict_fn= NULL;
+  st_conflict_fn_arg args[MAX_CONFLICT_ARGS];
+  Uint32 num_args = MAX_CONFLICT_ARGS;
+
+  int rep_read_rc= ndbcluster_get_binlog_replication_info(thd,
+                                                          ndb,
+                                                          m_dbname,
+                                                          m_tabname,
+                                                          ::server_id,
+                                                          form,
+                                                          &binlog_flags,
+                                                          &conflict_fn,
+                                                          args,
+                                                          &num_args);
+  if (rep_read_rc != 0)
+  {
+    DBUG_RETURN(rep_read_rc);
+  }
+
+  /* Reset database name */
+  ndb->setDatabaseName(m_dbname);
+
+  if (conflict_fn != NULL)
+  {
+    switch(conflict_fn->type)
+    {
+    case CFT_NDB_EPOCH:
+    {
+      /* Default 6 extra Gci bits allows 2^6 == 64
+       * epochs / saveGCP, a comfortable default
+       */
+      Uint32 numExtraGciBits = 6;
+      Uint32 numExtraAuthorBits = 1;
+      
+      if ((num_args == 1) &&
+          (args[0].type == CFAT_EXTRA_GCI_BITS))
+      {
+        numExtraGciBits = args[0].extraGciBits;
+      }
+      DBUG_PRINT("info", ("Setting ExtraRowGciBits to %u, "
+                          "ExtraAuthorBits to %u",
+                          numExtraGciBits,
+                          numExtraAuthorBits));
+      
+      tab.setExtraRowGciBits(numExtraGciBits);
+      tab.setExtraRowAuthorBits(numExtraAuthorBits);
+    }
+    default:
+      break;
+    }
+  }
+#endif
+
   if ((dict->beginSchemaTrans() == -1))
   {
     DBUG_PRINT("info", ("Failed to start schema transaction"));
@@ -7848,8 +8343,18 @@ cleanup_failed:
     {
 #ifdef HAVE_NDB_BINLOG
       if (share)
-        ndbcluster_read_binlog_replication(thd, ndb, share, m_table,
-                                           ::server_id, form, TRUE);
+      {
+        /* Set the Binlogging information we retrieved above */
+        ndbcluster_apply_binlog_replication_info(thd,
+                                                 share,
+                                                 m_table,
+                                                 form,
+                                                 conflict_fn,
+                                                 args,
+                                                 num_args,
+                                                 TRUE, /* Do set binlog flags */
+                                                 binlog_flags);
+      }
 #endif
       String event_name(INJECTOR_EVENT_LEN);
       ndb_rep_event_name(&event_name, m_dbname, m_tabname,
@@ -10013,6 +10518,58 @@ static int ndb_wait_setup_func_impl(ulon
 
 extern int(*ndb_wait_setup_func)(ulong);
 
+int try_determine_server_ids(const char* inputStr,
+                             Vector<Uint32>& serverIds)
+{
+  serverIds.clear();
+  serverIds.push_back(::server_id);
+
+  if (inputStr)
+  {
+    while (*inputStr != 0)
+    {
+      char* nextChar;
+      Uint32 id = strtoul(inputStr, &nextChar, 0);
+      if (id == 0)
+      {
+        /* Bad conversion */
+        return -1;
+      }
+      {
+        /* Have a serverid, check that it's unique 
+         * Duplicates are ok, but are ignored
+         */
+        bool duplicate = false;
+        for (Uint32 i=0; i<serverIds.size(); i++)
+        {
+          if (id == serverIds[i])
+          {
+            duplicate = true;
+            break;
+          }
+        }
+        if (!duplicate)
+          serverIds.push_back(id);
+      }
+      
+      inputStr = nextChar;
+      switch (*nextChar)
+      {
+      case 0:
+        break;
+      case ',':
+        inputStr++;
+        break;
+      default:
+        /* Bad format */
+        return -2;
+      }
+    }
+  }
+  
+  return serverIds.size();
+}
+
 extern int ndb_dictionary_is_mysqld;
 extern pthread_mutex_t LOCK_plugin;
 
@@ -10075,6 +10632,25 @@ static int ndbcluster_init(void *p)
 
   (void) my_hash_init(&ndbcluster_open_tables,table_alias_charset,32,0,0,
                       (my_hash_get_key) ndbcluster_get_key,0,0);
+
+  {
+    /* 
+       Initialise the cluster_server_id structures from the command
+       line argument (if any).  This is required as the plugin 
+       framework doesn't use the update function when initialising
+       a variable from the command line!
+    */
+    int rc = try_determine_server_ids(opt_ndb_cluster_server_ids,
+                                      cluster_server_ids);
+    
+    if (unlikely(rc < 1))
+    {
+      sql_print_error("NDB: supplied ndb_cluster_server_ids parameter (%s) "
+                      "is invalid", opt_ndb_cluster_server_ids);
+      DBUG_RETURN(-1);
+    }
+  }
+
   /* start the ndb injector thread */
   if (ndbcluster_binlog_start())
   {
@@ -14276,6 +14852,77 @@ static int ndbcluster_fill_files_table(h
   DBUG_RETURN(0);
 }
 
+/* CUT + PASTE START */
+/*
+ * Following code copied from sql_plugin.cc::check_func_str()
+ */
+static int generic_check_func_str(THD *thd, struct st_mysql_sys_var *var,
+                                  void *save, st_mysql_value *value)
+{
+  char buff[STRING_BUFFER_USUAL_SIZE];
+  const char *str;
+  int length;
+
+  length= sizeof(buff);
+  if ((str= value->val_str(value, buff, &length)))
+    str= thd->strmake(str, length);
+  *(const char**)save= str;
+  return 0;
+}
+
+/*
+ * Following code copied from sql_plugin.cc::update_func_str()
+ * Hardcoded for PLUGIN_VAR_MEMALLOC case with check around
+ * my_free for initial case where the string is unset.
+ */
+static void generic_update_func_str_dynamic(THD *thd, struct st_mysql_sys_var *var,
+                                            void *tgt, const void *save)
+{
+  char *old= *(char **) tgt;
+  *(char **)tgt= my_strdup(*(char **) save, MYF(0));
+  if (old)
+    my_free(old, MYF(0));
+}
+/* CUT + PASTE END */
+
+static int check_ndb_cluster_server_ids(THD *thd, struct st_mysql_sys_var *var,
+                                        void *save, st_mysql_value *value)
+{
+  /* Call generic check code */
+  int rc = generic_check_func_str(thd, var, save, value);
+  
+  if (rc == 0)
+  {
+    /* Check that we are happy with the supplied string */
+    const char* str = *(const char**)save;
+    Vector<Uint32> testServerIds;
+    if (try_determine_server_ids(str,
+                                 testServerIds) < 0)
+    {
+      my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "ndb_cluster_server_ids", str);
+      rc = 1;
+    }
+  }
+  return rc;
+}
+
+static void update_ndb_cluster_server_ids(THD *thd, struct st_mysql_sys_var *var,
+                                          void *tgt, const void *save)
+{
+  /* Call generic update code */
+  generic_update_func_str_dynamic(thd, var, tgt, save);
+  
+  assert(tgt);
+  const char* str = *(const char**) tgt;
+  
+  /* Now compute the cluster serverids array values based on 
+   * the string
+   */
+  int result = try_determine_server_ids(str,
+                                        cluster_server_ids);
+  assert(result >= 0);
+}
+
 static int show_ndb_vars(THD *thd, SHOW_VAR *var, char *buff)
 {
   if (!check_ndb_in_thd(thd))
@@ -14307,6 +14954,7 @@ SHOW_VAR ndb_status_variables_export[]= 
   {"Ndb",          (char*) &show_ndb_vars,                 SHOW_FUNC},
   {"Ndb",          (char*) &ndb_status_variables_fixed,    SHOW_ARRAY},
   {"Ndb_conflict", (char*) &ndb_status_conflict_variables, SHOW_ARRAY},
+  {"Ndb_slave",    (char*) &ndb_status_variables_slave,    SHOW_ARRAY},
   {NullS, NullS, SHOW_LONG}
 };
 
@@ -14503,6 +15151,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 */
@@ -14540,6 +15199,16 @@ static MYSQL_SYSVAR_UINT(
   0                                 /* block */
 );
 
+static MYSQL_SYSVAR_STR(
+  cluster_server_ids,               /* name */
+  opt_ndb_cluster_server_ids,       /* var */
+  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,              
+  "Comma separated list of server ids of other MySQLDs "
+  "attached to this Cluster.",
+  check_ndb_cluster_server_ids,     /* check func. */
+  update_ndb_cluster_server_ids,    /* update func. */
+  NULL                              /* default */
+);
 
 static struct st_mysql_sys_var* system_variables[]= {
   MYSQL_SYSVAR(cache_check_time),
@@ -14569,9 +15238,11 @@ 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),
+  MYSQL_SYSVAR(cluster_server_ids),
 
   NULL
 };
@@ -14619,4 +15290,6 @@ mysql_declare_plugin(ndbcluster)
 }
 mysql_declare_plugin_end;
 
+template class Vector<NdbOperation*>;
+
 #endif

=== modified file 'sql/ha_ndbcluster.h'
--- a/sql/ha_ndbcluster.h	2010-09-15 18:38:13 +0000
+++ b/sql/ha_ndbcluster.h	2010-10-03 01:41:32 +0000
@@ -126,19 +126,69 @@ typedef enum {
   NSS_ALTERED 
 } NDB_SHARE_STATE;
 
-#ifdef HAVE_NDB_BINLOG
 enum enum_conflict_fn_type
 {
   CFT_NDB_UNDEF = 0
   ,CFT_NDB_MAX
   ,CFT_NDB_OLD
   ,CFT_NDB_MAX_DEL_WIN
+  ,CFT_NDB_EPOCH
+  ,CFT_NUMBER_OF_CFTS /* End marker */
+};
+
+#ifdef HAVE_NDB_BINLOG
+static const Uint32 MAX_CONFLICT_ARGS= 8;
+
+enum enum_conflict_fn_arg_type
+{
+  CFAT_END
+  ,CFAT_COLUMN_NAME
+  ,CFAT_EXTRA_GCI_BITS
+};
+
+struct st_conflict_fn_arg
+{
+  enum_conflict_fn_arg_type type;
+  const char *ptr;
+  uint32 len;
+  union
+  {
+    uint32 fieldno;      // CFAT_COLUMN_NAME
+    uint32 extraGciBits; // CFAT_EXTRA_GCI_BITS
+  };
 };
 
+struct st_conflict_fn_def
+{
+  const char *name;
+  enum_conflict_fn_type type;
+  enum enum_conflict_fn_arg_type arg_type;
+  bool optional;
+};
+
+/* What type of operation was issued */
+enum enum_conflicting_op_type
+{                /* NdbApi          */
+  WRITE_ROW,     /* insert (!write) */
+  UPDATE_ROW,    /* update          */
+  DELETE_ROW     /* delete          */
+};
+
+/* What sort of conflict was found */
+enum enum_conflict_cause
+{
+  ROW_ALREADY_EXISTS,
+  ROW_DOES_NOT_EXIST,
+  ROW_IN_CONFLICT
+};
+  
+
 /* NdbOperation custom data which points out handler and record. */
 struct Ndb_exceptions_data {
   struct st_ndbcluster_share *share;
+  const NdbRecord* key_rec;
   const uchar* row;
+  enum_conflicting_op_type op_type;
 };
 
 typedef struct st_ndbcluster_conflict_fn_share {
@@ -151,6 +201,7 @@ typedef struct st_ndbcluster_conflict_fn
   uint8 unused;
   uint16 m_offset[16];
 
+  const NdbDictionary::Table *m_tab;
   const NdbDictionary::Table *m_ex_tab;
   uint32 m_count;
 } NDB_CONFLICT_FN_SHARE;
@@ -330,6 +381,7 @@ class Thd_ndb 
   bool m_error;
   bool m_slow_path;
   bool m_force_send;
+  bool m_slave_thread;
 
   int m_error_code;
   query_id_t m_query_id; /* query id whn m_error_code was set */
@@ -351,8 +403,7 @@ class Thd_ndb 
   uint m_batch_size;
 
   uint m_execute_count;
-  uint m_max_violation_count;
-  uint m_old_violation_count;
+  uint m_violation_count[CFT_NUMBER_OF_CFTS];
   uint m_conflict_fn_usage_count;
 
   uint m_scan_count;
@@ -365,6 +416,8 @@ class Thd_ndb 
   uint global_schema_lock_count;
   uint global_schema_lock_error;
 
+  Uint64 m_max_replicated_epoch;
+
   unsigned m_connect_count;
   bool valid_ndb(void);
   bool recycle_ndb(THD* thd);
@@ -593,6 +646,7 @@ private:
                           NdbInterpretedCode *);
   int row_conflict_fn_old(const uchar *old_data,
                           NdbInterpretedCode *);
+  int row_conflict_fn_epoch(NdbInterpretedCode *);
 #endif
   void setup_key_ref_for_ndb_record(const NdbRecord **key_rec,
                                     const uchar **key_row,
@@ -777,6 +831,8 @@ private:
   int start_statement(THD *thd, Thd_ndb *thd_ndb, uint table_count);
   int init_handler_for_statement(THD *thd);
 
+  void check_slave_status(THD* thd);
+
   Thd_ndb *m_thd_ndb;
   NdbScanOperation *m_active_cursor;
   const NdbDictionary::Table *m_table;

=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc	2010-09-29 11:01:55 +0000
+++ b/sql/ha_ndbcluster_binlog.cc	2010-10-03 01:41:32 +0000
@@ -30,6 +30,9 @@
 #include <ndbapi/ndb_cluster_connection.hpp>
 #include <util/NdbAutoPtr.hpp>
 #include <portlib/NdbTick.h>
+#include "slave.h"
+#include "rpl_mi.h"
+#include <util/Vector.hpp>
 
 #ifdef ndb_dynamite
 #undef assert
@@ -42,8 +45,11 @@ 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;
+extern Uint64 g_ndb_status_max_rep_epoch;
+extern Vector<Uint32> cluster_server_ids;
 
 /*
   defines for cluster replication table names
@@ -131,6 +137,10 @@ pthread_mutex_t ndb_schema_share_mutex;
 extern my_bool opt_log_slave_updates;
 static my_bool g_ndb_log_slave_updates;
 
+#ifdef HAVE_NDB_BINLOG
+static Uint32 g_ndb_slave_sql_run_id = 0xffffffff;
+#endif
+
 /* Schema object distribution handling */
 HASH ndb_schema_objects;
 typedef struct st_ndb_schema_object {
@@ -796,6 +806,9 @@ static void ndbcluster_reset_slave(THD *
     thd->main_da.reset_diagnostics_area();
   }
 
+  /* Reset Ndb_slave_max_replicated_epoch */
+  g_ndb_status_max_rep_epoch = 0;
+
   DBUG_VOID_RETURN;
 }
 
@@ -3635,18 +3648,13 @@ inline void slave_reset_conflict_fn(NDB_
   }
 }
 
-static int
-slave_set_resolve_fn(THD *thd, NDB_SHARE *share,
-                     const NDBTAB *ndbtab, uint field_index,
-                     enum_conflict_fn_type type, TABLE *table)
+static uint
+slave_check_resolve_col_type(const NDBTAB *ndbtab,
+                             uint field_index)
 {
-  DBUG_ENTER("slave_set_resolve_fn");
-
-  Thd_ndb *thd_ndb= get_thd_ndb(thd);
-  Ndb *ndb= thd_ndb->ndb;
-  NDBDICT *dict= ndb->getDictionary();
+  DBUG_ENTER("slave_check_resolve_col_type");
   const NDBCOL *c= ndbtab->getColumn(field_index);
-  uint sz;
+  uint sz= 0;
   switch (c->getType())
   {
   case  NDBCOL::Unsigned:
@@ -3662,10 +3670,22 @@ slave_set_resolve_fn(THD *thd, NDB_SHARE
   default:
     DBUG_PRINT("info", ("resolve column %u has wrong type",
                         field_index));
-    slave_reset_conflict_fn(share);
-    DBUG_RETURN(-1);
     break;
   }
+  DBUG_RETURN(sz);
+}
+
+static int
+slave_set_resolve_fn(THD *thd, NDB_SHARE *share,
+                     const NDBTAB *ndbtab, uint field_index,
+                     uint resolve_col_sz, enum_conflict_fn_type type, 
+                     TABLE *table)
+{
+  DBUG_ENTER("slave_set_resolve_fn");
+
+  Thd_ndb *thd_ndb= get_thd_ndb(thd);
+  Ndb *ndb= thd_ndb->ndb;
+  NDBDICT *dict= ndb->getDictionary();
 
   NDB_CONFLICT_FN_SHARE *cfn_share= share->m_cfn_share;
   if (cfn_share == NULL)
@@ -3674,9 +3694,10 @@ slave_set_resolve_fn(THD *thd, NDB_SHARE
       alloc_root(&share->mem_root, sizeof(NDB_CONFLICT_FN_SHARE));
     slave_reset_conflict_fn(share);
   }
-  cfn_share->m_resolve_size= sz;
+  cfn_share->m_resolve_size= resolve_col_sz;
   cfn_share->m_resolve_column= field_index;
   cfn_share->m_resolve_cft= type;
+  cfn_share->m_tab= ndbtab;
 
   {
     /* get exceptions table */
@@ -3735,7 +3756,10 @@ slave_set_resolve_fn(THD *thd, NDB_SHARE
           cfn_share->m_pk_cols= nkey;
           ndbtab_g.release();
           if (opt_ndb_extra_logging)
-            sql_print_information("NDB Slave: log exceptions to %s",
+            sql_print_information("NDB Slave: Table %s.%s logging exceptions to %s.%s",
+                                  table->s->db.str, 
+                                  table->s->table_name.str,
+                                  table->s->db.str, 
                                   ex_tab_name);
         }
         else
@@ -3752,76 +3776,44 @@ slave_set_resolve_fn(THD *thd, NDB_SHARE
   DBUG_RETURN(0);
 }
 
-enum enum_conflict_fn_arg_type
-{
-  CFAT_END
-  ,CFAT_COLUMN_NAME
-};
-struct st_conflict_fn_arg
-{
-  enum_conflict_fn_arg_type type;
-  const char *ptr;
-  uint32 len;
-  uint32 fieldno; // CFAT_COLUMN_NAME
-};
-struct st_conflict_fn_def
-{
-  const char *name;
-  enum_conflict_fn_type type;
-  enum enum_conflict_fn_arg_type arg_type;
-};
+
 static struct st_conflict_fn_def conflict_fns[]=
 {
-   { "NDB$MAX_DELETE_WIN", CFT_NDB_MAX_DEL_WIN, CFAT_COLUMN_NAME }
-  ,{ NULL,                 CFT_NDB_MAX_DEL_WIN, CFAT_END }
-  ,{ "NDB$MAX", CFT_NDB_MAX,   CFAT_COLUMN_NAME }
-  ,{ NULL,      CFT_NDB_MAX,   CFAT_END }
-  ,{ "NDB$OLD", CFT_NDB_OLD,   CFAT_COLUMN_NAME }
-  ,{ NULL,      CFT_NDB_OLD,   CFAT_END }
+  { "NDB$MAX_DELETE_WIN", CFT_NDB_MAX_DEL_WIN, CFAT_COLUMN_NAME, false }
+  ,{ NULL,                 CFT_NDB_MAX_DEL_WIN, CFAT_END, false }
+  ,{ "NDB$MAX", CFT_NDB_MAX,   CFAT_COLUMN_NAME, false }
+  ,{ NULL,      CFT_NDB_MAX,   CFAT_END, false }
+  ,{ "NDB$OLD", CFT_NDB_OLD,   CFAT_COLUMN_NAME, false }
+  ,{ NULL,      CFT_NDB_OLD,   CFAT_END, false }
+  ,{ "NDB$EPOCH", CFT_NDB_EPOCH, CFAT_EXTRA_GCI_BITS, true }
+  ,{ NULL,        CFT_NDB_EPOCH, CFAT_END, false }
 };
 static unsigned n_conflict_fns=
 sizeof(conflict_fns) / sizeof(struct st_conflict_fn_def);
 
-static int
-set_conflict_fn(THD *thd, NDB_SHARE *share,
-                const NDBTAB *ndbtab,
-                const NDBCOL *conflict_col,
-                char *conflict_fn,
-                char *msg, uint msg_len,
-                TABLE *table)
-{
-  DBUG_ENTER("set_conflict_fn");
-  uint len= 0;
-  switch (conflict_col->getArrayType())
-  {
-  case NDBCOL::ArrayTypeShortVar:
-    len= *(uchar*)conflict_fn;
-    conflict_fn++;
-    break;
-  case NDBCOL::ArrayTypeMediumVar:
-    len= uint2korr(conflict_fn);
-    conflict_fn+= 2;
-    break;
-  default:
-    break;
-  }
-  conflict_fn[len]= '\0';
-  const char *ptr= conflict_fn;
+int
+parse_conflict_fn_spec(const char* conflict_fn_spec,
+                       st_conflict_fn_def** conflict_fn,
+                       st_conflict_fn_arg* args,
+                       Uint32* max_args,
+                       const TABLE* table,
+                       char *msg, uint msg_len)
+{
+  DBUG_ENTER("parse_conflict_fn_spec");
+
+  Uint32 no_args = 0;
+  const char *ptr= conflict_fn_spec;
   const char *error_str= "unknown conflict resolution function";
   /* remove whitespace */
   while (*ptr == ' ' && *ptr != '\0') ptr++;
 
-  const unsigned MAX_ARGS= 8;
-  unsigned no_args= 0;
-  struct st_conflict_fn_arg args[MAX_ARGS];
-
-  DBUG_PRINT("info", ("parsing %s", conflict_fn));
+  DBUG_PRINT("info", ("parsing %s", conflict_fn_spec));
 
   for (unsigned i= 0; i < n_conflict_fns; i++)
   {
     struct st_conflict_fn_def &fn= conflict_fns[i];
     if (fn.name == NULL)
-      continue;
+      continue;  /* Skip argument entries */
 
     uint len= strlen(fn.name);
     if (strncmp(ptr, fn.name, len))
@@ -3847,6 +3839,13 @@ set_conflict_fn(THD *thd, NDB_SHARE *sha
     /* find all arguments */
     for (;;)
     {
+      if (no_args >= *max_args)
+      {
+        error_str= "too many arguments";
+        DBUG_PRINT("info", ("parse error %s", error_str));
+        break;
+      }
+
       /* expected type */
       enum enum_conflict_fn_arg_type type=
         conflict_fns[i+no_args].arg_type;
@@ -3862,16 +3861,30 @@ set_conflict_fn(THD *thd, NDB_SHARE *sha
       }
 
       /* arg */
+      /* Todo : Should support comma as an arg separator? */
       const char *start_arg= ptr;
       while (*ptr != ')' && *ptr != ' ' && *ptr != '\0') ptr++;
       const char *end_arg= ptr;
 
+      bool optional_arg = conflict_fns[i+no_args].optional;
       /* any arg given? */
       if (start_arg == end_arg)
       {
-        error_str= "missing function argument";
-        DBUG_PRINT("info", ("parse error %s", error_str));
-        break;
+        if (!optional_arg)
+        {
+          error_str= "missing function argument";
+          DBUG_PRINT("info", ("parse error %s", error_str));
+          break;
+        }
+        else
+        {
+          /* Arg was optional, and not present
+           * Must be at end of args, finish parsing
+           */
+          args[no_args].type= CFAT_END;
+          error_str= NULL;
+          break;
+        }
       }
 
       uint len= end_arg - start_arg;
@@ -3882,6 +3895,7 @@ set_conflict_fn(THD *thd, NDB_SHARE *sha
  
       DBUG_PRINT("info", ("found argument %s %u", start_arg, len));
 
+      bool arg_processing_error = false;
       switch (type)
       {
       case CFAT_COLUMN_NAME:
@@ -3902,10 +3916,31 @@ set_conflict_fn(THD *thd, NDB_SHARE *sha
         }
         break;
       }
+      case CFAT_EXTRA_GCI_BITS:
+      {
+        /* Map string to number and check it's in range etc */
+        char* end_of_arg = (char*) end_arg;
+        Uint32 bits = strtoul(start_arg, &end_of_arg, 0);
+        DBUG_PRINT("info", ("Using %u as the number of extra bits", bits));
+
+        if (bits > 31)
+        {
+          arg_processing_error= true;
+          error_str= "Too many extra Gci bits";
+          DBUG_PRINT("info", ("%s", error_str));
+          break;
+        }
+        /* Num bits seems ok */
+        args[no_args].extraGciBits = bits;
+        break;
+      }
       case CFAT_END:
         abort();
       }
 
+      if (arg_processing_error)
+        break;
+
       no_args++;
     }
 
@@ -3932,44 +3967,128 @@ set_conflict_fn(THD *thd, NDB_SHARE *sha
       error_str= "garbage in the end";
       break;
     }
+    /* Update ptrs to conflict fn + # of args */
+    *conflict_fn = &conflict_fns[i];
+    *max_args = no_args;
 
-    /* setup the function */
-    switch (fn.type)
-    {
-    case CFT_NDB_MAX:
-    case CFT_NDB_OLD:
-    case CFT_NDB_MAX_DEL_WIN:
-      if (args[0].fieldno == (uint32)-1)
-        break;
-      if (slave_set_resolve_fn(thd, share, ndbtab, args[0].fieldno,
-                               fn.type, table))
-      {
-        /* wrong data type */
-        my_snprintf(msg, msg_len,
-                 "column '%s' has wrong datatype",
-                 table->s->field[args[0].fieldno]->field_name);
-        DBUG_PRINT("info", ("%s", msg));
-        DBUG_RETURN(-1);
-      }
-      if (opt_ndb_extra_logging)
-      {
-        sql_print_information("NDB Slave: conflict_fn %s on attribute %s",
-                              fn.name,
-                              table->s->field[args[0].fieldno]->field_name);
-      }
-      break;
-    case CFT_NDB_UNDEF:
-      abort();
-    }
     DBUG_RETURN(0);
   }
   /* parse error */
   my_snprintf(msg, msg_len, "%s, %s at '%s'",
-           conflict_fn, error_str, ptr);
+           conflict_fn_spec, error_str, ptr);
   DBUG_PRINT("info", ("%s", msg));
   DBUG_RETURN(-1);
 }
 
+static int
+setup_conflict_fn(THD *thd, NDB_SHARE *share,
+                  const NDBTAB *ndbtab,
+                  char *msg, uint msg_len,
+                  TABLE *table,
+                  const st_conflict_fn_def* conflict_fn,
+                  const st_conflict_fn_arg* args,
+                  const Uint32 num_args)
+{
+  DBUG_ENTER("setup_conflict_fn");
+
+  /* setup the function */
+  switch (conflict_fn->type)
+  {
+  case CFT_NDB_MAX:
+  case CFT_NDB_OLD:
+  case CFT_NDB_MAX_DEL_WIN:
+  {
+    if (num_args != 1)
+    {
+      my_snprintf(msg, msg_len,
+                  "Incorrect arguments to conflict function");
+      DBUG_PRINT("info", ("%s", msg));
+      DBUG_RETURN(-1);
+    }
+    
+    uint resolve_col_sz= 0;
+    
+    if (0 == (resolve_col_sz = 
+              slave_check_resolve_col_type(ndbtab, args[0].fieldno)))
+    {
+      /* wrong data type */
+      slave_reset_conflict_fn(share);
+      my_snprintf(msg, msg_len,
+                  "column '%s' has wrong datatype",
+                  table->s->field[args[0].fieldno]->field_name);
+      DBUG_PRINT("info", ("%s", msg));
+      DBUG_RETURN(-1);
+    }
+    
+    if (slave_set_resolve_fn(thd, share, ndbtab, 
+                             args[0].fieldno, resolve_col_sz,
+                             conflict_fn->type, table))
+    {
+      my_snprintf(msg, msg_len,
+                  "unable to setup conflict resolution using column '%s'",
+                  table->s->field[args[0].fieldno]->field_name);
+      DBUG_PRINT("info", ("%s", msg));
+      DBUG_RETURN(-1);
+    }
+    if (opt_ndb_extra_logging)
+    {
+       sql_print_information("NDB Slave: Table %s.%s using conflict_fn %s on attribute %s.",
+                             table->s->db.str, 
+                             table->s->table_name.str,
+                             conflict_fn->name,
+                             table->s->field[args[0].fieldno]->field_name);
+    }
+    break;
+  }
+  case CFT_NDB_EPOCH:
+  {
+    if (num_args > 1)
+    {
+      my_snprintf(msg, msg_len,
+                  "Too many arguments to conflict function");
+      DBUG_PRINT("info", ("%s", msg));
+      DBUG_RETURN(-1);
+    }
+    
+    /* Check that table has required extra meta-columns */
+    /* Todo : Could warn if extra gcibits is insufficient to 
+     * represent SavePeriod/EpochPeriod
+     */
+    if (ndbtab->getExtraRowGciBits() == 0)
+      sql_print_information("Ndb Slave : CFT_NDB_EPOCH, low epoch resolution");
+    if (ndbtab->getExtraRowAuthorBits() == 0)
+    {
+      my_snprintf(msg, msg_len, "No extra row author bits in table.");
+      DBUG_PRINT("info", ("%s", msg));
+      DBUG_RETURN(-1);
+    }
+    
+    if (slave_set_resolve_fn(thd, share, ndbtab, 
+                             0, // field_no
+                             0, // resolve_col_sz
+                             conflict_fn->type, table))
+    {
+      my_snprintf(msg, msg_len,
+                  "unable to setup conflict resolution");
+      DBUG_PRINT("info", ("%s", msg));
+      DBUG_RETURN(-1);
+    }
+    if (opt_ndb_extra_logging)
+    {
+      sql_print_information("NDB Slave: Table %s.%s using conflict_fn %s.",
+                            table->s->db.str, 
+                            table->s->table_name.str,
+                            conflict_fn->name);
+    }
+    break;
+  }
+  case CFT_NUMBER_OF_CFTS:
+  case CFT_NDB_UNDEF:
+    abort();
+  }
+  DBUG_RETURN(0);
+}
+
 static const char *ndb_rep_db= NDB_REP_DB;
 static const char *ndb_replication_table= NDB_REPLICATION_TABLE;
 static const char *nrt_db= "db";
@@ -3977,17 +4096,26 @@ static const char *nrt_table_name= "tabl
 static const char *nrt_server_id= "server_id";
 static const char *nrt_binlog_type= "binlog_type";
 static const char *nrt_conflict_fn= "conflict_fn";
+
+/* 
+   ndbcluster_read_replication_table
+
+   This function reads the information for the supplied table from
+   the mysql.ndb_replication table.
+   Where there is no information (or no table), defaults are 
+   returned.
+*/
 int
-ndbcluster_read_binlog_replication(THD *thd, Ndb *ndb,
-                                   NDB_SHARE *share,
-                                   const NDBTAB *ndbtab,
-                                   uint server_id,
-                                   TABLE *table,
-                                   bool do_set_binlog_flags)
+ndbcluster_read_replication_table(THD *thd, Ndb *ndb,
+                                  const char* db,
+                                  const char* table_name,
+                                  uint server_id,
+                                  Uint32* binlog_flags,
+                                  char** conflict_fn_spec,
+                                  char* conflict_fn_buffer,
+                                  Uint32 conflict_fn_buffer_len)
 {
-  DBUG_ENTER("ndbcluster_read_binlog_replication");
-  const char *db= share->db;
-  const char *table_name= share->table_name;
+  DBUG_ENTER("ndbcluster_read_binlog_replication_table");
   NdbError ndberror;
   int error= 0;
   const char *error_str= "<none>";
@@ -4001,8 +4129,8 @@ ndbcluster_read_binlog_replication(THD *
        dict->getNdbError().code == 4009))
   {
     DBUG_PRINT("info", ("No %s.%s table", ndb_rep_db, ndb_replication_table));
-    if (do_set_binlog_flags)
-      set_binlog_flags(share, NBT_DEFAULT);
+    *binlog_flags= NBT_DEFAULT;
+    *conflict_fn_spec= NULL;
     DBUG_RETURN(0);
   }
   const NDBCOL
@@ -4068,6 +4196,10 @@ ndbcluster_read_binlog_replication(THD *
     char *ndb_conflict_fn[2]= {ndb_conflict_fn_buf, ndb_conflict_fn_buf+sz};
     NdbOperation *op[2];
     uint32 i, id= 0;
+    /* Read generic row (server_id==0) and specific row (server_id == our id)
+     * from ndb_replication.
+     * Specific overrides generic, if present
+     */
     for (i= 0; i < 2; i++)
     {
       NdbOperation *_op;
@@ -4127,39 +4259,70 @@ ndbcluster_read_binlog_replication(THD *
     if (col_binlog_type_rec_attr[1] == NULL ||
         col_binlog_type_rec_attr[1]->isNULL())
     {
+      /* No specific value, use generic */
       col_binlog_type_rec_attr[1]= col_binlog_type_rec_attr[0];
       ndb_binlog_type[1]= ndb_binlog_type[0];
     }
     if (col_conflict_fn_rec_attr[1] == NULL ||
         col_conflict_fn_rec_attr[1]->isNULL())
     {
+      /* No specific value, use generic */
       col_conflict_fn_rec_attr[1]= col_conflict_fn_rec_attr[0];
       ndb_conflict_fn[1]= ndb_conflict_fn[0];
     }
 
-    if (do_set_binlog_flags)
+    if (col_binlog_type_rec_attr[1] == NULL ||
+        col_binlog_type_rec_attr[1]->isNULL())
+    {
+      DBUG_PRINT("info", ("No binlog flag value, using default"));
+      /* No value */
+      *binlog_flags= NBT_DEFAULT;
+    }
+    else
+    {
+      DBUG_PRINT("info", ("Taking binlog flag value from the table"));
+      *binlog_flags= (enum Ndb_binlog_type) ndb_binlog_type[1];
+    }
+
+    if (col_conflict_fn_rec_attr[1] == NULL ||
+        col_conflict_fn_rec_attr[1]->isNULL())
     {
-      if (col_binlog_type_rec_attr[1] == NULL ||
-          col_binlog_type_rec_attr[1]->isNULL())
-        set_binlog_flags(share, NBT_DEFAULT);
-      else
-        set_binlog_flags(share, (enum Ndb_binlog_type) ndb_binlog_type[1]);
+      /* No conflict function */
+      *conflict_fn_spec = NULL;
     }
-    if (table)
+    else 
     {
-      if (col_conflict_fn_rec_attr[1] == NULL ||
-          col_conflict_fn_rec_attr[1]->isNULL())
-        slave_reset_conflict_fn(share); /* no conflict_fn */
-      else if (set_conflict_fn(thd, share, ndbtab,
-                               col_conflict_fn, ndb_conflict_fn[1],
-                               tmp_buf, sizeof(tmp_buf), table))
+      const char* conflict_fn = ndb_conflict_fn[1];
+      uint len= 0;
+      switch (col_conflict_fn->getArrayType())
+      {
+      case NDBCOL::ArrayTypeShortVar:
+        len= *(uchar*)conflict_fn;
+        conflict_fn++;
+        break;
+      case NDBCOL::ArrayTypeMediumVar:
+        len= uint2korr(conflict_fn);
+        conflict_fn+= 2;
+        break;
+      default:
+        abort();
+      }
+      if ((len + 1) > conflict_fn_buffer_len)
       {
-        error_str= tmp_buf;
-        error= 1;
         ndb->closeTransaction(trans);
+        error= -2;
+        error_str= "Conflict function specification too long.";
         goto err;
       }
+      memcpy(conflict_fn_buffer, conflict_fn, len);
+      conflict_fn_buffer[len] = '\0';
+      *conflict_fn_spec = conflict_fn_buffer;
     }
+    
+    DBUG_PRINT("info", ("Retrieved Binlog flags : %u and function spec : %s",
+                        *binlog_flags, (*conflict_fn_spec != NULL ?*conflict_fn_spec:
+                                       "NULL")));
+
     ndb->closeTransaction(trans);
 
     DBUG_RETURN(0);
@@ -4168,14 +4331,7 @@ ndbcluster_read_binlog_replication(THD *
 err:
   DBUG_PRINT("info", ("error %d, error_str %s, ndberror.code %u",
                       error, error_str, ndberror.code));
-  if (error > 0)
-  {
-    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
-                        ER_CONFLICT_FN_PARSE_ERROR,
-                        ER(ER_CONFLICT_FN_PARSE_ERROR),
-                        error_str);
-  }
-  else if (error < 0)
+  if (error < 0)
   {
     char msg[FN_REFLEN];
     switch (error)
@@ -4207,8 +4363,9 @@ err:
                         ER(ER_ILLEGAL_HA_CREATE_OPTION),
                         ndbcluster_hton_name, msg);  
   }
-  if (do_set_binlog_flags)
-    set_binlog_flags(share, NBT_DEFAULT);
+  *binlog_flags= NBT_DEFAULT;
+  *conflict_fn_spec= NULL;
+
   if (ndberror.code && opt_ndb_extra_logging)
   {
     List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
@@ -4220,6 +4377,185 @@ err:
   }
   DBUG_RETURN(ndberror.code);
 }
+
+/*
+  ndbcluster_get_binlog_replication_info
+
+  This function retrieves the data for the given table
+  from the ndb_replication table.
+
+  If the table is not found, or the table does not exist,
+  then defaults are returned.
+*/
+int
+ndbcluster_get_binlog_replication_info(THD *thd, Ndb *ndb,
+                                       const char* db,
+                                       const char* table_name,
+                                       uint server_id,
+                                       const TABLE *table,
+                                       Uint32* binlog_flags,
+                                       st_conflict_fn_def** conflict_fn,
+                                       st_conflict_fn_arg* args,
+                                       Uint32* num_args)
+{
+  DBUG_ENTER("ndbcluster_get_binlog_replication_info");
+
+  /* Override for ndb_apply_status when logging */
+  if (opt_ndb_log_apply_status)
+  {
+    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.
+      */
+      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);
+      *binlog_flags = NBT_FULL;
+      *conflict_fn = NULL;
+      *num_args = 0;
+      DBUG_RETURN(0);
+    }
+  }
+
+  const Uint32 MAX_CONFLICT_FN_SPEC_LEN = 256; 
+  char conflict_fn_buffer[MAX_CONFLICT_FN_SPEC_LEN];
+  char* conflict_fn_spec;
+
+  if (ndbcluster_read_replication_table(thd,
+                                        ndb,
+                                        db,
+                                        table_name,
+                                        server_id,
+                                        binlog_flags,
+                                        &conflict_fn_spec,
+                                        conflict_fn_buffer,
+                                        MAX_CONFLICT_FN_SPEC_LEN) != 0)
+  {
+    DBUG_RETURN(ER_NDB_REPLICATION_SCHEMA_ERROR);
+  }
+
+  if (table != NULL)
+  {
+    if (conflict_fn_spec != NULL)
+    {
+      char tmp_buf[FN_REFLEN];
+      
+      if (parse_conflict_fn_spec(conflict_fn_spec,
+                                 conflict_fn,
+                                 args,
+                                 num_args,
+                                 table,
+                                 tmp_buf,
+                                 sizeof(tmp_buf)) != 0)
+      {
+        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+                            ER_CONFLICT_FN_PARSE_ERROR,
+                            ER(ER_CONFLICT_FN_PARSE_ERROR),
+                            tmp_buf);
+        DBUG_RETURN(ER_CONFLICT_FN_PARSE_ERROR);
+      }
+    }
+    else
+    {
+      /* No conflict function specified */
+      conflict_fn= NULL;
+      num_args= 0;
+    }
+  }
+
+  DBUG_RETURN(0);
+}
+
+int
+ndbcluster_apply_binlog_replication_info(THD *thd,
+                                         NDB_SHARE *share,
+                                         const NDBTAB* ndbtab,
+                                         TABLE* table,
+                                         const st_conflict_fn_def* conflict_fn,
+                                         const st_conflict_fn_arg* args,
+                                         Uint32 num_args,
+                                         bool do_set_binlog_flags,
+                                         Uint32 binlog_flags)
+{
+  DBUG_ENTER("ndbcluster_apply_binlog_replication_info");
+  char tmp_buf[FN_REFLEN];
+
+  if (do_set_binlog_flags)
+  {
+    DBUG_PRINT("info", ("Setting binlog flags to %u", binlog_flags));
+    set_binlog_flags(share, (enum Ndb_binlog_type)binlog_flags);
+  }
+    
+  if (conflict_fn != NULL)
+  {
+    if (setup_conflict_fn(thd, share,
+                          ndbtab,
+                          tmp_buf, sizeof(tmp_buf),
+                          table,
+                          conflict_fn,
+                          args,
+                          num_args) != 0)
+    {
+      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+                          ER_CONFLICT_FN_PARSE_ERROR,
+                          ER(ER_CONFLICT_FN_PARSE_ERROR),
+                          tmp_buf);
+      DBUG_RETURN(-1);
+    }
+  }
+  else
+  {
+    /* No conflict function specified */
+    slave_reset_conflict_fn(share);
+  }
+
+  DBUG_RETURN(0);
+}
+
+int
+ndbcluster_read_binlog_replication(THD *thd, Ndb *ndb,
+                                   NDB_SHARE *share,
+                                   const NDBTAB *ndbtab,
+                                   uint server_id,
+                                   TABLE *table,
+                                   bool do_set_binlog_flags)
+{
+  DBUG_ENTER("ndbcluster_read_binlog_replication");
+  Uint32 binlog_flags;
+  st_conflict_fn_def* conflict_fn= NULL;
+  st_conflict_fn_arg args[MAX_CONFLICT_ARGS];
+  Uint32 num_args = MAX_CONFLICT_ARGS;
+  
+  if ((ndbcluster_get_binlog_replication_info(thd, ndb,
+                                              share->db,
+                                              share->table_name,
+                                              server_id,
+                                              table,
+                                              &binlog_flags,
+                                              &conflict_fn,
+                                              args,
+                                              &num_args) != 0) ||
+      (ndbcluster_apply_binlog_replication_info(thd,
+                                                share,
+                                                ndbtab,
+                                                table,
+                                                conflict_fn,
+                                                args,
+                                                num_args,
+                                                do_set_binlog_flags,
+                                                binlog_flags) != 0))
+  {
+    DBUG_RETURN(-1);
+  }
+  
+  DBUG_RETURN(0);
+}
 #endif /* HAVE_NDB_BINLOG */
 
 bool
@@ -5371,7 +5707,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;
@@ -5380,15 +5717,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;
@@ -5397,43 +5768,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;
+    }
   }
 
   /* 
@@ -5480,8 +5885,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));
     {
@@ -5503,8 +5911,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));
     {
@@ -5544,8 +5955,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));
     {
@@ -6274,6 +6688,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)
       {
         /*
@@ -6319,6 +6734,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;
@@ -6472,7 +6888,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);
@@ -6511,17 +6927,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";
@@ -6816,4 +7249,169 @@ void ndbcluster_anyvalue_set_serverid(Ui
   anyValue |= (serverId & opt_server_id_mask); 
 }
 
+#ifdef HAVE_NDB_BINLOG
+extern Master_info *active_mi;
+#endif
+
+void 
+ha_ndbcluster::check_slave_status(THD* thd)
+{
+  DBUG_ENTER("check_slave_status");
+
+#ifdef HAVE_NDB_BINLOG
+  if (thd->slave_thread)
+  {
+    Uint32 runId = active_mi->rli.slave_run_id;
+    DBUG_PRINT("info", ("Slave SQL thread run id is %u",
+                        runId));
+    if (unlikely(runId != g_ndb_slave_sql_run_id))
+    {
+      DBUG_PRINT("info", ("Slave run id changed from %u, "
+                          "treating as Slave restart",
+                          g_ndb_slave_sql_run_id));
+      g_ndb_slave_sql_run_id = runId;
+
+      /* Always try to load the Max Replicated Epoch info
+       * first.
+       * Could be made optional if it's a problem
+       */
+      {
+        /* 
+           Load highest replicated epoch from a local
+           MySQLD from the cluster.
+        */
+        DBUG_PRINT("info", ("Loading applied epoch information from %s",
+                            NDB_APPLY_TABLE));
+        NdbError ndb_error;
+        Vector<Uint32> localServerIds;
+        Vector<NdbOperation*> epochReadOps;
+        Vector<Uint64> epochs;
+        Uint64 highestAppliedEpoch= 0;
+        
+        /* Copy from globals to minimise chance of race with variable-setter */
+        assert(cluster_server_ids.size() >= 1);
+        for (Uint32 i=0; i< cluster_server_ids.size(); i++)
+          localServerIds.push_back(cluster_server_ids[i]);
+
+        /* Vector.fill() sets size to passed arg + 1 */
+        epochs.fill(localServerIds.size()-1, highestAppliedEpoch);
+
+        while(1)
+        {
+          Ndb* ndb= check_ndb_in_thd(thd);
+          NDBDICT* dict= ndb->getDictionary();
+          NdbTransaction* trans= NULL;
+          ndb->setDatabaseName(NDB_REP_DB);
+          Ndb_table_guard ndbtab_g(dict, NDB_APPLY_TABLE);
+          
+          const NDBTAB* ndbtab= ndbtab_g.get_table();
+          if (unlikely(ndbtab == NULL))
+          {
+            ndb_error = dict->getNdbError();
+            break;
+          }
+          
+          trans= ndb->startTransaction();
+          if (unlikely(trans == NULL))
+          {
+            ndb_error = ndb->getNdbError();
+            break;
+          }
+          
+
+          for (Uint32 n=0; n < localServerIds.size(); n++)
+          {
+            NdbOperation* op= trans->getNdbOperation(ndbtab);
+            if (unlikely(op == NULL))
+            {
+              ndb_error = trans->getNdbError();
+              break;
+            }
+            
+            if (unlikely((op->readTuple(NdbOperation::LM_CommittedRead) != 0) ||
+                         (op->setAbortOption(NdbOperation::AO_IgnoreError) != 0) ||
+                         // TODO : ServerId column# constant
+                         (op->equal(Uint32(0), localServerIds[n]) != 0) ||
+                         // TODO : Epoch column# constant
+                         (op->getValue(1, (char*) &epochs[n]) == NULL)))
+            {
+              ndb_error = op->getNdbError();
+              break;
+            }
+            
+            epochReadOps.push_back(op);
+            DBUG_PRINT("info", ("Defined applied epoch read op for serverid %u",
+                                localServerIds[n]));
+          }
+          if (ndb_error.code != 0)
+            break;
+          
+          assert(epochReadOps.size() == localServerIds.size());
+          assert(epochs.size() == localServerIds.size());
+
+          if (trans->execute(NdbTransaction::Commit))
+          {
+            ndb_error= trans->getNdbError();
+            break;
+          }
+          
+          for (Uint32 n=0; n < localServerIds.size(); n++)
+          {
+            const NdbOperation* op = epochReadOps[n];
+            if (op->getNdbError().code == 0)
+            {
+              DBUG_PRINT("info", ("Cluster contains epoch %llu from serverid %u",
+                                  epochs[n], localServerIds[n]));
+              if (epochs[n] > highestAppliedEpoch)
+              {
+                DBUG_PRINT("info", ("New highest epoch is %llu", epochs[n]));
+                highestAppliedEpoch = epochs[n];
+              }
+            }
+            else
+            {
+              if (likely(op->getNdbError().code == 626))
+              {
+                DBUG_PRINT("info", ("No data present for serverid %u",
+                                    localServerIds[n]));
+              }
+              else
+              {
+                ndb_error = op->getNdbError();
+                break;
+              }
+            }
+          }
+          
+          trans->close();
+          break;
+        } // while(1);
+
+        if (ndb_error.code != 0)
+        {
+          sql_print_warning("NDB Slave : Could not determine maximum replicated epoch from %s.%s "
+                            "at Slave start, error %u %s",
+                            NDB_REP_DB,
+                            NDB_APPLY_TABLE,
+                            ndb_error.code, ndb_error.message);
+        }
+
+        /* 
+           Set Global status variable to the Highest Applied Epoch from 
+           the Cluster DB.
+           If none was found, this will be zero.
+        */
+        g_ndb_status_max_rep_epoch = highestAppliedEpoch;
+        sql_print_information("NDB Slave : MaxReplicatedEpoch set to %llu (%u/%u) at Slave start",
+                              g_ndb_status_max_rep_epoch,
+                              (Uint32)(g_ndb_status_max_rep_epoch >> 32),
+                              (Uint32)(g_ndb_status_max_rep_epoch & 0xffffffff));
+      } // Load highest replicated epoch
+    } // New Slave SQL thread run id
+  } // In slave SQL thread
+#endif
+  
+  DBUG_VOID_RETURN;
+}
+
 #endif

=== modified file 'sql/ha_ndbcluster_binlog.h'
--- a/sql/ha_ndbcluster_binlog.h	2010-07-02 11:01:48 +0000
+++ b/sql/ha_ndbcluster_binlog.h	2010-10-03 01:41:32 +0000
@@ -95,8 +95,7 @@ static const char *ha_ndb_ext=".ndb";
 #define NDB_EXCEPTIONS_TABLE_SUFFIX "$EX"
 #define NDB_EXCEPTIONS_TABLE_SUFFIX_LOWER "$ex"
 
-const uint error_conflict_fn_old_violation= 9998;
-const uint error_conflict_fn_max_violation= 9999;
+const uint error_conflict_fn_violation= 9999;
 #endif /* HAVE_NDB_BINLOG */
 
 
@@ -239,6 +238,26 @@ void ndb_rep_event_name(String *event_na
                         const char *db, const char *tbl, my_bool full);
 #ifdef HAVE_NDB_BINLOG
 int
+ndbcluster_get_binlog_replication_info(THD *thd, Ndb *ndb,
+                                       const char* db,
+                                       const char* table_name,
+                                       uint server_id,
+                                       const TABLE *table,
+                                       Uint32* binlog_flags,
+                                       st_conflict_fn_def** conflict_fn,
+                                       st_conflict_fn_arg* args,
+                                       Uint32* num_args);
+int
+ndbcluster_apply_binlog_replication_info(THD *thd,
+                                         NDB_SHARE *share,
+                                         const NDBTAB* ndbtab,
+                                         TABLE* table,
+                                         const st_conflict_fn_def* conflict_fn,
+                                         const st_conflict_fn_arg* args,
+                                         Uint32 num_args,
+                                         bool do_set_binlog_flags,
+                                         Uint32 binlog_flags);
+int
 ndbcluster_read_binlog_replication(THD *thd, Ndb *ndb,
                                    NDB_SHARE *share,
                                    const NDBTAB *ndbtab,

=== modified file 'storage/ndb/include/kernel/AttributeHeader.hpp'
--- a/storage/ndb/include/kernel/AttributeHeader.hpp	2010-01-28 15:16:46 +0000
+++ b/storage/ndb/include/kernel/AttributeHeader.hpp	2010-10-03 01:41:32 +0000
@@ -63,6 +63,17 @@ public:
   STATIC_CONST( FRAGMENT_FREE_EXTENT_SPACE = 0xFFEB );
 
   /**
+   * 64-bit row gci (extending lower if not sufficient bits)
+   *   read-only
+   */
+  STATIC_CONST( ROW_GCI64    = 0xFFEA);
+
+  /**
+   * Row author... autoset to 0, can be over written
+   */
+  STATIC_CONST( ROW_AUTHOR    = 0xFFE9);
+
+  /**
    * Optimize pseudo column and optimization options
    */
   STATIC_CONST( OPTIMIZE     = 0xFFE0 );          //pseudo column id to optimize

=== modified file 'storage/ndb/include/kernel/kernel_types.h'
--- a/storage/ndb/include/kernel/kernel_types.h	2010-01-28 15:16:46 +0000
+++ b/storage/ndb/include/kernel/kernel_types.h	2010-10-03 01:41:32 +0000
@@ -36,9 +36,7 @@ enum Operation_t {
   ,ZDELETE  = 3
   ,ZWRITE   = 4
   ,ZREAD_EX = 5
-#if 0
-  ,ZREAD_CONSISTENT = 6
-#endif
+  ,ZREFRESH = 6
   ,ZUNLOCK  = 7
 };
 

=== modified file 'storage/ndb/include/kernel/signaldata/CreateTab.hpp'
--- a/storage/ndb/include/kernel/signaldata/CreateTab.hpp	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/include/kernel/signaldata/CreateTab.hpp	2010-10-03 01:41:32 +0000
@@ -24,7 +24,7 @@
 struct CreateTabReq
 {
   STATIC_CONST( SignalLength = 6 );
-  STATIC_CONST( SignalLengthLDM = 6 + 10 );
+  STATIC_CONST( SignalLengthLDM = 6 + 11 );
 
   enum RequestType {
   };
@@ -49,6 +49,7 @@ struct CreateTabReq
   Uint32 noOfKeyAttr;
   Uint32 checksumIndicator;
   Uint32 GCPIndicator;
+  Uint32 extraRowAuthorBits;
 
   SECTION( DICT_TAB_INFO = 0 );
   SECTION( FRAGMENTATION = 1 );

=== modified file 'storage/ndb/include/kernel/signaldata/CreateTable.hpp'
--- a/storage/ndb/include/kernel/signaldata/CreateTable.hpp	2010-04-01 05:20:25 +0000
+++ b/storage/ndb/include/kernel/signaldata/CreateTable.hpp	2010-10-03 01:41:32 +0000
@@ -76,7 +76,8 @@ struct CreateTableRef {
     OutOfStringBuffer = 773,
     NoLoggingTemporaryTable = 778,
     InvalidHashMap = 790,
-    TableDefinitionTooBig = 793
+    TableDefinitionTooBig = 793,
+    FeatureRequiresUpgrade = 794
   };
 
   Uint32 senderRef;

=== modified file 'storage/ndb/include/kernel/signaldata/DictTabInfo.hpp'
--- a/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp	2010-05-06 10:15:24 +0000
+++ b/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp	2010-10-03 01:41:32 +0000
@@ -149,6 +149,9 @@ public:
     HashMapObjectId    = 153,
     HashMapVersion     = 154,
 
+    ExtraRowGCIBits = 155,
+    ExtraRowAuthorBits = 156,
+
     TableEnd           = 999,
     
     AttributeName          = 1000, // String, Mandatory
@@ -377,6 +380,9 @@ public:
 
     Uint32 HashMapObjectId;
     Uint32 HashMapVersion;
+
+    Uint32 ExtraRowGCIBits;
+    Uint32 ExtraRowAuthorBits;
     
     Table() {}
     void init();

=== modified file 'storage/ndb/include/ndb_version.h.in'
--- a/storage/ndb/include/ndb_version.h.in	2010-09-29 08:45:11 +0000
+++ b/storage/ndb/include/ndb_version.h.in	2010-10-03 01:41:32 +0000
@@ -500,4 +500,25 @@ ndbd_suma_stop_me(Uint32 x)
   }
 }
 
+/* TODO : Check these before pushing */
+#define NDBD_TUP_EXTRABITS_70 NDB_MAKE_VERSION(7,0,20)
+#define NDBD_TUP_EXTRABITS_71 NDB_MAKE_VERSION(7,1,8)
+
+static
+inline
+int
+ndb_tup_extrabits(Uint32 x)
+{
+  {
+    const Uint32 major = (x >> 16) & 0xFF;
+    const Uint32 minor = (x >>  8) & 0xFF;
+
+    if (major == 7 && minor == 0)
+    {
+      return x >= NDBD_TUP_EXTRABITS_70;
+    }
+    return x >= NDBD_TUP_EXTRABITS_71;
+  }
+}   
+
 #endif

=== modified file 'storage/ndb/include/ndbapi/NdbDictionary.hpp'
--- a/storage/ndb/include/ndbapi/NdbDictionary.hpp	2010-09-30 14:27:18 +0000
+++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp	2010-10-03 01:41:32 +0000
@@ -603,6 +603,8 @@ public:
     static const Column * RECORDS_IN_RANGE;
     static const Column * ROWID;
     static const Column * ROW_GCI;
+    static const Column * ROW_GCI64;
+    static const Column * ROW_AUTHOR;
     static const Column * ANY_VALUE;
     static const Column * COPY_ROWID;
     static const Column * LOCK_REF;
@@ -1041,6 +1043,18 @@ public:
      *   passing NULL pointer will equal to bitmap with all columns set
      */
     int checkColumns(const Uint32* bitmap, unsigned len_in_bytes) const;
+
+    /**
+     * Get/set extra GCI bits (max 31)
+     */
+    void setExtraRowGciBits(Uint32);
+    Uint32 getExtraRowGciBits() const;
+
+    /**
+     * Get/set extra row author bits (max 31)
+     */
+    void setExtraRowAuthorBits(Uint32);
+    Uint32 getExtraRowAuthorBits() const;
 #endif
 
     // these 2 are not de-doxygenated

=== modified file 'storage/ndb/include/ndbapi/NdbOperation.hpp'
--- a/storage/ndb/include/ndbapi/NdbOperation.hpp	2010-09-29 13:25:19 +0000
+++ b/storage/ndb/include/ndbapi/NdbOperation.hpp	2010-10-03 01:41:32 +0000
@@ -915,6 +915,7 @@ public:
     DeleteRequest = 3,            ///< Delete Operation
     WriteRequest = 4,             ///< Write Operation
     ReadExclusive = 5,            ///< Read exclusive
+    RefreshRequest = 6,           ///<
     UnlockRequest = 7,            ///< Unlock operation
     OpenScanRequest,              ///< Scan Operation
     OpenRangeScanRequest,         ///< Range scan operation

=== modified file 'storage/ndb/include/ndbapi/NdbTransaction.hpp'
--- a/storage/ndb/include/ndbapi/NdbTransaction.hpp	2010-09-30 14:27:18 +0000
+++ b/storage/ndb/include/ndbapi/NdbTransaction.hpp	2010-10-03 01:41:32 +0000
@@ -747,6 +747,12 @@ public:
                                   const NdbOperation::OperationOptions *opts = 0,
                                   Uint32 sizeOfOptions = 0);
 
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+  const NdbOperation *refreshTuple(const NdbRecord *key_rec, const char *key_row,
+                                   const NdbOperation::OperationOptions *opts = 0,
+                                   Uint32 sizeOfOptions = 0);
+#endif
+
   /**
    * Scan a table, using NdbRecord to read out column data.
    *

=== modified file 'storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp	2010-04-29 14:52:05 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp	2010-10-03 01:41:32 +0000
@@ -73,6 +73,8 @@ DictTabInfo::TableMapping[] = {
   DTIMAP(Table, SingleUserMode, SingleUserMode),
   DTIMAP(Table, HashMapObjectId, HashMapObjectId),
   DTIMAP(Table, HashMapVersion, HashMapVersion),
+  DTIMAP(Table, ExtraRowGCIBits, ExtraRowGCIBits),
+  DTIMAP(Table, ExtraRowAuthorBits, ExtraRowAuthorBits),
   DTIBREAK(AttributeName)
 };
 
@@ -182,6 +184,9 @@ DictTabInfo::Table::init(){
 
   HashMapObjectId = RNIL;
   HashMapVersion = RNIL;
+
+  ExtraRowGCIBits = 0;
+  ExtraRowAuthorBits = 0;
 }
 
 void

=== modified file 'storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp	2010-01-28 15:16:46 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp	2010-10-03 01:41:32 +0000
@@ -37,6 +37,7 @@ printTCKEYREQ(FILE * output, const Uint3
 	  sig->getOperationType(requestInfo) == ZDELETE  ? "Delete" :
 	  sig->getOperationType(requestInfo) == ZWRITE   ? "Write"  :
           sig->getOperationType(requestInfo) == ZUNLOCK  ? "Unlock" :
+          sig->getOperationType(requestInfo) == ZREFRESH ? "Refresh" :
 	  "Unknown");
   {
     if(sig->getDirtyFlag(requestInfo)){

=== modified file 'storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp'
--- a/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp	2010-03-02 17:49:20 +0000
+++ b/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp	2010-10-03 01:41:32 +0000
@@ -140,7 +140,7 @@ ndbout << "Ptr: " << ptr.p->word32 << " 
 /**
  * Check kernel_types for other operation types
  */
-#define ZSCAN_OP 6
+#define ZSCAN_OP 8
 #define ZSCAN_REC_SIZE 256
 #define ZSTAND_BY 2
 #define ZTABLESIZE 16
@@ -642,6 +642,7 @@ public:
   class Dblqh* c_lqh;
 
   void execACCMINUPDATE(Signal* signal);
+  void removerow(Uint32 op, const Local_key*);
 
 private:
   BLOCK_DEFINES(Dbacc);

=== modified file 'storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp	2010-08-20 11:10:25 +0000
+++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp	2010-10-03 01:41:32 +0000
@@ -973,9 +973,12 @@ void Dbacc::initOpRec(Signal* signal) 
   Uint32 readFlag = (((Treqinfo >> 4) & 0x3) == 0);      // Only 1 if Read
   Uint32 dirtyFlag = (((Treqinfo >> 6) & 0x1) == 1);     // Only 1 if Dirty
   Uint32 dirtyReadFlag = readFlag & dirtyFlag;
+  Uint32 operation = Treqinfo & 0xf;
+  if (operation == ZREFRESH)
+    operation = ZWRITE;
 
   Uint32 opbits = 0;
-  opbits |= Treqinfo & 0x7;
+  opbits |= operation;
   opbits |= ((Treqinfo >> 4) & 0x3) ? (Uint32) Operationrec::OP_LOCK_MODE : 0;
   opbits |= ((Treqinfo >> 4) & 0x3) ? (Uint32) Operationrec::OP_ACC_LOCK_MODE : 0;
   opbits |= (dirtyReadFlag) ? (Uint32) Operationrec::OP_DIRTY_READ : 0;
@@ -2318,6 +2321,34 @@ void Dbacc::execACCMINUPDATE(Signal* sig
   ndbrequire(false);
 }//Dbacc::execACCMINUPDATE()
 
+void
+Dbacc::removerow(Uint32 opPtrI, const Local_key* key)
+{
+  jamEntry();
+  operationRecPtr.i = opPtrI;
+  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
+  Uint32 opbits = operationRecPtr.p->m_op_bits;
+  fragrecptr.i = operationRecPtr.p->fragptr;
+
+  opbits |= Operationrec::OP_ELEMENT_DISAPPEARED;
+  opbits &= ~Uint32(Operationrec::OP_COMMIT_DELETE_CHECK);
+  operationRecPtr.p->m_op_bits = opbits;
+
+#ifdef VM_TRACE
+  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
+  if (likely(fragrecptr.p->localkeylen == 1))
+  {
+    ndbrequire(operationRecPtr.p->localdata[0] == key->ref());
+    return;
+  }
+  else if (fragrecptr.p->localkeylen == 2)
+  {
+    ndbrequire(operationRecPtr.p->localdata[0] == key->m_page_no);
+    ndbrequire(operationRecPtr.p->localdata[1] == key->m_page_idx);
+  }
+#endif
+}//Dbacc::execACCMINUPDATE()
+
 /* ******************--------------------------------------------------------------- */
 /* ACC_COMMITREQ                                        COMMIT  TRANSACTION          */
 /*                                                     SENDER: LQH,    LEVEL B       */

=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2010-09-21 07:36:08 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2010-10-03 01:41:32 +0000
@@ -721,6 +721,8 @@ Dbdict::packTableIntoPages(SimplePropert
   w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh);
   w.add(DictTabInfo::SingleUserMode, tablePtr.p->singleUserMode);
   w.add(DictTabInfo::HashMapObjectId, tablePtr.p->hashMapObjectId);
+  w.add(DictTabInfo::ExtraRowGCIBits, tablePtr.p->m_extra_row_gci_bits);
+  w.add(DictTabInfo::ExtraRowAuthorBits, tablePtr.p->m_extra_row_author_bits);
 
   if (tablePtr.p->hashMapObjectId != RNIL)
   {
@@ -4897,6 +4899,8 @@ void Dbdict::handleTabInfoInit(SimplePro
   tablePtr.p->singleUserMode = c_tableDesc.SingleUserMode;
   tablePtr.p->hashMapObjectId = c_tableDesc.HashMapObjectId;
   tablePtr.p->hashMapVersion = c_tableDesc.HashMapVersion;
+  tablePtr.p->m_extra_row_gci_bits = c_tableDesc.ExtraRowGCIBits;
+  tablePtr.p->m_extra_row_author_bits = c_tableDesc.ExtraRowAuthorBits;
 
   tabRequire(tablePtr.p->noOfAttributes <= MAX_ATTRIBUTES_IN_TABLE,
              CreateTableRef::NoMoreAttributeRecords); // bad error code!
@@ -5414,6 +5418,27 @@ void Dbdict::handleTabInfo(SimplePropert
   tabRequire(keyLength > 0, 
 	     CreateTableRef::InvalidPrimaryKeySize);
 
+  /* Check that all currently running nodes data support
+   * table features
+   */
+  for (Uint32 nodeId=1; nodeId < MAX_NODES; nodeId++)
+  {
+    const NodeInfo& ni = getNodeInfo(nodeId);
+
+    if (ni.m_connected && 
+        (ni.m_type == NODE_TYPE_DB))
+    {
+      /* Check that all nodes support extra bits */
+      if (tablePtr.p->m_extra_row_gci_bits ||
+          tablePtr.p->m_extra_row_author_bits)
+      {
+        tabRequire(ndb_tup_extrabits(ni.m_version),
+                   CreateTableRef::FeatureRequiresUpgrade);
+      }
+    }
+  }
+
+
   if(tablePtr.p->m_tablespace_id != RNIL || counts[3] || counts[4])
   {
     FilegroupPtr tablespacePtr;
@@ -6116,8 +6141,9 @@ Dbdict::createTab_local(Signal* signal,
   req->noOfNullAttributes = tabPtr.p->noOfNullBits;
   req->noOfKeyAttr = tabPtr.p->noOfPrimkey;
   req->checksumIndicator = 1;
-  req->GCPIndicator = 1;
+  req->GCPIndicator = 1 + tabPtr.p->m_extra_row_gci_bits;
   req->noOfAttributes = tabPtr.p->noOfAttributes;
+  req->extraRowAuthorBits = tabPtr.p->m_extra_row_author_bits;
   sendSignal(DBLQH_REF, GSN_CREATE_TAB_REQ, signal,
              CreateTabReq::SignalLengthLDM, JBB);
 

=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp	2010-08-13 09:31:43 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp	2010-10-03 01:41:32 +0000
@@ -281,6 +281,8 @@ public:
       TR_Temporary    = 0x8,
       TR_ForceVarPart = 0x10
     };
+    Uint8 m_extra_row_gci_bits;
+    Uint8 m_extra_row_author_bits;
     Uint16 m_bits;
 
     /* Number of attibutes in table */

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2010-09-20 13:09:18 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2010-10-03 01:41:32 +0000
@@ -3079,6 +3079,7 @@ public:
   bool is_same_trans(Uint32 opId, Uint32 trid1, Uint32 trid2);
   void get_op_info(Uint32 opId, Uint32 *hash, Uint32* gci_hi, Uint32* gci_lo);
   void accminupdate(Signal*, Uint32 opPtrI, const Local_key*);
+  void accremoverow(Signal*, Uint32 opPtrI, const Local_key*);
 
   /**
    *
@@ -3270,6 +3271,16 @@ Dblqh::accminupdate(Signal* signal, Uint
 }
 
 inline
+void
+Dblqh::accremoverow(Signal* signal, Uint32 opId, const Local_key* key)
+{
+  TcConnectionrecPtr regTcPtr;
+  regTcPtr.i= opId;
+  ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
+  c_acc->removerow(regTcPtr.p->accConnectrec, key);
+}
+
+inline
 bool
 Dblqh::TRACE_OP_CHECK(const TcConnectionrec* regTcPtr)
 {

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2010-09-27 08:52:07 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2010-10-03 01:41:32 +0000
@@ -144,6 +144,7 @@ operator<<(NdbOut& out, Operation_t op)
   case ZDELETE: out << "DELETE"; break;
   case ZWRITE: out << "WRITE"; break;
   case ZUNLOCK: out << "UNLOCK"; break;
+  case ZREFRESH: out << "REFRESH"; break;
   }
   return out;
 }
@@ -4371,6 +4372,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal
     regTcPtr->lockType = 
       op == ZREAD_EX ? ZUPDATE : 
       (Operation_t) op == ZWRITE ? ZINSERT : 
+      (Operation_t) op == ZREFRESH ? ZINSERT :
       (Operation_t) op == ZUNLOCK ? ZREAD : // lockType not relevant for unlock req
       (Operation_t) op;
   }
@@ -4494,8 +4496,11 @@ void Dblqh::execLQHKEYREQ(Signal* signal
 
   sig2 = lqhKeyReq->variableData[nextPos + 0];
   sig3 = cnewestGci;
+  /* If gci_hi provided, take it and set gci_lo to max value
+   * Otherwise, it will be decided by TUP at commit time as normal
+   */
   regTcPtr->gci_hi = LqhKeyReq::getGCIFlag(Treqinfo) ? sig2 : sig3;
-  regTcPtr->gci_lo = 0;
+  regTcPtr->gci_lo = LqhKeyReq::getGCIFlag(Treqinfo) ? ~Uint32(0) : 0;
   nextPos += LqhKeyReq::getGCIFlag(Treqinfo);
   
   if (LqhKeyReq::getRowidFlag(Treqinfo))
@@ -4878,6 +4883,7 @@ void Dblqh::prepareContinueAfterBlockedL
     case ZINSERT: TRACENR("INSERT"); break;
     case ZDELETE: TRACENR("DELETE"); break;
     case ZUNLOCK: TRACENR("UNLOCK"); break;
+    case ZREFRESH: TRACENR("REFRESH"); break;
     default: TRACENR("<Unknown: " << regTcPtr->operation << ">"); break;
     }
     
@@ -4927,7 +4933,6 @@ Dblqh::exec_acckeyreq(Signal* signal, Tc
   Uint32 taccreq;
   regTcPtr.p->transactionState = TcConnectionrec::WAIT_ACC;
   taccreq = regTcPtr.p->operation;
-  taccreq = taccreq + (regTcPtr.p->opSimple << 3);
   taccreq = taccreq + (regTcPtr.p->lockType << 4);
   taccreq = taccreq + (regTcPtr.p->dirtyOp << 6);
   taccreq = taccreq + (regTcPtr.p->replicaType << 7);
@@ -5092,7 +5097,7 @@ Dblqh::handle_nr_copy(Signal* signal, Pt
     if (match)
     {
       jam();
-      if (op != ZDELETE)
+      if (op != ZDELETE && op != ZREFRESH)
       {
 	if (TRACENR_FLAG)
 	  TRACENR(" Changing from to ZWRITE" << endl);
@@ -5100,7 +5105,9 @@ Dblqh::handle_nr_copy(Signal* signal, Pt
       }
       goto run;
     }
-    
+
+    ndbassert(!match && op == ZINSERT);
+
     /**
      * 1) Delete row at specified rowid (if len > 0)
      * 2) Delete specified row at different rowid (if exists)
@@ -5711,7 +5718,7 @@ void Dblqh::execACCKEYCONF(Signal* signa
       LqhKeyReq::setOperation(requestInfo, op);
       regTcPtr->reqinfo = requestInfo;
     }
-  }//if
+  }
   
   /* ------------------------------------------------------------------------
    * IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
@@ -5808,7 +5815,7 @@ Dblqh::acckeyconf_tupkeyreq(Signal* sign
   
   TRACE_OP(regTcPtr, "TUPKEYREQ");
   
-  regTcPtr->m_use_rowid |= (op == ZINSERT);
+  regTcPtr->m_use_rowid |= (op == ZINSERT || op == ZREFRESH);
   regTcPtr->m_row_id.m_page_no = page_no;
   regTcPtr->m_row_id.m_page_idx = page_idx;
   
@@ -11522,6 +11529,8 @@ Dblqh::execPREPARE_COPY_FRAG_REQ(Signal*
     fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION;
     fragptr.p->logFlag = Fragrecord::STATE_FALSE;
 
+    c_tup->start_copy_frag(req.tableId, req.fragId);
+
     c_tup->get_frag_info(req.tableId, req.fragId, &max_page);
   }    
     
@@ -12508,6 +12517,8 @@ void Dblqh::execCOPY_ACTIVEREQ(Signal* s
       fragptr.p->logFlag = Fragrecord::STATE_TRUE;
     }
   }
+
+  c_tup->complete_copy_frag(tabptr.i, fragptr.i);
   
   if (flags & CopyActiveReq::CAR_NO_WAIT)
   {

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2010-08-31 10:55:01 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2010-10-03 01:41:32 +0000
@@ -2991,6 +2991,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) 
     case ZINSERT:
     case ZDELETE:
     case ZWRITE:
+    case ZREFRESH:
       jam();
       break;
     default:

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2010-09-24 18:19:07 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2010-10-03 01:41:32 +0000
@@ -269,6 +269,7 @@ inline const Uint32* ALIGN_WORD(const vo
 #define ZMUST_BE_ABORTED_ERROR 898
 #define ZTUPLE_DELETED_ERROR 626
 #define ZINSERT_ERROR 630
+#define ZOP_AFTER_REFRESH_ERROR 920
 
 #define ZINVALID_CHAR_FORMAT 744
 #define ZROWID_ALLOCATED 899
@@ -421,6 +422,8 @@ struct Fragoperrec {
   Uint32 attributeCount;
   Uint32 charsetIndex;
   Uint32 m_null_bits[2];
+  Uint32 m_extra_row_gci_bits;
+  Uint32 m_extra_row_author_bits;
   union {
     BlockReference lqhBlockrefFrag;
     Uint32 m_senderRef;
@@ -1009,7 +1012,9 @@ ArrayPool<TupTriggerData> c_triggerPool;
       TR_Checksum = 0x1, // Need to be 1
       TR_RowGCI   = 0x2,
       TR_ForceVarPart = 0x4,
-      TR_DiskPart  = 0x8
+      TR_DiskPart  = 0x8,
+      TR_ExtraRowGCIBits = 0x10,
+      TR_ExtraRowAuthorBits = 0x20
     };
     Uint16 m_bits;
     Uint16 total_rec_size; // Max total size for entire tuple in words
@@ -1022,6 +1027,7 @@ ArrayPool<TupTriggerData> c_triggerPool;
     Uint16 noOfKeyAttr;
     Uint16 noOfCharsets;
     Uint16 m_dyn_null_bits;
+    Uint16 m_no_of_extra_columns; // "Hidden" columns
 
     bool need_expand() const { 
       return m_no_of_attributes > m_attributes[MM].m_no_of_fixsize;
@@ -1047,6 +1053,17 @@ ArrayPool<TupTriggerData> c_triggerPool;
         (disk && m_attributes[DD].m_no_of_varsize > 0);
     }
 
+    template <Uint32 bit> Uint32 getExtraAttrId() const {
+      if (bit == TR_ExtraRowGCIBits)
+        return 0;
+      Uint32 no = 0;
+      if (m_bits & TR_ExtraRowGCIBits)
+        no++;
+      assert(bit == TR_ExtraRowAuthorBits);
+      //if (bit == TR_ExtraRowAuthorBits)
+      return no;
+    }
+
     /**
      * Descriptors for MM and DD part
      */
@@ -1712,7 +1729,9 @@ public:
   void complete_restore_lcp(Signal*, Uint32 ref, Uint32 data,
                             Uint32 tableId, Uint32 fragmentId);
   Uint32 get_max_lcp_record_size(Uint32 tableId);
-  
+  void start_copy_frag(Uint32 tableId, Uint32 fragmentId);
+  void complete_copy_frag(Uint32 tableId, Uint32 fragmentId);
+
   int nr_read_pk(Uint32 fragPtr, const Local_key*, Uint32* dataOut, bool&copy);
   int nr_update_gci(Uint32 fragPtr, const Local_key*, Uint32 gci);
   int nr_delete(Signal*, Uint32, Uint32 fragPtr, const Local_key*, Uint32 gci);
@@ -2010,6 +2029,13 @@ private:
                       KeyReqStruct* req_struct,
 		      bool disk);
 
+  int handleRefreshReq(Signal* signal,
+                       Ptr<Operationrec>,
+                       Ptr<Fragrecord>,
+                       Tablerec*,
+                       KeyReqStruct*,
+                       bool disk);
+
 //------------------------------------------------------------------
 //------------------------------------------------------------------
   int  updateStartLab(Signal* signal,
@@ -2880,10 +2906,14 @@ private:
   void initData();
   void initRecords();
 
+  // 2 words for optional GCI64 + AUTHOR info
+#define EXTRA_COPY_PROC_WORDS 2
+#define MAX_COPY_PROC_LEN (MAX_ATTRIBUTES_IN_TABLE + EXTRA_COPY_PROC_WORDS)
+
   void deleteScanProcedure(Signal* signal, Operationrec* regOperPtr);
   void allocCopyProcedure();
   void freeCopyProcedure();
-  void prepareCopyProcedure(Uint32 numAttrs);
+  void prepareCopyProcedure(Uint32 numAttrs, Uint16 tableBits);
   void releaseCopyProcedure();
   void copyProcedure(Signal* signal,
                      TablerecPtr regTabPtr,
@@ -2902,7 +2932,7 @@ private:
 //-----------------------------------------------------------------------------
 
 // Public methods
-  Uint32 getTabDescrOffsets(Uint32, Uint32, Uint32, Uint32*);
+  Uint32 getTabDescrOffsets(Uint32, Uint32, Uint32, Uint32, Uint32*);
   Uint32 getDynTabDescrOffsets(Uint32 MaskSize, Uint32* offset);
   Uint32 allocTabDescr(Uint32 allocSize);
   void releaseTabDescr(Uint32 desc);
@@ -3103,6 +3133,8 @@ private:
   Uint32 czero;
   Uint32 cCopyProcedure;
   Uint32 cCopyLastSeg;
+  Uint32 cCopyOverwrite;
+  Uint32 cCopyOverwriteLen;
 
  // A little bit bigger to cover overwrites in copy algorithms (16384 real size).
 #define ZATTR_BUFFER_SIZE 16384
@@ -3301,11 +3333,16 @@ private:
   void findFirstOp(OperationrecPtr&);
   bool is_rowid_lcp_scanned(const Local_key& key1,
                            const Dbtup::ScanOp& op);
-  void commit_operation(Signal*, Uint32, Tuple_header*, PagePtr,
+  void commit_operation(Signal*, Uint32, Uint32, Tuple_header*, PagePtr,
 			Operationrec*, Fragrecord*, Tablerec*);
-  
-  void dealloc_tuple(Signal* signal, Uint32, Page*, Tuple_header*, 
+  void commit_refresh(Signal*, Uint32, Uint32, Tuple_header*, PagePtr,
+                      Operationrec*, Fragrecord*, Tablerec*);
+  void dealloc_tuple(Signal* signal, Uint32, Uint32, Page*, Tuple_header*,
 		     Operationrec*, Fragrecord*, Tablerec*);
+  bool store_extra_row_bits(Uint32, const Tablerec*, Tuple_header*, Uint32,
+                            bool);
+  void read_extra_row_bits(Uint32, const Tablerec*, Tuple_header*, Uint32 *,
+                            bool);
   
   int handle_size_change_after_update(KeyReqStruct* req_struct,
 				      Tuple_header* org,

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp	2010-09-03 05:35:51 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp	2010-10-03 01:41:32 +0000
@@ -155,7 +155,8 @@ Dbtup::is_rowid_lcp_scanned(const Local_
 
 void
 Dbtup::dealloc_tuple(Signal* signal,
-		     Uint32 gci,
+		     Uint32 gci_hi,
+                     Uint32 gci_lo,
 		     Page* page,
 		     Tuple_header* ptr, 
 		     Operationrec* regOperPtr, 
@@ -176,7 +177,7 @@ Dbtup::dealloc_tuple(Signal* signal,
     tmpptr.i = m_pgman_ptr.i;
     tmpptr.p = reinterpret_cast<Page*>(m_pgman_ptr.p);
     disk_page_free(signal, regTabPtr, regFragPtr, 
-		   &disk, tmpptr, gci);
+		   &disk, tmpptr, gci_hi);
   }
   
   if (! (bits & (Tuple_header::LCP_SKIP | Tuple_header::ALLOC)) && 
@@ -201,7 +202,12 @@ Dbtup::dealloc_tuple(Signal* signal,
   if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
   {
     jam();
-    * ptr->get_mm_gci(regTabPtr) = gci;
+    * ptr->get_mm_gci(regTabPtr) = gci_hi;
+    if (regTabPtr->m_bits & Tablerec::TR_ExtraRowGCIBits)
+    {
+      Uint32 attrId = regTabPtr->getExtraAttrId<Tablerec::TR_ExtraRowGCIBits>();
+      store_extra_row_bits(attrId, regTabPtr, ptr, gci_lo, /* truncate */true);
+    }
   }
 }
 
@@ -227,7 +233,8 @@ static void dump_buf_hex(unsigned char *
 
 void
 Dbtup::commit_operation(Signal* signal,
-			Uint32 gci,
+			Uint32 gci_hi,
+                        Uint32 gci_lo,
 			Tuple_header* tuple_ptr, 
 			PagePtr pagePtr,
 			Operationrec* regOperPtr, 
@@ -338,7 +345,7 @@ Dbtup::commit_operation(Signal* signal,
     if(copy_bits & Tuple_header::DISK_ALLOC)
     {
       jam();
-      disk_page_alloc(signal, regTabPtr, regFragPtr, &key, diskPagePtr, gci);
+      disk_page_alloc(signal, regTabPtr, regFragPtr, &key, diskPagePtr, gci_hi);
     }
     
     if(regTabPtr->m_attributes[DD].m_no_of_varsize == 0)
@@ -358,7 +365,7 @@ Dbtup::commit_operation(Signal* signal,
     {
       jam();
       disk_page_undo_update(diskPagePtr.p, 
-			    &key, dst, sz, gci, logfile_group_id);
+			    &key, dst, sz, gci_hi, logfile_group_id);
     }
     
     memcpy(dst, disk_ptr, 4*sz);
@@ -394,7 +401,13 @@ Dbtup::commit_operation(Signal* signal,
   if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
   {
     jam();
-    * tuple_ptr->get_mm_gci(regTabPtr) = gci;
+    * tuple_ptr->get_mm_gci(regTabPtr) = gci_hi;
+    if (regTabPtr->m_bits & Tablerec::TR_ExtraRowGCIBits)
+    {
+      Uint32 attrId = regTabPtr->getExtraAttrId<Tablerec::TR_ExtraRowGCIBits>();
+      store_extra_row_bits(attrId, regTabPtr, tuple_ptr, gci_lo,
+                           /* truncate */true);
+    }
   }
   
   if (regTabPtr->m_bits & Tablerec::TR_Checksum) {
@@ -741,23 +754,27 @@ skip_disk:
     
     tuple_ptr->m_operation_ptr_i = RNIL;
     
-    if(regOperPtr.p->op_struct.op_type != ZDELETE)
+    if (regOperPtr.p->op_struct.op_type == ZDELETE)
+    {
+      jam();
+      if (get_page)
+        ndbassert(tuple_ptr->m_header_bits & Tuple_header::DISK_PART);
+      dealloc_tuple(signal, gci_hi, gci_lo, page.p, tuple_ptr,
+                    regOperPtr.p, regFragPtr.p, regTabPtr.p); 
+    }
+    else if(regOperPtr.p->op_struct.op_type != ZREFRESH)
     {
       jam();
-      commit_operation(signal, gci_hi, tuple_ptr, page,
-		       regOperPtr.p, regFragPtr.p, regTabPtr.p); 
+      commit_operation(signal, gci_hi, gci_lo, tuple_ptr, page,
+                       regOperPtr.p, regFragPtr.p, regTabPtr.p);
     }
     else
     {
       jam();
-      if (get_page)
-      {
-	ndbassert(tuple_ptr->m_header_bits & Tuple_header::DISK_PART);
-      }
-      dealloc_tuple(signal, gci_hi, page.p, tuple_ptr,
-		    regOperPtr.p, regFragPtr.p, regTabPtr.p); 
+      commit_refresh(signal, gci_hi, gci_lo, tuple_ptr, page,
+                     regOperPtr.p, regFragPtr.p, regTabPtr.p);
     }
-  } 
+  }
 
   if (nextOp != RNIL)
   {
@@ -808,3 +825,39 @@ Dbtup::set_commit_change_mask_info(const
     }
   }
 }
+
+void
+Dbtup::commit_refresh(Signal* signal,
+                      Uint32 gci_hi,
+                      Uint32 gci_lo,
+                      Tuple_header* tuple_ptr,
+                      PagePtr pagePtr,
+                      Operationrec* regOperPtr,
+                      Fragrecord* regFragPtr,
+                      Tablerec* regTabPtr)
+{
+  switch(regOperPtr->m_copy_tuple_location.m_file_no){
+  case 1:
+  case 3:
+    break;
+  case 2:
+  case 4:
+    // "Normal" update
+    commit_operation(signal, gci_hi, gci_lo, tuple_ptr, pagePtr,
+                     regOperPtr, regFragPtr, regTabPtr);
+    return;
+
+  default:
+    ndbrequire(false);
+  }
+
+  Local_key key = regOperPtr->m_tuple_location;
+  key.m_page_no = pagePtr.p->frag_page_id;
+
+  /**
+   * Tell ACC to delete
+   */
+  c_lqh->accremoverow(signal, regOperPtr->userpointer, &key);
+  dealloc_tuple(signal, gci_hi, gci_lo, pagePtr.p, tuple_ptr,
+                regOperPtr, regFragPtr, regTabPtr);
+}

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2010-09-07 06:44:00 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2010-10-03 01:41:32 +0000
@@ -213,7 +213,13 @@ Dbtup::insertActiveOpList(OperationrecPt
 	  prevOpPtr.p->op_struct.delete_insert_flag= true;
 	  regOperPtr.p->op_struct.delete_insert_flag= true;
 	  return true;
-	} else {
+	}
+        else if (op == ZREFRESH)
+        {
+          return true;
+        }
+        else
+        {
 	  terrorCode= ZTUPLE_DELETED_ERROR;
 	  return false;
 	}
@@ -223,6 +229,15 @@ Dbtup::insertActiveOpList(OperationrecPt
 	terrorCode= ZINSERT_ERROR;
 	return false;
       }
+      else if (prevOp == ZREFRESH)
+      {
+        /**
+         * No operations allowed after a Refresh
+         * operation
+         */
+        terrorCode = ZOP_AFTER_REFRESH_ERROR;
+        return false;
+      }
       return true;
     }
     else
@@ -287,7 +302,7 @@ Dbtup::setup_read(KeyReqStruct *req_stru
     Uint32 currOp= currOpPtr.p->op_struct.op_type;
     
     if((found && currOp == ZDELETE) || 
-       ((dirty || !found) && currOp == ZINSERT))
+       ((dirty || !found) && (currOp == ZINSERT || currOp == ZREFRESH)))
     {
       terrorCode= ZTUPLE_DELETED_ERROR;
       break;
@@ -351,7 +366,7 @@ Dbtup::load_diskpage(Signal* signal, 
     regOperPtr->op_struct.m_load_diskpage_on_commit= 1;
     return 1;
   }
-  
+
   jam();
   Uint32 page_idx= local_key & MAX_TUPLES_PER_PAGE;
   Uint32 frag_page_id= local_key >> MAX_TUPLES_BITS;
@@ -408,6 +423,7 @@ Dbtup::load_diskpage(Signal* signal, 
   case ZUPDATE:
   case ZINSERT:
   case ZWRITE:
+  case ZREFRESH:
     regOperPtr->op_struct.m_wait_log_buffer= 1;
     regOperPtr->op_struct.m_load_diskpage_on_commit= 1;
   }
@@ -554,7 +570,7 @@ void Dbtup::execTUPKEYREQ(Signal* signal
    Uint32 Rstoredid= tupKeyReq->storedProcedure;
 
    regOperPtr->fragmentPtr= Rfragptr;
-   regOperPtr->op_struct.op_type= (TrequestInfo >> 6) & 0xf;
+   regOperPtr->op_struct.op_type= (TrequestInfo >> 6) & 0x7;
    regOperPtr->op_struct.delete_insert_flag = false;
    regOperPtr->op_struct.m_reorg = (TrequestInfo >> 12) & 3;
 
@@ -634,6 +650,12 @@ void Dbtup::execTUPKEYREQ(Signal* signal
      goto do_insert;
    }
 
+   if (Roptype == ZREFRESH && localkey == ~ (Uint32) 0)
+   {
+     // No tuple allocatated yet
+     goto do_refresh;
+   }
+
    /**
     * Get pointer to tuple
     */
@@ -815,6 +837,23 @@ void Dbtup::execTUPKEYREQ(Signal* signal
        sendTUPKEYCONF(signal, &req_struct, regOperPtr);
        return;
      }
+     else if (Roptype == ZREFRESH)
+     {
+       /**
+        * No TUX or immediate triggers
+        */
+   do_refresh:
+       if (unlikely(handleRefreshReq(signal, operPtr,
+                                     fragptr, regTabPtr,
+                                     &req_struct, disk_page != RNIL) == -1))
+       {
+         return;
+       }
+
+       sendTUPKEYCONF(signal, &req_struct, regOperPtr);
+       return;
+
+     }
      else
      {
        ndbrequire(false); // Invalid op type
@@ -1063,6 +1102,15 @@ int Dbtup::handleUpdateReq(Signal* signa
   
   if (!req_struct->interpreted_exec) {
     jam();
+
+    if (regTabPtr->m_bits & Tablerec::TR_ExtraRowAuthorBits)
+    {
+      jam();
+      Uint32 attrId =
+        regTabPtr->getExtraAttrId<Tablerec::TR_ExtraRowAuthorBits>();
+      
+      store_extra_row_bits(attrId, regTabPtr, dst, /* default */ 0, false);
+    }
     int retValue = updateAttributes(req_struct,
 				    &cinBuffer[0],
 				    req_struct->attrinfo_len);
@@ -1469,6 +1517,14 @@ int Dbtup::handleInsertReq(Signal* signa
     terrorCode = ZAI_INCONSISTENCY_ERROR;
     goto update_error;
   }
+
+  if (regTabPtr->m_bits & Tablerec::TR_ExtraRowAuthorBits)
+  {
+    Uint32 attrId =
+      regTabPtr->getExtraAttrId<Tablerec::TR_ExtraRowAuthorBits>();
+
+    store_extra_row_bits(attrId, regTabPtr, tuple_ptr, /* default */ 0, false);
+  }
   
   if (!regTabPtr->m_default_value_location.isNull())
   {
@@ -1831,6 +1887,138 @@ error:
   return -1;
 }
 
+int
+Dbtup::handleRefreshReq(Signal* signal,
+                        Ptr<Operationrec> regOperPtr,
+                        Ptr<Fragrecord>  regFragPtr,
+                        Tablerec* regTabPtr,
+                        KeyReqStruct *req_struct,
+                        bool disk)
+{
+  Uint32 refresh_case;
+  if (regOperPtr.p->is_first_operation())
+  {
+    jam();
+    if (req_struct->frag_page_id == (~(Uint32)0) >> MAX_TUPLES_BITS)
+    {
+      jam();
+      refresh_case = 1;
+      //ndbout_c("case 1");
+      /**
+       * This is refresh of non-existing tuple...
+       *   i.e "delete", reuse initial insert
+       */
+       Local_key accminupdate;
+       Local_key * accminupdateptr = &accminupdate;
+
+       /**
+        * We don't need ...in this scenario
+        * - disk
+        * - default values
+        */
+       Uint32 save_disk = regTabPtr->m_no_of_disk_attributes;
+       Local_key save_defaults = regTabPtr->m_default_value_location;
+       Bitmask<MAXNROFATTRIBUTESINWORDS> save_mask =
+         regTabPtr->notNullAttributeMask;
+
+       regTabPtr->m_no_of_disk_attributes = 0;
+       regTabPtr->m_default_value_location.setNull();
+       regOperPtr.p->op_struct.op_type = ZINSERT;
+
+       /**
+        * Update notNullAttributeMask  to only include primary keys
+        */
+       regTabPtr->notNullAttributeMask.clear();
+       const Uint32 * primarykeys =
+         (Uint32*)&tableDescriptor[regTabPtr->readKeyArray].tabDescr;
+       for (Uint32 i = 0; i<regTabPtr->noOfKeyAttr; i++)
+         regTabPtr->notNullAttributeMask.set(primarykeys[i] >> 16);
+
+       int res = handleInsertReq(signal, regOperPtr,
+                                 regFragPtr, regTabPtr, req_struct,
+                                 &accminupdateptr);
+
+       regTabPtr->m_no_of_disk_attributes = save_disk;
+       regTabPtr->m_default_value_location = save_defaults;
+       regTabPtr->notNullAttributeMask = save_mask;
+
+       if (unlikely(res == -1))
+       {
+         return -1;
+       }
+
+       regOperPtr.p->op_struct.op_type = ZREFRESH;
+
+       if (accminupdateptr)
+       {
+       /**
+          * Update ACC local-key, once *everything* has completed succesfully
+          */
+         c_lqh->accminupdate(signal,
+                             regOperPtr.p->userpointer,
+                             accminupdateptr);
+       }
+    }
+    else
+    {
+      refresh_case = 2;
+      //ndbout_c("case 2");
+      jam();
+
+      Uint32 tup_version_save = req_struct->m_tuple_ptr->get_tuple_version();
+      Uint32 new_tup_version = decr_tup_version(tup_version_save);
+      req_struct->m_tuple_ptr->set_tuple_version(new_tup_version);
+      int res = handleUpdateReq(signal, regOperPtr.p, regFragPtr.p,
+                                regTabPtr, req_struct, disk);
+      req_struct->m_tuple_ptr->set_tuple_version(tup_version_save);
+      if (res == -1)
+        return -1;
+    }
+  }
+  else
+  {
+    jam();
+
+    Uint32 tup_version_save = req_struct->prevOpPtr.p->tupVersion;
+    Uint32 new_tup_version = decr_tup_version(tup_version_save);
+    req_struct->prevOpPtr.p->tupVersion = new_tup_version;
+
+    int res;
+    if (req_struct->prevOpPtr.p->op_struct.op_type == ZDELETE)
+    {
+      refresh_case = 3;
+      //ndbout_c("case 3");
+
+      jam();
+      /**
+       * This is multi-update + DELETE + REFRESH
+       */
+      Local_key * accminupdateptr = 0;
+      res = handleInsertReq(signal, regOperPtr,
+                            regFragPtr, regTabPtr, req_struct,
+                            &accminupdateptr);
+    }
+    else
+    {
+      jam();
+      refresh_case = 4;
+      //ndbout_c("case 4");
+      /**
+       * This is multi-update + INSERT/UPDATE + REFRESH
+       */
+      res = handleUpdateReq(signal, regOperPtr.p, regFragPtr.p,
+                            regTabPtr, req_struct, disk);
+    }
+    req_struct->prevOpPtr.p->tupVersion = tup_version_save;
+    if (res == -1)
+      return -1;
+  }
+
+  // overload meaning...
+  regOperPtr.p->m_copy_tuple_location.m_file_no = refresh_case;
+  return 0;
+}
+
 bool
 Dbtup::checkNullAttributes(KeyReqStruct * req_struct,
                            Tablerec* regTabPtr)
@@ -2006,6 +2194,25 @@ int Dbtup::interpreterStartLab(Signal* s
 	return -1;
       }
     }
+
+    if ((RlogSize > 0) ||
+        (RfinalUpdateLen > 0))
+    {
+      /* Operation updates row,
+       * reset author pseudo-col before update takes effect
+       */
+      Tablerec* regTabPtr = req_struct->tablePtrP;
+      Tuple_header* dst = req_struct->m_tuple_ptr;
+
+      if (regTabPtr->m_bits & Tablerec::TR_ExtraRowAuthorBits)
+      {
+        Uint32 attrId =
+          regTabPtr->getExtraAttrId<Tablerec::TR_ExtraRowAuthorBits>();
+        
+        store_extra_row_bits(attrId, regTabPtr, dst, /* default */ 0, false);
+      }
+    }
+
     if (RfinalUpdateLen > 0) {
       jam();
       /* ---------------------------------------------------------------- */

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2010-09-07 06:44:00 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2010-10-03 01:41:32 +0000
@@ -52,6 +52,8 @@ void Dbtup::initData() 
 
   cCopyProcedure = RNIL;
   cCopyLastSeg = RNIL;
+  cCopyOverwrite = 0;
+  cCopyOverwriteLen = 0;
 
   // Records with constant sizes
   init_list_sizes();

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp	2010-09-21 07:36:08 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp	2010-10-03 01:41:32 +0000
@@ -77,6 +77,9 @@ Dbtup::execCREATE_TAB_REQ(Signal* signal
   memset(fragOperPtr.p->m_null_bits, 0, sizeof(fragOperPtr.p->m_null_bits));
   fragOperPtr.p->charsetIndex = 0;
   fragOperPtr.p->lqhBlockrefFrag = req->senderRef;
+  fragOperPtr.p->m_extra_row_gci_bits =
+    req->GCPIndicator > 1 ? req->GCPIndicator - 1 : 0;
+  fragOperPtr.p->m_extra_row_author_bits = req->extraRowAuthorBits;
 
   regTabPtr.p->m_createTable.m_fragOpPtrI = fragOperPtr.i;
   regTabPtr.p->m_createTable.defValSectionI = RNIL;
@@ -85,6 +88,9 @@ Dbtup::execCREATE_TAB_REQ(Signal* signal
   regTabPtr.p->m_bits |= (req->checksumIndicator ? Tablerec::TR_Checksum : 0);
   regTabPtr.p->m_bits |= (req->GCPIndicator ? Tablerec::TR_RowGCI : 0);
   regTabPtr.p->m_bits |= (req->forceVarPartFlag? Tablerec::TR_ForceVarPart : 0);
+  regTabPtr.p->m_bits |=
+    (req->GCPIndicator > 1 ? Tablerec::TR_ExtraRowGCIBits : 0);
+  regTabPtr.p->m_bits |= (req->extraRowAuthorBits ? Tablerec::TR_ExtraRowAuthorBits : 0);
 
   regTabPtr.p->m_offsets[MM].m_disk_ref_offset= 0;
   regTabPtr.p->m_offsets[MM].m_null_words= 0;
@@ -117,12 +123,26 @@ Dbtup::execCREATE_TAB_REQ(Signal* signal
   regTabPtr.p->noOfCharsets= req->noOfCharsets;
   regTabPtr.p->m_no_of_attributes= req->noOfAttributes;
   regTabPtr.p->dynTabDescriptor= RNIL;
+  regTabPtr.p->m_no_of_extra_columns = 0;
+
+  if (regTabPtr.p->m_bits & Tablerec::TR_ExtraRowGCIBits)
+  {
+    jam();
+    regTabPtr.p->m_no_of_extra_columns++;
+  }
+
+  if (regTabPtr.p->m_bits & Tablerec::TR_ExtraRowAuthorBits)
+  {
+    jam();
+    regTabPtr.p->m_no_of_extra_columns++;
+  }
 
   {
     Uint32 offset[10];
     Uint32 allocSize= getTabDescrOffsets(req->noOfAttributes,
                                          req->noOfCharsets,
                                          req->noOfKeyAttr,
+                                         regTabPtr.p->m_no_of_extra_columns,
                                          offset);
     Uint32 tableDescriptorRef= allocTabDescr(allocSize);
     if (tableDescriptorRef == RNIL)
@@ -177,6 +197,8 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* 
   fragOperPtr.p->attributeCount--;
   const bool lastAttr = (fragOperPtr.p->attributeCount == 0);
 
+  Uint32 extraAttrId = 0;
+
   Uint32 firstTabDesIndex= regTabPtr.p->tabDescriptor + (attrId * ZAD_SIZE);
   setTabDescrWord(firstTabDesIndex, attrDescriptor);
   Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
@@ -320,7 +342,71 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* 
 	       signal, 2, JBB);
     return;
   }
-  
+
+  if (fragOperPtr.p->m_extra_row_gci_bits)
+  {
+    jam();
+
+    const Uint32 bits = fragOperPtr.p->m_extra_row_gci_bits;
+
+    /**
+     * Create attribute descriptor for extra row gci bits...
+     */
+    Uint32 desc = 0;
+    Uint32 off = 0;
+
+    AttributeDescriptor::setSize(desc, 0); // bit
+    AttributeDescriptor::setArraySize(desc, bits);
+    AttributeOffset::setNullFlagPos(off, fragOperPtr.p->m_null_bits[MM]);
+    fragOperPtr.p->m_null_bits[MM] += bits;
+
+    if (fragOperPtr.p->m_null_bits[MM] > AO_NULL_FLAG_POS_MASK)
+    {
+      jam();
+      terrorCode = ZTOO_MANY_BITS_ERROR;
+      goto error;
+    }
+
+    Uint32 idx = regTabPtr.p->tabDescriptor;
+    idx += ZAD_SIZE * (regTabPtr.p->m_no_of_attributes + extraAttrId);
+    setTabDescrWord(idx, desc);
+    setTabDescrWord(idx + 1, off);
+
+    extraAttrId++;
+  }
+
+  if (fragOperPtr.p->m_extra_row_author_bits)
+  {
+    jam();
+
+    const Uint32 bits = fragOperPtr.p->m_extra_row_author_bits;
+
+    /**
+     * Create attribute descriptor for extra row gci bits...
+     */
+    Uint32 desc = 0;
+    Uint32 off = 0;
+
+    AttributeDescriptor::setSize(desc, 0); // bit
+    AttributeDescriptor::setArraySize(desc, bits);
+    AttributeOffset::setNullFlagPos(off, fragOperPtr.p->m_null_bits[MM]);
+    fragOperPtr.p->m_null_bits[MM] += bits;
+
+    if (fragOperPtr.p->m_null_bits[MM] > AO_NULL_FLAG_POS_MASK)
+    {
+      jam();
+      terrorCode = ZTOO_MANY_BITS_ERROR;
+      goto error;
+    }
+
+    Uint32 idx = regTabPtr.p->tabDescriptor;
+    idx += ZAD_SIZE * (regTabPtr.p->m_no_of_attributes + extraAttrId);
+    setTabDescrWord(idx, desc);
+    setTabDescrWord(idx + 1, off);
+
+    extraAttrId++;
+  }
+
 #define BTW(x) ((x+31) >> 5)
   regTabPtr.p->m_offsets[MM].m_null_words= BTW(fragOperPtr.p->m_null_bits[MM]);
   regTabPtr.p->m_offsets[DD].m_null_words= BTW(fragOperPtr.p->m_null_bits[DD]);
@@ -1015,6 +1101,7 @@ Dbtup::handleAlterTablePrepare(Signal *s
     /* Allocate a new (possibly larger) table descriptor buffer. */
     Uint32 allocSize= getTabDescrOffsets(newNoOfAttr, newNoOfCharsets,
                                          newNoOfKeyAttrs,
+                                         regTabPtr->m_no_of_extra_columns,
                                          regAlterTabOpPtr.p->tabDesOffset);
     Uint32 tableDescriptorRef= allocTabDescr(allocSize);
     if (tableDescriptorRef == RNIL) {
@@ -1035,11 +1122,24 @@ Dbtup::handleAlterTablePrepare(Signal *s
       (CHARSET_INFO**)(desc + regAlterTabOpPtr.p->tabDesOffset[2]);
     memcpy(CharsetArray, regTabPtr->charsetArray,
            sizeof(*CharsetArray)*regTabPtr->noOfCharsets);
-    Uint32 *attrDesPtr= desc + regAlterTabOpPtr.p->tabDesOffset[4];
+    Uint32 * const attrDesPtrStart = desc + regAlterTabOpPtr.p->tabDesOffset[4];
+    Uint32 * attrDesPtr = attrDesPtrStart;
     memcpy(attrDesPtr,
            &tableDescriptor[regTabPtr->tabDescriptor].tabDescr,
-           (ZAD_SIZE<<2)*oldNoOfAttr);
-    attrDesPtr+= ZAD_SIZE*oldNoOfAttr;
+           4 * ZAD_SIZE * oldNoOfAttr);
+
+    /**
+     * Copy extra columns descriptors to end of attrDesPtr
+     */
+    {
+      const Uint32 * src = &tableDescriptor[regTabPtr->tabDescriptor].tabDescr;
+      src += ZAD_SIZE * oldNoOfAttr;
+
+      Uint32 * dst = attrDesPtr + (ZAD_SIZE * newNoOfAttr);
+      memcpy(dst, src, 4 * ZAD_SIZE * regTabPtr->m_no_of_extra_columns);
+    }
+
+    attrDesPtr+= ZAD_SIZE * oldNoOfAttr;
 
     /*
       Loop over the new attributes to add.
@@ -1110,6 +1210,7 @@ Dbtup::handleAlterTablePrepare(Signal *s
       *attrDesPtr++= attrDes2;
     }
     ndbassert(newNoOfCharsets==charsetIndex);
+    ndbrequire(attrDesPtr == attrDesPtrStart + (ZAD_SIZE * newNoOfAttr));
 
     regAlterTabOpPtr.p->noOfDynNullBits= dyn_nullbits;
     ndbassert(noDynamic ==
@@ -1820,6 +1921,7 @@ void Dbtup::releaseTabDescr(Tablerec* co
     getTabDescrOffsets(regTabPtr->m_no_of_attributes,
                        regTabPtr->noOfCharsets,
                        regTabPtr->noOfKeyAttr,
+                       regTabPtr->m_no_of_extra_columns,
                        offset);
 
     regTabPtr->tabDescriptor= RNIL;
@@ -2518,6 +2620,44 @@ Dbtup::complete_restore_lcp(Signal* sign
   rebuild_page_free_list(signal);
 }
 
+void
+Dbtup::start_copy_frag(Uint32 tableId, Uint32 fragmentId)
+{
+  TablerecPtr tabPtr;
+  tabPtr.i= tableId;
+  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
+
+  /* If the table has extra row GCI bits, copyFrag uses
+   * attrinfo to restore the GCI.  We clear the table's
+   * GCI bit here so that it is not trampled by LQH.
+   */
+  if (tabPtr.p->m_bits & Tablerec::TR_ExtraRowGCIBits)
+  {
+    /* Save Table's TR_RowGCI bit in some borrowed space */
+    tabPtr.p->m_dropTable.tabUserRef= (tabPtr.p->m_bits & 
+                                       Tablerec::TR_RowGCI)? 1 : 0;
+
+    /* Clear Table's TR_RowGCI bit as GCI is set from 
+     * AttrInfo during COPYFRAG
+     */
+    tabPtr.p->m_bits &= ~((Uint16) Tablerec::TR_RowGCI);
+  }
+}
+
+void 
+Dbtup::complete_copy_frag(Uint32 tableId, Uint32 fragmentId)
+{
+  TablerecPtr tabPtr;
+  tabPtr.i= tableId;
+  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
+  
+  if (tabPtr.p->m_bits & Tablerec::TR_ExtraRowGCIBits)
+  {
+    /* Restore Table's TR_RowGCI bit */
+    tabPtr.p->m_bits |= ((tabPtr.p->m_dropTable.tabUserRef & 1) ? Tablerec::TR_RowGCI : 0);
+  }
+}
+
 bool
 Dbtup::get_frag_info(Uint32 tableId, Uint32 fragId, Uint32* maxPage)
 {

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp	2010-09-07 06:44:00 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp	2010-10-03 01:41:32 +0000
@@ -26,6 +26,7 @@
 #include <AttributeDescriptor.hpp>
 #include "AttributeOffset.hpp"
 #include <AttributeHeader.hpp>
+#include <dblqh/Dblqh.hpp>
 
 void
 Dbtup::setUpQueryRoutines(Tablerec *regTabPtr)
@@ -1744,6 +1745,70 @@ int Dbtup::updateAttributes(KeyReqStruct
       inBufIndex += 1 + sz;
       req_struct->in_buf_index = inBufIndex;
     }
+    else if (attributeId == AttributeHeader::ROW_AUTHOR)
+    {
+      jam();
+      Uint32 sz= ahIn.getDataSize();
+      ndbrequire(sz == 1);
+
+      Uint32 value = * (inBuffer + inBufIndex + 1);
+      Uint32 attrId =
+        regTabPtr->getExtraAttrId<Tablerec::TR_ExtraRowAuthorBits>();
+
+      if (unlikely(!(regTabPtr->m_bits & Tablerec::TR_ExtraRowAuthorBits)))
+      {
+        return -ZATTRIBUTE_ID_ERROR;
+      }
+
+      if (unlikely(store_extra_row_bits(attrId, regTabPtr,
+                                        req_struct->m_tuple_ptr,
+                                        value, /* truncate */ false) == false))
+      {
+        return -ZAI_INCONSISTENCY_ERROR;
+      }
+      inBufIndex += 1 + sz;
+      req_struct->in_buf_index = inBufIndex;
+    }
+    else if (attributeId == AttributeHeader::ROW_GCI64)
+    {
+      jam();
+      Uint32 sz= ahIn.getDataSize();
+      ndbrequire(sz == 2);
+      Uint32 attrId =
+        regTabPtr->getExtraAttrId<Tablerec::TR_ExtraRowGCIBits>();
+      Uint32 gciLo = * (inBuffer + inBufIndex + 1);
+      Uint32 gciHi = * (inBuffer + inBufIndex + 2);
+      
+      if (likely(! (regTabPtr->m_bits & Tablerec::TR_RowGCI)))
+      {
+        // TODO : Problem here that we allow GCI set for tables
+        // that genuinely don't have GCI.
+        /* Set GCI (setting rowGCI flag temporarily) */
+        {
+          Uint16 saveBits = regTabPtr->m_bits;
+          regTabPtr->m_bits |= Tablerec::TR_RowGCI;
+          *req_struct->m_tuple_ptr->get_mm_gci(regTabPtr) = gciHi;
+          regTabPtr->m_bits = saveBits;
+        }
+
+        if (regTabPtr->m_bits & Tablerec::TR_ExtraRowGCIBits)
+        {
+          if (unlikely(store_extra_row_bits(attrId, regTabPtr,
+                                            req_struct->m_tuple_ptr,
+                                            gciLo, /*truncate*/ true) == false))
+          {
+            return -ZAI_INCONSISTENCY_ERROR;
+          }
+        }
+      }
+      else
+      {
+        return -ZAI_INCONSISTENCY_ERROR;
+      }
+      
+      inBufIndex+= 1 + sz;
+      req_struct->in_buf_index = inBufIndex;
+    }
     else
     {
       jam();
@@ -2503,6 +2568,48 @@ Dbtup::read_pseudo(const Uint32 * inBuff
       sz = 2;
     }
     break;
+  case AttributeHeader::ROW_GCI64:
+  {
+    sz = 0;
+    if (req_struct->tablePtrP->m_bits & Tablerec::TR_RowGCI)
+    {
+      Uint32 tmp0 = *req_struct->m_tuple_ptr->get_mm_gci(req_struct->tablePtrP);
+      Uint32 tmp1 = ~Uint32(0);
+      if (req_struct->tablePtrP->m_bits & Tablerec::TR_ExtraRowGCIBits)
+      {
+        Uint32 attrId =
+          req_struct->tablePtrP->getExtraAttrId<Tablerec::TR_ExtraRowGCIBits>();
+        read_extra_row_bits(attrId,
+                            req_struct->tablePtrP,
+                            req_struct->m_tuple_ptr,
+                            &tmp1,
+                            /* extend */ true);
+      }
+      Uint64 tmp = Uint64(tmp0) << 32 | tmp1;
+      memcpy(outBuffer + 1, &tmp, sizeof(tmp));
+      sz = 2;
+    }
+    break;
+  }
+  case AttributeHeader::ROW_AUTHOR:
+  {
+    sz = 0;
+    if (req_struct->tablePtrP->m_bits & Tablerec::TR_ExtraRowAuthorBits)
+    {
+      Uint32 attrId = req_struct->tablePtrP
+        ->getExtraAttrId<Tablerec::TR_ExtraRowAuthorBits>();
+
+      Uint32 tmp;
+      read_extra_row_bits(attrId,
+                          req_struct->tablePtrP,
+                          req_struct->m_tuple_ptr,
+                          &tmp,
+                          /* extend */ false);
+      outBuffer[1] = tmp;
+      sz = 1;
+    }
+    break;
+  }
   case AttributeHeader::ANY_VALUE:
   {
     /**
@@ -3347,3 +3454,85 @@ Dbtup::read_lcp_keys(Uint32 tableId,
 
   return ret;
 }
+
+bool
+Dbtup::store_extra_row_bits(Uint32 extra_no,
+                            const Tablerec* regTabPtr,
+                            Tuple_header* ptr,
+                            Uint32 value,
+                            bool truncate)
+{
+  jam();
+  if (unlikely(extra_no >= regTabPtr->m_no_of_extra_columns))
+    return false;
+  /**
+   * ExtraRowGCIBits are using regTabPtr->m_no_of_attributes + extra_no
+   */
+  Uint32 num_attr= regTabPtr->m_no_of_attributes;
+  Uint32 attrId = num_attr + extra_no;
+  Uint32 descr_start = regTabPtr->tabDescriptor;
+  TableDescriptor *tab_descr = &tableDescriptor[descr_start];
+  ndbrequire(descr_start + (attrId << ZAD_LOG_SIZE)<= cnoOfTabDescrRec);
+
+  Uint32 attrDescriptorIndex = attrId << ZAD_LOG_SIZE;
+  Uint32 attrDescriptor = tab_descr[attrDescriptorIndex].tabDescr;
+  Uint32 attrOffset = tab_descr[attrDescriptorIndex + 1].tabDescr;
+
+  Uint32 pos = AttributeOffset::getNullFlagPos(attrOffset);
+  Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+  Uint32 maxVal = (1 << bitCount) - 1;
+  Uint32 *bits= ptr->get_null_bits(regTabPtr);
+
+  if (value > maxVal)
+  {
+    if (truncate)
+    {
+      value = maxVal;
+    }
+    else
+    {
+      return false;
+    }
+  }
+
+  Uint32 check = regTabPtr->m_offsets[MM].m_null_words;
+  BitmaskImpl::setField(check, bits, pos, bitCount, &value);
+  return true;
+}
+
+void
+Dbtup::read_extra_row_bits(Uint32 extra_no,
+                           const Tablerec* regTabPtr,
+                           Tuple_header* ptr,
+                           Uint32 * value,
+                           bool extend)
+{
+  /**
+   * ExtraRowGCIBits are using regTabPtr->m_no_of_attributes + extra_no
+   */
+  ndbrequire(extra_no < regTabPtr->m_no_of_extra_columns);
+  Uint32 num_attr= regTabPtr->m_no_of_attributes;
+  Uint32 attrId = num_attr + extra_no;
+  Uint32 descr_start = regTabPtr->tabDescriptor;
+  TableDescriptor *tab_descr = &tableDescriptor[descr_start];
+  ndbrequire(descr_start + (attrId << ZAD_LOG_SIZE)<= cnoOfTabDescrRec);
+
+  Uint32 attrDescriptorIndex = attrId << ZAD_LOG_SIZE;
+  Uint32 attrDescriptor = tab_descr[attrDescriptorIndex].tabDescr;
+  Uint32 attrOffset = tab_descr[attrDescriptorIndex + 1].tabDescr;
+
+  Uint32 pos = AttributeOffset::getNullFlagPos(attrOffset);
+  Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+  Uint32 maxVal = (1 << bitCount) - 1;
+  Uint32 *bits= ptr->get_null_bits(regTabPtr);
+
+  Uint32 tmp;
+  Uint32 check = regTabPtr->m_offsets[MM].m_null_words;
+  BitmaskImpl::getField(check, bits, pos, bitCount, &tmp);
+
+  if (tmp == maxVal && extend)
+  {
+    tmp = ~Uint32(0);
+  }
+  * value = tmp;
+}

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp	2010-10-03 01:41:32 +0000
@@ -154,8 +154,15 @@ void Dbtup::allocCopyProcedure()
     ndbrequire(appendToSection(iVal, &ahWord, 1));
   }
 
+  /* Add space for extra attrs */
+  ahWord = 0;
+  for (Uint32 extra=0; extra < EXTRA_COPY_PROC_WORDS; extra++)
+    ndbrequire(appendToSection(iVal, &ahWord, 1));
+  
   cCopyProcedure= iVal;
   cCopyLastSeg= RNIL;
+  cCopyOverwrite= 0;
+  cCopyOverwriteLen= 0;
 }
 
 void Dbtup::freeCopyProcedure()
@@ -166,7 +173,8 @@ void Dbtup::freeCopyProcedure()
   cCopyProcedure=RNIL;
 }
 
-void Dbtup::prepareCopyProcedure(Uint32 numAttrs)
+void Dbtup::prepareCopyProcedure(Uint32 numAttrs,
+                                 Uint16 tableBits)
 {
   /* Set length of copy procedure section to the
    * number of attributes supplied
@@ -174,23 +182,51 @@ void Dbtup::prepareCopyProcedure(Uint32 
   ndbassert(numAttrs <= MAX_ATTRIBUTES_IN_TABLE);
   ndbassert(cCopyProcedure != RNIL);
   ndbassert(cCopyLastSeg == RNIL);
+  ndbassert(cCopyOverwrite == 0);
+  ndbassert(cCopyOverwriteLen == 0);
   Ptr<SectionSegment> first;
   g_sectionSegmentPool.getPtr(first, cCopyProcedure);
 
   /* Record original 'last segment' of section */
   cCopyLastSeg= first.p->m_lastSegment;
 
+  /* Check table bits to see if we need to do extra reads */
+  Uint32 extraAttrIds[EXTRA_COPY_PROC_WORDS];
+  Uint32 extraReads = 0;
+
+  if (tableBits & Tablerec::TR_ExtraRowGCIBits)
+  {
+    AttributeHeader ah(AttributeHeader::ROW_GCI64,0);
+    extraAttrIds[extraReads++] = ah.m_value;
+  }
+  if (tableBits & Tablerec::TR_ExtraRowAuthorBits)
+  {
+    AttributeHeader ah(AttributeHeader::ROW_AUTHOR,0);
+    extraAttrIds[extraReads++] = ah.m_value;
+  }
+
   /* Modify section to represent relevant prefix 
    * of code by modifying size and lastSegment
    */
-  first.p->m_sz= numAttrs;
+  Uint32 newSize = numAttrs + extraReads;
+  first.p->m_sz= newSize;
 
+  if (extraReads)
+  {
+    cCopyOverwrite= numAttrs;
+    cCopyOverwriteLen = extraReads;
+
+    ndbrequire(writeToSection(first.i, numAttrs, extraAttrIds, extraReads));
+  }
+
+  /* Trim section size and lastSegment */
   Ptr<SectionSegment> curr= first;  
-  while(numAttrs > SectionSegment::DataLength)
+  while(newSize > SectionSegment::DataLength)
   {
     g_sectionSegmentPool.getPtr(curr, curr.p->m_nextSegment);
-    numAttrs-= SectionSegment::DataLength;
+    newSize-= SectionSegment::DataLength;
   }
+
   first.p->m_lastSegment= curr.i;
 }
 
@@ -203,10 +239,24 @@ void Dbtup::releaseCopyProcedure()
   Ptr<SectionSegment> first;
   g_sectionSegmentPool.getPtr(first, cCopyProcedure);
   
-  ndbassert(first.p->m_sz <= MAX_ATTRIBUTES_IN_TABLE);
-  first.p->m_sz= MAX_ATTRIBUTES_IN_TABLE;
+  ndbassert(first.p->m_sz <= MAX_COPY_PROC_LEN);
+  first.p->m_sz= MAX_COPY_PROC_LEN;
   first.p->m_lastSegment= cCopyLastSeg;
   
+  if (cCopyOverwriteLen)
+  {
+    ndbassert(cCopyOverwriteLen <= EXTRA_COPY_PROC_WORDS);
+    Uint32 attrids[EXTRA_COPY_PROC_WORDS];
+    for (Uint32 i=0; i < cCopyOverwriteLen; i++)
+    {
+      AttributeHeader ah(cCopyOverwrite + i, 0);
+      attrids[i] = ah.m_value;
+    }
+    ndbrequire(writeToSection(first.i, cCopyOverwrite, attrids, cCopyOverwriteLen));
+    cCopyOverwriteLen= 0;
+    cCopyOverwrite= 0;
+  }
+
   cCopyLastSeg= RNIL;
 }
   
@@ -222,8 +272,13 @@ void Dbtup::copyProcedure(Signal* signal
    * This assumes that there is only one fragment copy going
    * on at any time, which is verified by checking 
    * cCopyLastSeg == RNIL before starting each copy
+   *
+   * If the table has extra per-row metainformation that
+   * needs copied then we add that to the copy procedure
+   * as well.
    */
-  prepareCopyProcedure(regTabPtr.p->m_no_of_attributes);
+  prepareCopyProcedure(regTabPtr.p->m_no_of_attributes,
+                       regTabPtr.p->m_bits);
 
   SectionHandle handle(this);
   handle.m_cnt=1;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp	2009-09-16 10:52:41 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp	2010-10-03 01:41:32 +0000
@@ -35,8 +35,11 @@
  */
 
 Uint32
-Dbtup::getTabDescrOffsets(Uint32 noOfAttrs, Uint32 noOfCharsets,
-                          Uint32 noOfKeyAttr, Uint32* offset)
+Dbtup::getTabDescrOffsets(Uint32 noOfAttrs,
+                          Uint32 noOfCharsets,
+                          Uint32 noOfKeyAttr,
+                          Uint32 extraColumns,
+                          Uint32* offset)
 {
   // belongs to configure.in
   unsigned sizeOfPointer = sizeof(CHARSET_INFO*);
@@ -50,7 +53,7 @@ Dbtup::getTabDescrOffsets(Uint32 noOfAtt
   offset[2] = allocSize += noOfAttrs * sizeOfReadFunction();
   offset[3] = allocSize += noOfCharsets * sizeOfPointer;
   offset[4] = allocSize += noOfKeyAttr;
-  offset[5] = allocSize += noOfAttrs * ZAD_SIZE;
+  offset[5] = allocSize += (noOfAttrs + extraColumns) * ZAD_SIZE;
   offset[6] = allocSize += (noOfAttrs+1) >> 1;  // real order
   allocSize += ZTD_TRAILER_SIZE;
   // return number of words
@@ -318,6 +321,7 @@ Dbtup::verifytabdes()
         const Uint32 alloc = getTabDescrOffsets(ptr.p->m_no_of_attributes,
                                                 ptr.p->noOfCharsets,
                                                 ptr.p->noOfKeyAttr,
+                                                ptr.p->m_no_of_extra_columns,
                                                 offset);
         const Uint32 desc = ptr.p->readKeyArray - offset[3];
         Uint32 size = alloc;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp	2010-09-03 05:35:51 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp	2010-10-03 01:41:32 +0000
@@ -619,6 +619,7 @@ void Dbtup::checkDetachedTriggers(KeyReq
   switch (save_type) {
   case ZUPDATE:
   case ZINSERT:
+  case ZREFRESH:
     req_struct->m_tuple_ptr =get_copy_tuple(&regOperPtr->m_copy_tuple_location);
     break;
   }
@@ -634,7 +635,10 @@ void Dbtup::checkDetachedTriggers(KeyReq
       return;
       goto end;
     }
-    regOperPtr->op_struct.op_type = ZINSERT;
+    else if (save_type != ZREFRESH)
+    {
+      regOperPtr->op_struct.op_type = ZINSERT;
+    }
   }
   else if (save_type == ZINSERT) {
     /**
@@ -686,6 +690,25 @@ void Dbtup::checkDetachedTriggers(KeyReq
                          regTablePtr->subscriptionUpdateTriggers, 
                          regOperPtr, disk);
     break;
+  case ZREFRESH:
+    jam();
+    switch(regOperPtr->m_copy_tuple_location.m_file_no){
+    case 1:
+    case 3:
+      fireDetachedTriggers(req_struct,
+                           regTablePtr->subscriptionDeleteTriggers,
+                           regOperPtr, disk);
+      break;
+    case 2:
+    case 4:
+      fireDetachedTriggers(req_struct,
+                           regTablePtr->subscriptionInsertTriggers,
+                           regOperPtr, disk);
+      break;
+    default:
+      ndbrequire(false);
+    }
+    break;
   default:
     ndbrequire(false);
     break;
@@ -1055,12 +1078,14 @@ out:
 
     switch(regOperPtr->op_struct.op_type) {
     case(ZINSERT):
+    is_insert:
       jam();
       // Send AttrInfo signals with new attribute values
       trigAttrInfo->setAttrInfoType(TrigAttrInfo::AFTER_VALUES);
       sendTrigAttrInfo(signal, afterBuffer, noAfterWords, executeDirect, ref);
       break;
     case(ZDELETE):
+    is_delete:
       if (trigPtr->sendBeforeValues) {
         jam();
         trigAttrInfo->setAttrInfoType(TrigAttrInfo::BEFORE_VALUES);
@@ -1077,6 +1102,22 @@ out:
       trigAttrInfo->setAttrInfoType(TrigAttrInfo::AFTER_VALUES);
       sendTrigAttrInfo(signal, afterBuffer, noAfterWords, executeDirect, ref);
       break;
+    case ZREFRESH:
+      jam();
+      switch(regOperPtr->m_copy_tuple_location.m_file_no){
+      case 1:
+        jam();
+      case 3:
+        jam();
+        goto is_delete;
+      case 2:
+        jam();
+      case 4:
+        jam();
+        goto is_insert;
+      default:
+        ndbrequire(false);
+      }
     default:
       ndbrequire(false);
     }
@@ -1104,6 +1145,25 @@ out:
     jam();
     fireTrigOrd->m_triggerEvent = TriggerEvent::TE_DELETE;
     break;
+  case ZREFRESH:
+    jam();
+    switch(regOperPtr->m_copy_tuple_location.m_file_no){
+    case 1:
+      jam();
+    case 3:
+      jam();
+      fireTrigOrd->m_triggerEvent = TriggerEvent::TE_DELETE;
+      break;
+    case 2:
+      jam();
+    case 4:
+      jam();
+      fireTrigOrd->m_triggerEvent = TriggerEvent::TE_INSERT;
+      break;
+    default:
+      ndbrequire(false);
+    }
+    break;
   default:
     ndbrequire(false);
     break;
@@ -1295,7 +1355,7 @@ bool Dbtup::readTriggerInfo(TupTriggerDa
 // Delete without sending before values only read Primary Key
 //--------------------------------------------------------------------
     return true;
-  } else {
+  } else if (regOperPtr->op_struct.op_type != ZREFRESH){
     jam();
 //--------------------------------------------------------------------
 // All others send all attributes that are monitored, except:
@@ -1312,6 +1372,25 @@ bool Dbtup::readTriggerInfo(TupTriggerDa
     numAttrsToRead = setAttrIds(attributeMask, regTabPtr->m_no_of_attributes,
                                 &readBuffer[0]);
   }
+  else
+  {
+    jam();
+    switch(regOperPtr->m_copy_tuple_location.m_file_no){
+    case 1:
+    case 3:
+      return true; // generate ZDELETE...no before values
+    case 2:
+    case 4:
+      // generate ZINSERT...all after values
+      numAttrsToRead = setAttrIds(trigPtr->attributeMask,
+                                  regTabPtr->m_no_of_attributes,
+                                  &readBuffer[0]);
+      break;
+    default:
+      ndbrequire(false);
+    }
+  }
+
   ndbrequire(numAttrsToRead <= MAX_ATTRIBUTES_IN_TABLE);
 //--------------------------------------------------------------------
 // Read Main tuple values
@@ -1555,6 +1634,8 @@ Dbtup::executeTuxCommitTriggers(Signal* 
       return;
     jam();
     tupVersion= regOperPtr->tupVersion;
+  } else if (regOperPtr->op_struct.op_type == ZREFRESH) {
+    return;
   } else {
     ndbrequire(false);
     tupVersion= 0; // remove warning
@@ -1587,6 +1668,9 @@ Dbtup::executeTuxAbortTriggers(Signal* s
   } else if (regOperPtr->op_struct.op_type == ZDELETE) {
     jam();
     return;
+  } else if (regOperPtr->op_struct.op_type == ZREFRESH) {
+    jam();
+    return;
   } else {
     ndbrequire(false);
     tupVersion= 0; // remove warning

=== modified file 'storage/ndb/src/kernel/vm/LongSignal.cpp'
--- a/storage/ndb/src/kernel/vm/LongSignal.cpp	2009-03-20 17:03:34 +0000
+++ b/storage/ndb/src/kernel/vm/LongSignal.cpp	2010-10-03 01:41:32 +0000
@@ -400,3 +400,58 @@ releaseSection(SPC_ARG Uint32 firstSegme
                                      p->m_lastSegment);
   }
 }
+
+bool
+writeToSection(Uint32 firstSegmentIVal, Uint32 offset, 
+               const Uint32* src,
+               Uint32 len)
+{
+  Ptr<SectionSegment> segPtr;
+
+  if (len == 0)
+    return true;
+
+  if (firstSegmentIVal == RNIL)
+  {
+    return false;
+  }
+  else
+  {
+    /* Section has at least one segment with data already */
+    g_sectionSegmentPool.getPtr(segPtr, firstSegmentIVal);
+
+    Uint32 existingLen= segPtr.p->m_sz;
+
+    assert(existingLen > 0);
+    if (offset >= existingLen)
+      return false;         /* No sparse sections or extension */    
+    if (len > (existingLen - offset))
+      return false;         /* Would be extending beyond current length */
+
+    /* Advance through segments to the one containing the start offset */
+    while (offset >= SectionSegment::DataLength)
+    {
+      g_sectionSegmentPool.getPtr(segPtr, segPtr.p->m_nextSegment);
+      offset-= SectionSegment::DataLength;
+    }
+    
+    /* Now overwrite the words */
+    while (true)
+    {
+      Uint32 wordsToCopy = MIN(len, 
+                               SectionSegment::DataLength - offset);
+      memcpy(&segPtr.p->theData[offset], src, (wordsToCopy << 2));
+      src+= wordsToCopy;
+      len-= wordsToCopy;
+      
+      if (!len)
+      {
+        return true;
+      }
+
+      offset = 0;
+      g_sectionSegmentPool.getPtr(segPtr, segPtr.p->m_nextSegment);
+    }
+  }    
+}  
+

=== modified file 'storage/ndb/src/kernel/vm/LongSignalImpl.hpp'
--- a/storage/ndb/src/kernel/vm/LongSignalImpl.hpp	2008-10-08 19:09:05 +0000
+++ b/storage/ndb/src/kernel/vm/LongSignalImpl.hpp	2010-10-03 01:41:32 +0000
@@ -47,6 +47,8 @@ bool import(SPC_ARG Ptr<SectionSegment> 
 bool appendToSection(SPC_ARG Uint32& firstSegmentIVal, const Uint32* src, Uint32 len);
 /* dupSection : Create new section as copy of src section */
 bool dupSection(SPC_ARG Uint32& copyFirstIVal, Uint32 srcFirstIVal);
+/* writeToSection : Overwrite section from offset with data.  */
+bool writeToSection(Uint32 firstSegmentIVal, Uint32 offset, const Uint32* src, Uint32 len);
 
 void release(SPC_ARG SegmentedSectionPtr & ptr);
 void releaseSection(SPC_ARG Uint32 firstSegmentIVal);

=== modified file 'storage/ndb/src/kernel/vm/SimulatedBlock.cpp'
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp	2010-06-10 14:32:07 +0000
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp	2010-10-03 01:41:32 +0000
@@ -1575,6 +1575,13 @@ SimulatedBlock::dupSection(Uint32& copyF
   return ::dupSection(SB_SP_ARG copyFirstIVal, srcFirstIVal);
 }
 
+bool
+SimulatedBlock::writeToSection(Uint32 firstSegmentIVal, Uint32 offset, 
+                               const Uint32* src, Uint32 len)
+{
+  return ::writeToSection(firstSegmentIVal, offset, src, len);
+}
+
 class SectionSegmentPool& 
 SimulatedBlock::getSectionSegmentPool(){
   return g_sectionSegmentPool;

=== modified file 'storage/ndb/src/kernel/vm/SimulatedBlock.hpp'
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp	2010-08-20 11:10:25 +0000
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp	2010-10-03 01:41:32 +0000
@@ -326,6 +326,7 @@ protected:
   bool import(SegmentedSectionPtr& ptr, const Uint32* src, Uint32 len);
   bool appendToSection(Uint32& firstSegmentIVal, const Uint32* src, Uint32 len);
   bool dupSection(Uint32& copyFirstIVal, Uint32 srcFirstIVal);
+  bool writeToSection(Uint32 firstSegmentIVal, Uint32 offset, const Uint32* src, Uint32 len);
 
   void handle_invalid_sections_in_send_signal(Signal*) const;
   void handle_lingering_sections_after_execute(Signal*) const;

=== modified file 'storage/ndb/src/ndbapi/NdbDictionary.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionary.cpp	2010-09-30 14:27:18 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp	2010-10-03 01:41:32 +0000
@@ -915,6 +915,36 @@ NdbDictionary::Table::getRowGCIIndicator
 }
 
 void
+NdbDictionary::Table::setExtraRowGciBits(Uint32 val)
+{
+  if (val <= 31)
+  {
+    m_impl.m_extra_row_gci_bits = val;
+  }
+}
+
+Uint32
+NdbDictionary::Table::getExtraRowGciBits() const
+{
+  return m_impl.m_extra_row_gci_bits;
+}
+
+void
+NdbDictionary::Table::setExtraRowAuthorBits(Uint32 val)
+{
+  if (val <= 31)
+  {
+    m_impl.m_extra_row_author_bits = val;
+  }
+}
+
+Uint32
+NdbDictionary::Table::getExtraRowAuthorBits() const
+{
+  return m_impl.m_extra_row_author_bits;
+}
+
+void
 NdbDictionary::Table::setForceVarPart(bool val){
   m_impl.m_force_var_part = val;
 }

=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2010-10-01 10:08:29 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2010-10-03 01:41:32 +0000
@@ -378,6 +378,10 @@ NdbColumnImpl::create_pseudo_columns()
     NdbColumnImpl::create_pseudo("NDB$ROWID");
   NdbDictionary::Column::ROW_GCI=
     NdbColumnImpl::create_pseudo("NDB$ROW_GCI");
+  NdbDictionary::Column::ROW_GCI64 =
+    NdbColumnImpl::create_pseudo("NDB$ROW_GCI64");
+  NdbDictionary::Column::ROW_AUTHOR =
+    NdbColumnImpl::create_pseudo("NDB$ROW_AUTHOR");
   NdbDictionary::Column::ANY_VALUE=
     NdbColumnImpl::create_pseudo("NDB$ANY_VALUE");
   NdbDictionary::Column::COPY_ROWID=
@@ -408,6 +412,8 @@ NdbColumnImpl::destory_pseudo_columns()
   delete NdbDictionary::Column::RECORDS_IN_RANGE;
   delete NdbDictionary::Column::ROWID;
   delete NdbDictionary::Column::ROW_GCI;
+  delete NdbDictionary::Column::ROW_GCI64;
+  delete NdbDictionary::Column::ROW_AUTHOR;
   delete NdbDictionary::Column::ANY_VALUE;
   delete NdbDictionary::Column::OPTIMIZE;
   NdbDictionary::Column::FRAGMENT= 0;
@@ -421,6 +427,8 @@ NdbColumnImpl::destory_pseudo_columns()
   NdbDictionary::Column::RECORDS_IN_RANGE= 0;
   NdbDictionary::Column::ROWID= 0;
   NdbDictionary::Column::ROW_GCI= 0;
+  NdbDictionary::Column::ROW_GCI64= 0;
+  NdbDictionary::Column::ROW_AUTHOR= 0;
   NdbDictionary::Column::ANY_VALUE= 0;
   NdbDictionary::Column::OPTIMIZE= 0;
 
@@ -499,6 +507,18 @@ NdbColumnImpl::create_pseudo(const char 
     col->m_impl.m_attrSize = 8;
     col->m_impl.m_arraySize = 1;
     col->m_impl.m_nullable = true;
+  } else if(!strcmp(name, "NDB$ROW_GCI64")){
+    col->setType(NdbDictionary::Column::Bigunsigned);
+    col->m_impl.m_attrId = AttributeHeader::ROW_GCI64;
+    col->m_impl.m_attrSize = 8;
+    col->m_impl.m_arraySize = 1;
+    col->m_impl.m_nullable = true;
+  } else if(!strcmp(name, "NDB$ROW_AUTHOR")){
+    col->setType(NdbDictionary::Column::Unsigned);
+    col->m_impl.m_attrId = AttributeHeader::ROW_AUTHOR;
+    col->m_impl.m_attrSize = 4;
+    col->m_impl.m_arraySize = 1;
+    col->m_impl.m_nullable = true;
   } else if(!strcmp(name, "NDB$ANY_VALUE")){
     col->setType(NdbDictionary::Column::Unsigned);
     col->m_impl.m_attrId = AttributeHeader::ANY_VALUE;
@@ -637,6 +657,8 @@ NdbTableImpl::init(){
   m_single_user_mode = 0;
   m_hash_map_id = RNIL;
   m_hash_map_version = ~0;
+  m_extra_row_gci_bits = 0;
+  m_extra_row_author_bits = 0;
 }
 
 bool
@@ -831,6 +853,22 @@ NdbTableImpl::equal(const NdbTableImpl& 
     DBUG_RETURN(false);
   }
 
+  if (m_extra_row_gci_bits != obj.m_extra_row_gci_bits)
+  {
+    DBUG_PRINT("info",("m_extra_row_gci_bits %d != %d",
+                       (int32)m_extra_row_gci_bits,
+                       (int32)obj.m_extra_row_gci_bits));
+    DBUG_RETURN(false);
+  }
+
+  if (m_extra_row_author_bits != obj.m_extra_row_author_bits)
+  {
+    DBUG_PRINT("info",("m_extra_row_author_bits %d != %d",
+                       (int32)m_extra_row_author_bits,
+                       (int32)obj.m_extra_row_author_bits));
+    DBUG_RETURN(false);
+  }
+
   DBUG_RETURN(true);
 }
 
@@ -896,6 +934,8 @@ NdbTableImpl::assign(const NdbTableImpl&
   m_fragmentCount = org.m_fragmentCount;
   
   m_single_user_mode = org.m_single_user_mode;
+  m_extra_row_gci_bits = org.m_extra_row_gci_bits;
+  m_extra_row_author_bits = org.m_extra_row_author_bits;
 
   if (m_index != 0)
     delete m_index;
@@ -2718,6 +2758,8 @@ NdbDictInterface::parseTableInfo(NdbTabl
   impl->m_minLoadFactor = tableDesc->MinLoadFactor;
   impl->m_maxLoadFactor = tableDesc->MaxLoadFactor;
   impl->m_single_user_mode = tableDesc->SingleUserMode;
+  impl->m_extra_row_gci_bits = tableDesc->ExtraRowGCIBits;
+  impl->m_extra_row_author_bits = tableDesc->ExtraRowAuthorBits;
 
   impl->m_indexType = (NdbDictionary::Object::Type)
     getApiConstant(tableDesc->TableType,
@@ -3233,7 +3275,9 @@ NdbDictInterface::compChangeMask(const N
      impl.m_tablespace_version != old_impl.m_tablespace_version ||
      impl.m_id != old_impl.m_id ||
      impl.m_version != old_impl.m_version ||
-     sz < old_sz)
+     sz < old_sz ||
+     impl.m_extra_row_gci_bits != old_impl.m_extra_row_gci_bits ||
+     impl.m_extra_row_author_bits != old_impl.m_extra_row_author_bits)
   {
     DBUG_PRINT("info", ("Old and new table not compatible"));
     goto invalid_alter_table;
@@ -3419,6 +3463,8 @@ NdbDictInterface::serializeTableDesc(Ndb
   tmpTab->LinearHashFlag = impl.m_linear_flag;
   tmpTab->SingleUserMode = impl.m_single_user_mode;
   tmpTab->ForceVarPartFlag = impl.m_force_var_part;
+  tmpTab->ExtraRowGCIBits = impl.m_extra_row_gci_bits;
+  tmpTab->ExtraRowAuthorBits = impl.m_extra_row_author_bits;
 
   tmpTab->FragmentType = getKernelConstant(impl.m_fragmentType,
  					   fragmentTypeMapping,
@@ -8310,6 +8356,8 @@ const NdbDictionary::Column * NdbDiction
 const NdbDictionary::Column * NdbDictionary::Column::RECORDS_IN_RANGE = 0;
 const NdbDictionary::Column * NdbDictionary::Column::ROWID = 0;
 const NdbDictionary::Column * NdbDictionary::Column::ROW_GCI = 0;
+const NdbDictionary::Column * NdbDictionary::Column::ROW_GCI64 = 0;
+const NdbDictionary::Column * NdbDictionary::Column::ROW_AUTHOR = 0;
 const NdbDictionary::Column * NdbDictionary::Column::ANY_VALUE = 0;
 const NdbDictionary::Column * NdbDictionary::Column::COPY_ROWID = 0;
 const NdbDictionary::Column * NdbDictionary::Column::OPTIMIZE = 0;

=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp	2010-10-01 10:08:29 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp	2010-10-03 01:41:32 +0000
@@ -235,6 +235,8 @@ public:
   Uint16 m_keyLenInWords;
   Uint16 m_fragmentCount;
   Uint8 m_single_user_mode;
+  Uint8 m_extra_row_gci_bits;
+  Uint8 m_extra_row_author_bits;
 
   NdbIndexImpl * m_index;
   NdbColumnImpl * getColumn(unsigned attrId);

=== modified file 'storage/ndb/src/ndbapi/NdbOperationExec.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2010-09-30 09:32:28 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2010-10-03 01:41:32 +0000
@@ -1118,7 +1118,8 @@ NdbOperation::buildSignalsNdbRecord(Uint
   /* Final update signal words */
   if ((tOpType == InsertRequest) || 
       (tOpType == WriteRequest) ||
-      (tOpType == UpdateRequest))
+      (tOpType == UpdateRequest) ||
+      (tOpType == RefreshRequest))
   {
     updRow= m_attribute_row;
     NdbBlob *currentBlob= theBlobList;
@@ -1331,7 +1332,8 @@ NdbOperation::buildSignalsNdbRecord(Uint
 
   if ((tOpType == InsertRequest) ||
       (tOpType == WriteRequest) ||
-      (tOpType == UpdateRequest))
+      (tOpType == UpdateRequest) ||
+      (tOpType == RefreshRequest))
   {
     /* Handle setAnyValue() for all cases except delete */
     if (m_use_any_value)

=== modified file 'storage/ndb/src/ndbapi/NdbTransaction.cpp'
--- a/storage/ndb/src/ndbapi/NdbTransaction.cpp	2010-09-30 14:27:18 +0000
+++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp	2010-10-03 01:41:32 +0000
@@ -1995,6 +1995,7 @@ NdbTransaction::receiveTCKEY_FAILCONF(co
       case NdbOperation::DeleteRequest:
       case NdbOperation::WriteRequest:
       case NdbOperation::UnlockRequest:
+      case NdbOperation::RefreshRequest:
 	tOp = tOp->next();
 	break;
       case NdbOperation::ReadRequest:
@@ -2567,6 +2568,41 @@ NdbTransaction::writeTuple(const NdbReco
   return op;
 }
 
+const NdbOperation *
+NdbTransaction::refreshTuple(const NdbRecord *key_rec, const char *key_row,
+                             const NdbOperation::OperationOptions *opts,
+                             Uint32 sizeOfOptions)
+{
+  /* Check that the NdbRecord specifies the full primary key. */
+  if (!(key_rec->flags & NdbRecord::RecHasAllKeys))
+  {
+    setOperationErrorCodeAbort(4292);
+    return NULL;
+  }
+
+  Uint8 keymask[NDB_MAX_ATTRIBUTES_IN_TABLE/8];
+  bzero(keymask, sizeof(keymask));
+  for (Uint32 i = 0; i<key_rec->key_index_length; i++)
+  {
+    Uint32 id = key_rec->columns[key_rec->key_indexes[i]].attrId;
+    keymask[(id / 8)] |= (1 << (id & 7));
+  }
+
+  NdbOperation *op= setupRecordOp(NdbOperation::RefreshRequest,
+                                  NdbOperation::LM_Exclusive,
+                                  NdbOperation::AbortOnError,
+                                  key_rec, key_row,
+                                  key_rec, key_row,
+                                  keymask /* mask */,
+                                  opts,
+                                  sizeOfOptions);
+  if(!op)
+    return op;
+
+  theSimpleState= 0;
+
+  return op;
+}
 
 NdbScanOperation *
 NdbTransaction::scanTable(const NdbRecord *result_record,

=== modified file 'storage/ndb/src/ndbapi/ndberror.c'
--- a/storage/ndb/src/ndbapi/ndberror.c	2010-05-03 04:49:08 +0000
+++ b/storage/ndb/src/ndbapi/ndberror.c	2010-10-03 01:41:32 +0000
@@ -744,6 +744,7 @@ ErrorBundle ErrorCodes[] = {
   { 2810, DMEC, TR, "No space left on the device" },
   { 2811, DMEC, TR, "Error with file permissions, please check file system" },
   { 2815, DMEC, TR, "Error in reading files, please check file system" },
+  {  920, DMEC, AE, "Row operation defined after refreshTuple()" },
 
   { NO_CONTACT_WITH_PROCESS, DMEC, AE,
     "No contact with the process (dead ?)."},

=== modified file 'storage/ndb/test/include/HugoOperations.hpp'
--- a/storage/ndb/test/include/HugoOperations.hpp	2010-01-28 15:16:46 +0000
+++ b/storage/ndb/test/include/HugoOperations.hpp	2010-10-03 01:41:32 +0000
@@ -87,6 +87,10 @@ public:  
 		     int recordNo,
 		     int numRecords = 1);
   
+  int pkRefreshRecord(Ndb*,
+		     int recordNo,
+		     int numRecords = 1);
+
   int execute_Commit(Ndb*, 
 		     AbortOption ao = AbortOnError);
   int execute_NoCommit(Ndb*,
@@ -109,6 +113,9 @@ public:  
 		   int rowId);
 
   int equalForRow(NdbOperation*, int rowid);
+  int equalForRecord(const NdbRecord*, char * buffer, int rowid);
+  int setValueForRecord(const NdbRecord*, char * buffer, int rowid,
+                        const NdbDictionary::Column*);
 
   bool getPartIdForRow(const NdbOperation* pOp, int rowid, Uint32& partId);
   

=== modified file 'storage/ndb/test/include/HugoTransactions.hpp'
--- a/storage/ndb/test/include/HugoTransactions.hpp	2010-02-18 23:50:31 +0000
+++ b/storage/ndb/test/include/HugoTransactions.hpp	2010-10-03 01:41:32 +0000
@@ -110,6 +110,9 @@ public:
 		   int batch = 1,
 		   bool allowConstraintViolation = true,
 		   int doSleep = 0);
+
+  int pkRefreshRecords(Ndb*, int startFrom, int count = 1, int batch = 1);
+
   int lockRecords(Ndb*,
 		  int records,
 		  int percentToLock = 1,

=== modified file 'storage/ndb/test/ndbapi/testRestartGci.cpp'
--- a/storage/ndb/test/ndbapi/testRestartGci.cpp	2010-09-30 15:26:18 +0000
+++ b/storage/ndb/test/ndbapi/testRestartGci.cpp	2010-10-03 01:41:32 +0000
@@ -29,10 +29,12 @@
  */
 
 struct SavedRecord {
-  int m_gci;
+  Uint64 m_gci;
+  Uint32 m_author;
   BaseString m_str;
-  SavedRecord(int _gci, BaseString _str){ 
+  SavedRecord(Uint64 _gci, Uint32 _author, BaseString _str){ 
     m_gci = _gci; 
+    m_author = _author;
     m_str.assign(_str); 
   }
   SavedRecord(){
@@ -41,7 +43,7 @@ struct SavedRecord {
   };
 };
 Vector<SavedRecord> savedRecords;
-
+Uint64 highestExpectedGci;
 
 #define CHECK(b) if (!(b)) { \
   ndbout << "ERR: "<< step->getName() \
@@ -49,6 +51,109 @@ Vector<SavedRecord> savedRecords;
   result = NDBT_FAILED; \
   break; }
 
+static
+int
+maybeExtraBits(Ndb* ndb, NdbDictionary::Table& tab, int when, void* arg)
+{
+  switch(when){
+  case 0: // Before
+    break;
+  case 1: // After
+    return 0;
+  default:
+    return 0;
+  }
+
+  bool useExtendedBits = ((rand() % 5) != 0);
+  Uint32 numGciBits= rand() % 32;      /* 0 -> 31 */
+  Uint32 numAuthorBits = rand() % 32;  /* 0 -> 31 */ 
+
+  if (useExtendedBits && (numGciBits || numAuthorBits))
+  {
+    ndbout_c("Creating table %s with %u extra Gci and %u extra Author bits",
+             tab.getName(), numGciBits, numAuthorBits);
+    tab.setExtraRowGciBits(numGciBits);
+    tab.setExtraRowAuthorBits(numAuthorBits);
+  }
+  else
+  {
+    ndbout_c("Table has no extra bits");
+  }
+  
+  return 0;
+}
+
+int runDropTable(NDBT_Context* ctx, NDBT_Step* step)
+{
+  GETNDB(step)->getDictionary()->dropTable(ctx->getTableName(0));
+  return NDBT_OK;
+}
+
+int runCreateTable(NDBT_Context* ctx, NDBT_Step* step)
+{
+
+  runDropTable(ctx, step);
+
+  /* Use extra proc to control whether we have extra bits */
+  if (NDBT_Tables::createTable(GETNDB(step),
+                               ctx->getTableName(0),
+                               false, false,
+                               maybeExtraBits) == NDBT_OK)
+  {
+    ctx->setTab(GETNDB(step)->
+                getDictionary()->
+                getTable(ctx->getTableName(0)));
+    return NDBT_OK;
+  }
+  return NDBT_FAILED;
+}
+
+int setRowInNdbRecordBuff(NDBT_Context* ctx,
+                          NDBT_Step* step,
+                          Uint32 recNum,
+                          Uint32 updateCount,
+                          char* buff,
+                          Uint32 buffLen)
+{
+  int result = NDBT_OK;
+  const NdbDictionary::Table* tab = ctx->getTab();
+  do
+  {
+    const NdbRecord* rec = tab->getDefaultRecord();
+    CHECK(rec != NULL);
+    HugoCalculator calc(*tab);
+    Uint32 attrId;
+    CHECK(NdbDictionary::getFirstAttrId(rec, attrId));
+    
+    do
+    {
+      /* Calculate value for this column 'into' correct
+       * position in buffer
+       */
+      char attrBuf[NDB_MAX_TUPLE_SIZE];
+      char* valPtr = NdbDictionary::getValuePtr(rec,
+                                                buff,
+                                                attrId);
+      Uint32 colLen = tab->getColumn(attrId)->getSizeInBytes();
+      
+      assert(((valPtr - buff) + colLen) < buffLen);
+      
+      const char* calcPtr = calc.calcValue(recNum, attrId, updateCount,
+                                           attrBuf, colLen, &colLen);
+      
+      if (calcPtr)
+      {
+        memcpy(valPtr, calcPtr, colLen);
+      }
+
+      if (tab->getColumn(attrId)->getNullable())
+        CHECK(NdbDictionary::setNull(rec, buff, attrId, (calcPtr == NULL)) == 0);
+    } while (NdbDictionary::getNextAttrId(rec, attrId));
+  } while (0);
+  
+  return result;
+}
+  
 int runInsertRememberGci(NDBT_Context* ctx, NDBT_Step* step){
   int result = NDBT_OK;
   int records = ctx->getNumRecords();
@@ -56,7 +161,15 @@ int runInsertRememberGci(NDBT_Context* c
   Ndb* pNdb = GETNDB(step);
   int i = 0;
 
-  while(ctx->isTestStopped() == false && i < records){
+  ndbout_c("Inserting %u records", records);
+  Uint64 minGci = 0xffffffffffffffff;
+  Uint64 maxGci = 0;
+  Uint32 numAuthorBits = ctx->getTab()->getExtraRowAuthorBits();
+  Uint32 authorMask = (1 << numAuthorBits) -1;
+  ndbout_c("numAuthor bits is %u, mask is %x",
+           numAuthorBits, authorMask);
+
+  while(i < records){
     // Insert record and read it in same transaction
     CHECK(hugoOps.startTransaction(pNdb) == 0);
     CHECK(hugoOps.pkInsertRecord(pNdb, i) == 0);
@@ -65,14 +178,50 @@ int runInsertRememberGci(NDBT_Context* c
       result = NDBT_FAILED;
       break;
     }
+    /* Set the author column (if present) */
+    Uint32 authorVal = 0;
+    if (ctx->getTab()->getExtraRowAuthorBits() > 0)
+    {
+      authorVal = (rand() & authorMask);
+      /* Pain here due to need to use NdbRecord */
+      char rowBuff[NDB_MAX_TUPLE_SIZE];
+      const NdbDictionary::Table* tab = ctx->getTab();
+      CHECK(setRowInNdbRecordBuff(ctx, step, i, 0, rowBuff,
+                                  sizeof(rowBuff)) == NDBT_OK);
+      NdbOperation::SetValueSpec setValueSpec;
+      setValueSpec.column = NdbDictionary::Column::ROW_AUTHOR;
+      setValueSpec.value = &authorVal;
+      NdbOperation::OperationOptions opts;
+      opts.optionsPresent= NdbOperation::OperationOptions::OO_SETVALUE;
+      opts.extraSetValues= &setValueSpec;
+      opts.numExtraSetValues = 1;
+      
+      const NdbOperation* update = hugoOps.getTransaction()->
+        updateTuple(tab->getDefaultRecord(), rowBuff,
+                    tab->getDefaultRecord(), rowBuff,
+                    NULL, /* mask */
+                    &opts,
+                    sizeof(opts));
+      CHECK(update != NULL);
+    }
+    /* Read row back */
     CHECK(hugoOps.pkReadRecord(pNdb, i) == 0);
     if (hugoOps.execute_Commit(pNdb) != 0){
       ndbout << "Did not find record in DB " << i << endl;
       result = NDBT_FAILED;
       break;
     }
-    savedRecords.push_back(SavedRecord(hugoOps.getRecordGci(0),
-				     hugoOps.getRecordStr(0)));
+    Uint64 gci;
+    CHECK(hugoOps.getTransaction()->getGCI(&gci) == 0);
+
+    if (gci < minGci)
+      minGci = gci;
+    if (gci > maxGci)
+      maxGci = gci;
+
+    savedRecords.push_back(SavedRecord(gci,
+                                       authorVal,
+                                       hugoOps.getRecordStr(0)));
 
     CHECK(hugoOps.closeTransaction(pNdb) == 0);
     i++;
@@ -80,13 +229,21 @@ int runInsertRememberGci(NDBT_Context* c
     NdbSleep_MilliSleep(10);
   };
 
+  ndbout_c("  Inserted records from gci %x/%x to gci %x/%x",
+           (Uint32) (minGci >> 32), (Uint32) (minGci & 0xffffffff),
+           (Uint32) (maxGci >> 32), (Uint32) (maxGci & 0xffffffff));
+
+  highestExpectedGci = maxGci;
+
   return result;
 }
 
-int runRestart(NDBT_Context* ctx, NDBT_Step* step){
+int runRestartAll(NDBT_Context* ctx, NDBT_Step* step){
   Ndb* pNdb = GETNDB(step);
   NdbRestarter restarter;
 
+  ndbout_c("Restart of all nodes");
+
   // Restart cluster with abort
   if (restarter.restartAll(false, false, true) != 0){
     ctx->stopTest();
@@ -104,6 +261,42 @@ int runRestart(NDBT_Context* ctx, NDBT_S
   return NDBT_OK;
 }
 
+int runRestartOneInitial(NDBT_Context* ctx, NDBT_Step* step){
+  Ndb* pNdb = GETNDB(step);
+  NdbRestarter restarter;
+
+  if (restarter.getNumDbNodes() < 2)
+    return NDBT_OK;
+
+  /* We don't restart the Master as we need to know a 
+   * non-restarted node to reliably get the restartGci
+   * afterwards!
+   * Should be no real reason not to restart the master.
+   */
+  int node = restarter.getRandomNotMasterNodeId(rand());
+  ndbout_c("Restarting node %u initial", node);
+  
+  if (restarter.restartOneDbNode(node, 
+                                 true,  /* Initial */
+                                 false, /* Nostart */
+                                 true)  /* Abort */
+      != 0)
+  {
+    ctx->stopTest();
+    return NDBT_FAILED;
+  }
+
+  if (restarter.waitClusterStarted(300) != 0){
+    return NDBT_FAILED;
+  }
+  
+  if (pNdb->waitUntilReady() != 0){
+    return NDBT_FAILED;
+  }
+
+  return NDBT_OK;
+}
+
 int runRestartGciControl(NDBT_Context* ctx, NDBT_Step* step){
   int records = ctx->getNumRecords();
   Ndb* pNdb = GETNDB(step);
@@ -119,10 +312,38 @@ int runRestartGciControl(NDBT_Context* c
     NdbSleep_MilliSleep(10);
   }
 
-  // Stop the other thread
-  ctx->stopTest();
+  return runRestartAll(ctx,step);
+}
+
+int runDetermineRestartGci(NDBT_Context* ctx, NDBT_Step* step)
+{
+  Ndb* pNdb = GETNDB(step);
+  Uint32 restartGci;
+  int res = pNdb->getDictionary()->getRestartGCI(&restartGci);
+  if (res != 0)
+  {
+    ndbout << "Failed to retrieve restart gci" << endl;
+    ndbout << pNdb->getDictionary()->getNdbError() << endl;
+    return NDBT_FAILED;
+  }
+  
+  ndbout_c("Restart GCI is %u (0x%x)",
+           restartGci, restartGci);
+  
+  ndbout_c("Highest expected GCI was %x/%x",
+           (Uint32) (highestExpectedGci >> 32),
+           (Uint32) (highestExpectedGci & 0xffffffff));
+  
+  highestExpectedGci = ((Uint64) restartGci) << 32 | 0xffffffff;
+  ndbout_c("Resetting Highest expected GCI to align with restart Gci (%x/%x)",
+           (Uint32) (highestExpectedGci >> 32),
+           (Uint32) (highestExpectedGci & 0xffffffff));
+  return NDBT_OK;
+}
 
-  return runRestart(ctx,step);
+int runRequireExact(NDBT_Context* ctx, NDBT_Step* step){
+  ctx->incProperty("ExactGCI");
+  return NDBT_OK;
 }
 
 int runVerifyInserts(NDBT_Context* ctx, NDBT_Step* step){
@@ -132,16 +353,6 @@ int runVerifyInserts(NDBT_Context* ctx, 
   HugoOperations hugoOps(*ctx->getTab());
   NdbRestarter restarter;
 
-  Uint32 restartGCI;
-  int res = pNdb->getDictionary()->getRestartGCI(&restartGCI);
-  if (res != 0)
-  {
-    ndbout << "Failed to retreive restart gci" << endl;
-    ndbout << pNdb->getDictionary()->getNdbError() << endl;
-    return NDBT_FAILED;
-  }
-
-  ndbout << "restartGCI = " << restartGCI << endl;
   int count = 0;
   if (utilTrans.selectCount(pNdb, 64, &count) != 0){
     return NDBT_FAILED;
@@ -152,7 +363,7 @@ int runVerifyInserts(NDBT_Context* ctx, 
   int recordsWithLowerOrSameGci = 0;
   unsigned i; 
   for (i = 0; i < savedRecords.size(); i++){
-    if (savedRecords[i].m_gci <= (int)restartGCI)
+    if (savedRecords[i].m_gci <= highestExpectedGci)
       recordsWithLowerOrSameGci++;
   }
   if (recordsWithLowerOrSameGci != count){
@@ -160,10 +371,13 @@ int runVerifyInserts(NDBT_Context* ctx, 
     result = NDBT_FAILED;
   }
 
+  bool exactGCIonly = ctx->getProperty("ExactGCI", (unsigned) 0);
 
   // RULE2: The records found in db should have same or lower 
   // gci as in the vector
   int recordsWithIncorrectGci = 0;
+  int recordsWithRoundedGci = 0;
+  int recordsWithIncorrectAuthor = 0;
   for (i = 0; i < savedRecords.size(); i++){
     CHECK(hugoOps.startTransaction(pNdb) == 0);
     /* First read of row to check contents */
@@ -174,13 +388,15 @@ int runVerifyInserts(NDBT_Context* ctx, 
     CHECK(readOp != NULL);
     CHECK(readOp->readTuple() == 0);
     CHECK(hugoOps.equalForRow(readOp, i) == 0);
-    NdbRecAttr* rowGci = readOp->getValue(NdbDictionary::Column::ROW_GCI);
+    NdbRecAttr* rowGci = readOp->getValue(NdbDictionary::Column::ROW_GCI64);
+    NdbRecAttr* rowAuthor = readOp->getValue(NdbDictionary::Column::ROW_AUTHOR);
     CHECK(rowGci != NULL);
+    CHECK(rowAuthor != NULL);
     if (hugoOps.execute_Commit(pNdb) != 0){
       // Record was not found in db'
 
       // Check record gci
-      if (savedRecords[i].m_gci <= (int)restartGCI){
+      if (savedRecords[i].m_gci <= highestExpectedGci) {
 	ndbout << "ERR: Record "<<i<<" should have existed" << endl;
 	result = NDBT_FAILED;
       }
@@ -190,7 +406,7 @@ int runVerifyInserts(NDBT_Context* ctx, 
          * Let's disappear it, so that it doesn't cause confusion
          * after further restarts.
          */
-        savedRecords[i].m_gci = (Uint32(1) << 31) -1; // Big number
+        savedRecords[i].m_gci = (Uint64(1) << 63) -1; // Big number
       }
     } else {
       // Record was found in db
@@ -201,16 +417,42 @@ int runVerifyInserts(NDBT_Context* ctx, 
 	result = NDBT_FAILED;
       }
       // Check record gci in range
-      if (savedRecords[i].m_gci > (int)restartGCI){
+      if (savedRecords[i].m_gci > highestExpectedGci){
 	ndbout << "ERR: Record "<<i<<" should not have existed" << endl;
 	result = NDBT_FAILED;
       }
       // Check record gci is exactly correct
-      if (savedRecords[i].m_gci != rowGci->int32_value()){
-        ndbout << "ERR: Record "<<i<<" should have GCI " <<
-          savedRecords[i].m_gci << ", but has " << 
-          rowGci->int32_value() << endl;
-        recordsWithIncorrectGci++;
+      if (savedRecords[i].m_gci != rowGci->u_64_value()){
+        Uint64 expectedRoundedGci = (savedRecords[i].m_gci | 0xffffffff);
+        if ((!exactGCIonly) && 
+            (expectedRoundedGci != rowGci->u_64_value()))
+        { 
+          ndbout_c("ERR: Record %u should have GCI %x/%x, but has "
+                   "%x/%x.",
+                   i,
+                   (Uint32) (savedRecords[i].m_gci >> 32),
+                   (Uint32) (savedRecords[i].m_gci & 0xffffffff),
+                   (Uint32) (rowGci->u_64_value() >> 32),
+                   (Uint32) (rowGci->u_64_value() & 0xffffffff));
+          recordsWithIncorrectGci++;
+          result = NDBT_FAILED;
+        }
+        else
+        {
+          recordsWithRoundedGci++;
+        }
+      }
+      
+      // Check author value is correct.
+      Uint32 expectedAuthor = savedRecords[i].m_author;
+      
+      if (rowAuthor->u_32_value() != expectedAuthor)
+      {
+        ndbout_c("ERR: Record %u should have Author %d, but has %d.",
+                 i,
+                 expectedAuthor,
+                 rowAuthor->u_32_value());
+        recordsWithIncorrectAuthor++;
         result = NDBT_FAILED;
       }
     }
@@ -223,17 +465,26 @@ int runVerifyInserts(NDBT_Context* ctx, 
   ndbout << "There are " << savedRecords.size() 
 	 << " records in vector" << endl;
 
-  ndbout << "There are " << recordsWithLowerOrSameGci 
-	 << " records with lower or same gci than " << restartGCI <<  endl;
+  ndbout_c("There are %u records with lower or same gci than %x/%x",
+           recordsWithLowerOrSameGci, 
+           (Uint32)(highestExpectedGci >> 32),
+           (Uint32)(highestExpectedGci & 0xffffffff));
   
+  ndbout_c("There are %u records with rounded Gcis.  Exact GCI flag is %u",
+           recordsWithRoundedGci, exactGCIonly);
+
   ndbout << "There are " << recordsWithIncorrectGci
          << " records with incorrect Gci on recovery." << endl;
 
+  ndbout << "There are " << recordsWithIncorrectAuthor
+         << " records with incorrect Author on recovery." << endl;
+
   return result;
 }
 
 int runClearGlobals(NDBT_Context* ctx, NDBT_Step* step){
   savedRecords.clear();
+  highestExpectedGci = 0;
   return NDBT_OK;
 }
 
@@ -252,23 +503,50 @@ NDBT_TESTSUITE(testRestartGci);
 TESTCASE("InsertRestartGci", 
 	 "Verify that only expected records are still in NDB\n"
 	 "after a restart" ){
-  INITIALIZER(runClearTable);
+  INITIALIZER(runCreateTable);
   INITIALIZER(runClearGlobals);
-  STEP(runInsertRememberGci);
-  STEP(runRestartGciControl);
+  INITIALIZER(runInsertRememberGci);
+  INITIALIZER(runRestartGciControl);
+  INITIALIZER(runDetermineRestartGci);
+  TC_PROPERTY("ExactGCI", Uint32(0)); /* Recovery from Redo == inexact low word */
   VERIFIER(runVerifyInserts);
   /* Restart again - LCP after first restart will mean that this
    * time we recover from LCP, not Redo
    */
-  VERIFIER(runRestart);
+  VERIFIER(runRestartAll);
+  VERIFIER(runDetermineRestartGci);
+  VERIFIER(runVerifyInserts);  // Check GCIs again
+  /* Restart again - one node, initial.  This will check 
+   * COPYFRAG behaviour
+   */
+  VERIFIER(runRestartOneInitial);
   VERIFIER(runVerifyInserts);  // Check GCIs again
+  VERIFIER(runClearTable);
+  /* Re-fill table with records, will just be in Redo
+   * Then restart, testing COPYFRAG behaviour with
+   * non #ffff... low word
+   */
+  VERIFIER(runClearGlobals);
+  VERIFIER(runInsertRememberGci);
+  VERIFIER(runRestartOneInitial);
+  /* Require exact GCI match from here - no Redo messing it up */
+  VERIFIER(runRequireExact);
+  VERIFIER(runVerifyInserts);
+  /* Now-restart all nodes - all inserts should be
+   * in LCP, and should be restored correctly
+   */
+  VERIFIER(runRestartAll);
+  VERIFIER(runDetermineRestartGci);
+  VERIFIER(runVerifyInserts);
   FINALIZER(runClearTable);
+  FINALIZER(runDropTable);
 }
 NDBT_TESTSUITE_END(testRestartGci);
 
 int main(int argc, const char** argv){
   ndb_init();
   NDBT_TESTSUITE_INSTANCE(testRestartGci);
+  testRestartGci.setCreateTable(false);
   return testRestartGci.execute(argc, argv);
 }
 

=== modified file 'storage/ndb/test/src/HugoOperations.cpp'
--- a/storage/ndb/test/src/HugoOperations.cpp	2010-05-17 06:56:12 +0000
+++ b/storage/ndb/test/src/HugoOperations.cpp	2010-10-03 01:41:32 +0000
@@ -568,6 +568,39 @@ int HugoOperations::pkDeleteRecord(Ndb* 
   return NDBT_OK;
 }
 
+int HugoOperations::pkRefreshRecord(Ndb* pNdb,
+                                    int recordNo,
+                                    int numRecords){
+
+  char buffer[NDB_MAX_TUPLE_SIZE];
+  const NdbDictionary::Table * pTab =
+    pNdb->getDictionary()->getTable(tab.getName());
+
+  if (pTab == 0)
+  {
+    return NDBT_FAILED;
+  }
+
+  const NdbRecord * record = pTab->getDefaultRecord();
+  for(int r=0; r < numRecords; r++)
+  {
+    bzero(buffer, sizeof(buffer));
+    if (equalForRecord(record, buffer, r + recordNo))
+    {
+      return NDBT_FAILED;
+    }
+
+    const NdbOperation* pOp = pTrans->refreshTuple(record, buffer);
+    if (pOp == NULL)
+    {
+      ERR(pTrans->getNdbError());
+      setNdbError(pTrans->getNdbError());
+      return NDBT_FAILED;
+    }
+  }
+  return NDBT_OK;
+}
+
 int HugoOperations::execute_Commit(Ndb* pNdb,
 				   AbortOption eao){
 
@@ -794,6 +827,43 @@ HugoOperations::equalForRow(NdbOperation
   return NDBT_OK;
 }
 
+int
+HugoOperations::equalForRecord(const NdbRecord* record,
+                               char * buffer, int rowId)
+{
+  for(int a = 0; a<tab.getNoOfColumns(); a++)
+  {
+    const NdbDictionary::Column* attr = tab.getColumn(a);
+    if (attr->getPrimaryKey() == true)
+    {
+      setValueForRecord(record, buffer, rowId, attr);
+    }
+  }
+  return NDBT_OK;
+}
+
+int
+HugoOperations::setValueForRecord(const NdbRecord* record,
+                                  char * buffer, int rowId,
+                                  const NdbDictionary::Column* attr)
+{
+  Uint32 attrId = attr->getColumnNo();
+  int len = attr->getSizeInBytes();
+  char buf[NDB_MAX_TUPLE_SIZE];
+  memset(buf, 0, sizeof(buf));
+  Uint32 real_len;
+  const char * value = calc.calcValue(rowId, attrId, 0, buf, len, &real_len);
+  if (value == 0)
+  {
+    NdbDictionary::setNull(record, buffer, attrId, true);
+  }
+  else
+  {
+    memcpy(NdbDictionary::getValuePtr(record, buffer, attrId), buf, real_len);
+  }
+  return NDBT_OK;
+}
+
 bool HugoOperations::getPartIdForRow(const NdbOperation* pOp,
                                      int rowid,
                                      Uint32& partId)

=== modified file 'storage/ndb/test/src/HugoTransactions.cpp'
--- a/storage/ndb/test/src/HugoTransactions.cpp	2010-02-18 23:50:31 +0000
+++ b/storage/ndb/test/src/HugoTransactions.cpp	2010-10-03 01:41:32 +0000
@@ -1502,6 +1502,79 @@ HugoTransactions::pkDelRecords(Ndb* pNdb
 }
 
 int 
+HugoTransactions::pkRefreshRecords(Ndb* pNdb,
+                                   int startFrom,
+                                   int count,
+                                   int batch)
+{
+  int r = 0;
+  int retryAttempt = 0;
+
+  g_info << "|- Refreshing records..." << startFrom << "-" << (startFrom+count)
+         << " (batch=" << batch << ")" << endl;
+
+  while (r < count)
+  {
+    if(r + batch > count)
+      batch = count - r;
+
+    if (retryAttempt >= m_retryMax)
+    {
+      g_info << "ERROR: has retried this operation " << retryAttempt
+	     << " times, failing!" << endl;
+      return NDBT_FAILED;
+    }
+
+    pTrans = pNdb->startTransaction();
+    if (pTrans == NULL)
+    {
+      const NdbError err = pNdb->getNdbError();
+
+      if (err.status == NdbError::TemporaryError){
+	ERR(err);
+	NdbSleep_MilliSleep(50);
+	retryAttempt++;
+	continue;
+      }
+      ERR(err);
+      return NDBT_FAILED;
+    }
+
+    if (pkRefreshRecord(pNdb, r, batch) != NDBT_OK)
+    {
+      ERR(pTrans->getNdbError());
+      closeTransaction(pNdb);
+      return NDBT_FAILED;
+    }
+
+    if (pTrans->execute(Commit, AbortOnError) == -1)
+    {
+      const NdbError err = pTrans->getNdbError();
+
+      switch(err.status){
+      case NdbError::TemporaryError:
+	ERR(err);
+	closeTransaction(pNdb);
+	NdbSleep_MilliSleep(50);
+	retryAttempt++;
+	continue;
+	break;
+
+      default:
+	ERR(err);
+	closeTransaction(pNdb);
+	return NDBT_FAILED;
+      }
+    }
+
+    closeTransaction(pNdb);
+    r += batch; // Read next record
+  }
+
+  return NDBT_OK;
+}
+
+int
 HugoTransactions::pkReadUnlockRecords(Ndb* pNdb, 
                                       int records,
                                       int batch,

=== modified file 'storage/ndb/test/src/NDBT_Table.cpp'
--- a/storage/ndb/test/src/NDBT_Table.cpp	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/test/src/NDBT_Table.cpp	2010-10-03 01:41:32 +0000
@@ -39,6 +39,8 @@ operator <<(class NdbOut& ndbout, const 
   ndbout << "SingleUserMode: " << (Uint32) tab.getSingleUserMode() << endl;
   ndbout << "ForceVarPart: " << tab.getForceVarPart() << endl;
   ndbout << "FragmentCount: " << tab.getFragmentCount() << endl;
+  ndbout << "ExtraRowGciBits: " << tab.getExtraRowGciBits() << endl;
+  ndbout << "ExtraRowAuthorBits: " << tab.getExtraRowAuthorBits() << endl;
 
   //<< ((tab.getTupleKey() == TupleId) ? " tupleid" : "") <<endl;
   ndbout << "TableStatus: ";

=== modified file 'storage/ndb/test/tools/hugoPkUpdate.cpp'
--- a/storage/ndb/test/tools/hugoPkUpdate.cpp	2009-05-26 18:53:34 +0000
+++ b/storage/ndb/test/tools/hugoPkUpdate.cpp	2010-10-03 01:41:32 +0000
@@ -43,6 +43,8 @@ struct ThrOutput {
   NDBT_Stats latency;
 };
 
+static int _refresh = 0;
+
 int main(int argc, const char** argv){
   ndb_init();
 
@@ -63,7 +65,9 @@ int main(int argc, const char** argv){
     //    { "batch", 'b', arg_integer, &_batch, "batch value", "batch" },
     { "records", 'r', arg_integer, &_records, "Number of records", "records" },
     { "usage", '?', arg_flag, &_help, "Print help", "" },
-    { "database", 'd', arg_string, &db, "Database", "" }
+    { "database", 'd', arg_string, &db, "Database", "" },
+    { "refresh", 0, arg_flag, &_refresh, "refresh record rather than update them", "" }
+
   };
   int num_args = sizeof(args) / sizeof(args[0]);
   int optind = 0;
@@ -177,9 +181,19 @@ static void hugoPkUpdate(NDBT_Thread& th
   hugoTrans.setThrInfo(ths.get_count(), thr.get_thread_no());
 
   int ret;
-  ret = hugoTrans.pkUpdateRecords(thr.get_ndb(),
-                                  input->records,
-                                  input->batch);
+  if (_refresh == 0)
+  {
+    ret = hugoTrans.pkUpdateRecords(thr.get_ndb(),
+                                    input->records,
+                                    input->batch);
+  }
+  else
+  {
+    ret = hugoTrans.pkRefreshRecords(thr.get_ndb(),
+                                     0,
+                                     input->records,
+                                     input->batch);
+  }
   if (ret != 0)
     thr.set_err(ret);
 }

=== modified file 'storage/ndb/tools/select_all.cpp'
--- a/storage/ndb/tools/select_all.cpp	2010-08-16 17:02:58 +0000
+++ b/storage/ndb/tools/select_all.cpp	2010-10-03 01:41:32 +0000
@@ -50,6 +50,8 @@ static int _dumpDisk = 0;
 static int use_rowid = 0;
 static int nodata = 0;
 static int use_gci = 0;
+static int use_gci64 = 0;
+static int use_author = 0;
 
 static struct my_option my_long_options[] =
 {
@@ -87,6 +89,12 @@ static struct my_option my_long_options[
   { "gci", NDB_OPT_NOSHORT, "Dump gci",
     (uchar**) &use_gci, (uchar**) &use_gci, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 
+  { "gci64", NDB_OPT_NOSHORT, "Dump ROW$GCI64",
+    (uchar**) &use_gci64, (uchar**) &use_gci64, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+  { "author", NDB_OPT_NOSHORT, "Dump ROW$AUTHOR",
+    (uchar**) &use_author, (uchar**) &use_author, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
   { "tupscan", 't', "Scan in tup order",
     (uchar**) &_tup, (uchar**) &_tup, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 
@@ -329,7 +337,7 @@ int scanReadRecords(Ndb* pNdb, 
     if(_dumpDisk && disk)
       disk_ref = pOp->getValue(NdbDictionary::Column::DISK_REF);
 
-    NdbRecAttr * rowid= 0, *frag = 0, *gci = 0;
+    NdbRecAttr * rowid= 0, *frag = 0, *gci = 0, *gci64 = 0, *author = 0;
     if (use_rowid)
     {
       frag = pOp->getValue(NdbDictionary::Column::FRAGMENT);
@@ -340,7 +348,17 @@ int scanReadRecords(Ndb* pNdb, 
     {
       gci = pOp->getValue(NdbDictionary::Column::ROW_GCI);
     }
+
+    if (use_gci64)
+    {
+      gci64 = pOp->getValue(NdbDictionary::Column::ROW_GCI64);
+    }
     
+    if (use_author)
+    {
+      author = pOp->getValue(NdbDictionary::Column::ROW_AUTHOR);
+    }
+
     check = pTrans->execute(NdbTransaction::NoCommit);   
     if( check == -1 ) {
       const NdbError err = pTrans->getNdbError();
@@ -387,6 +405,18 @@ int scanReadRecords(Ndb* pNdb, 
         ndbout << "DISK_REF";
       }
 
+      if (gci64)
+      {
+        DELIMITER;
+        ndbout << "ROW$GCI64";
+      }
+
+      if (author)
+      {
+        DELIMITER;
+        ndbout << "ROW$AUTHOR";
+      }
+
       ndbout << endl;
     }
 #undef DELIMITER
@@ -427,8 +457,30 @@ int scanReadRecords(Ndb* pNdb, 
 	       << " m_page: " << disk_ref->u_32_value() 
 	       << " m_page_idx: " << *(Uint16*)(disk_ref->aRef() + 4) << " ]";
       }
+
+      if (gci64)
+      {
+	if (gci64->isNULL())
+	  ndbout << "NULL\t";
+        else
+        {
+          Uint64 tmp = gci64->u_64_value();
+          ndbout << Uint32(tmp >> 32) << "/" << Uint32(tmp) << "\t";
+        }
+      }
+
+      if (author)
+      {
+	if (author->isNULL())
+	  ndbout << "NULL\t";
+        else
+        {
+          ndbout << author->u_32_value() << "\t";
+        }
+      }
+
       
-      if (rowid || disk_ref || gci || !nodata)
+      if (rowid || disk_ref || gci || !nodata || gci64 || author)
 	ndbout << endl;
       eof = pOp->nextResult();
     }


Attachment: [text/bzr-bundle] bzr/frazer@mysql.com-20101003014132-7yu8qc9jdrhlmrpm.bundle
Thread
bzr push into mysql-5.1-telco-7.0 branch (frazer:3820 to 3821) Frazer Clement3 Oct