From: Frazer Clement Date: January 25 2012 5:58pm Subject: bzr push into mysql-5.1-telco-7.0 branch (frazer.clement:4825) List-Archive: http://lists.mysql.com/commits/142539 Message-Id: <201201251759.q0PHx0gH016886@acsmt357.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 4825 Frazer Clement 2012-01-25 [merge] Merge modified: storage/ndb/src/kernel/vm/mt.cpp === modified file 'mysql-test/suite/ndb_rpl/r/ndb_rpl_rep_error.result' --- a/mysql-test/suite/ndb_rpl/r/ndb_rpl_rep_error.result 2012-01-17 13:51:35 +0000 +++ b/mysql-test/suite/ndb_rpl/r/ndb_rpl_rep_error.result 2012-01-25 17:13:13 +0000 @@ -1,9 +1,51 @@ include/master-slave.inc [connection master] +Wrong schema for the table, too few pks create table t1 (a int key, X int) engine ndb; Warnings: -Error 1626 Bad schema for mysql.ndb_replication table. Message: Wrong number of primary key parts, expected 3 +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Wrong number of primary key parts, expected 3 drop table t1; +Wrong schema for the table, incorrect pk +create table t1 (a int key, X int) engine ndb; +Warnings: +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Missing or wrong type for column 'server_id' +drop table t1; +Wrong schema for the table, binlog_type is signed +create table t1 (a int key, X int) engine ndb; +Warnings: +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Missing or wrong type for column 'binlog_type' +drop table t1; +Wrong schema for the table, conflict_fn is too long +create table t1 (a int key, X int) engine ndb; +Warnings: +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Missing or wrong type for column 'conflict_fn' +drop table t1; +Correct schema for the table but no conflict fn +insert into mysql.ndb_replication values ("test", "t1", 0, 7); +create table test.t1 (a int primary key) engine=ndb; +show warnings; +Level Code Message +drop table test.t1; +MySQLD error output for server 1.1 matching pattern %NDB Binlog: logging% +relevant +[note] ndb binlog: logging ./test/t1 (full,use_update) +delete from mysql.ndb_replication; +Check that NULL uses server defaults +show variables like 'ndb_log_update_as_write'; +Variable_name Value +ndb_log_update_as_write ON +show variables like 'ndb_log_updated_only'; +Variable_name Value +ndb_log_updated_only ON +insert into mysql.ndb_replication values ("test", "t1", 0, NULL); +create table test.t1 (a int primary key) engine=ndb; +show warnings; +Level Code Message +drop table test.t1; +MySQLD error output for server 1.1 matching pattern %NDB Binlog: logging% +relevant +[note] ndb binlog: logging ./test/t1 (updated,use_write) +Correct schema for the table but other errors insert into mysql.ndb_replication values ("test", "t1", 0, NULL, "NDB$X(X)"); create table t1 (a int key, X int) engine ndb; ERROR HY000: Can't create table 'test.t1' (errno: 1627) @@ -34,3 +76,249 @@ Level Code Message Error 1627 Error in parsing conflict function. Message: NDB$MAX(X Y), missing ')' at 'Y)' Error 1005 Can't create table 'test.t1' (errno: 1627) delete from mysql.ndb_replication; +show variables like 'server_id'; +Variable_name Value +server_id 1 +create database europenorth; +create database europesouth; +create database usnorth; +create database ussouth; +Basic wildcard tests +Note that we put in bad conflict fn names so that the warnings generated +when the table create fails give an indication of which ndb_replication +table row was chosen. + +Wild serverid +insert into mysql.ndb_replication values ("europenorth", "france", 1, NULL, "NDB$A()"); +insert into mysql.ndb_replication values ("europenorth", "france", 0, NULL, "NDB$B()"); +Should match specific entry (1) with algorithm A. +create table europenorth.france (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.france' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$A(), unknown conflict resolution function at 'NDB$A()' +Error 1005 Can't create table 'europenorth.france' (errno: 1627) +delete from mysql.ndb_replication where server_id=1; +Should match generic entry (0) with algorthin B. +create table europenorth.france (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.france' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()' +Error 1005 Can't create table 'europenorth.france' (errno: 1627) +delete from mysql.ndb_replication; +Wild table_name +insert into mysql.ndb_replication values ("europenorth", "fr_nce", 1, NULL, "NDB$A()"); +insert into mysql.ndb_replication values ("europenorth", "%any", 1, NULL, "NDB$B()"); +Should match specific entry (fr_nce) with algorithm A. +create table europenorth.france (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.france' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$A(), unknown conflict resolution function at 'NDB$A()' +Error 1005 Can't create table 'europenorth.france' (errno: 1627) +Should match specific entry (%any) with algorithm B. +create table europenorth.germany (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.germany' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()' +Error 1005 Can't create table 'europenorth.germany' (errno: 1627) +Should match specific entry (%any) with algorithm B. +create table europenorth.romany (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.romany' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()' +Error 1005 Can't create table 'europenorth.romany' (errno: 1627) +No match, should be fine +create table europenorth.uk (a int primary key) engine=ndb; +show warnings; +Level Code Message +drop table europenorth.uk; +delete from mysql.ndb_replication; +Wild db +insert into mysql.ndb_replication values ("%north", "countries", 1, NULL, "NDB$A()"); +insert into mysql.ndb_replication values ("%south", "countries", 1, NULL, "NDB$B()"); +Should match north with A +create table europenorth.countries (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.countries' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$A(), unknown conflict resolution function at 'NDB$A()' +Error 1005 Can't create table 'europenorth.countries' (errno: 1627) +Should match north with A +create table usnorth.countries (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'usnorth.countries' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$A(), unknown conflict resolution function at 'NDB$A()' +Error 1005 Can't create table 'usnorth.countries' (errno: 1627) +Should match south with B +create table europesouth.countries (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europesouth.countries' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()' +Error 1005 Can't create table 'europesouth.countries' (errno: 1627) +Should match south with B +create table ussouth.countries (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'ussouth.countries' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()' +Error 1005 Can't create table 'ussouth.countries' (errno: 1627) +delete from mysql.ndb_replication; +Now test wildcard matching precedence +Wildcards match in the following precedence (highest->lowest) +Exact match +Wild serverid +Wild table_name +Wild serverid + wild table_name +Wild db +Wild db + wild serverid +Wild db + wild table_name +All wild + +The 'wild serverid' is 0 + +Multiple matches at the same precedence are ambiguous and result +in an error. + +Start with full set of potential matches, and chip away +insert into mysql.ndb_replication values ("europenorth", "netherlands", 1, NULL, "NDB$A()"); +insert into mysql.ndb_replication values ("europenorth", "netherlands", 0, NULL, "NDB$B()"); +insert into mysql.ndb_replication values ("europenorth", "%lands", 1, NULL, "NDB$C()"); +insert into mysql.ndb_replication values ("europenorth", "nether%s", 1, NULL, "NDB$D()"); +insert into mysql.ndb_replication values ("europenorth", "%lands", 0, NULL, "NDB$E()"); +insert into mysql.ndb_replication values ("europenorth", "nether%s", 0, NULL, "NDB$F()"); +insert into mysql.ndb_replication values ("Europe%", "netherlands", 1, NULL, "NDB$G()"); +insert into mysql.ndb_replication values ("%North", "netherlands", 1, NULL, "NDB$H()"); +insert into mysql.ndb_replication values ("Europe%", "netherlands", 0, NULL, "NDB$I()"); +insert into mysql.ndb_replication values ("%North", "netherlands", 0, NULL, "NDB$J()"); +insert into mysql.ndb_replication values ("Europe%", "%lands", 1, NULL, "NDB$K()"); +insert into mysql.ndb_replication values ("%North", "nether%s", 1, NULL, "NDB$L()"); +insert into mysql.ndb_replication values ("Europe%", "%lands", 0, NULL, "NDB$M()"); +insert into mysql.ndb_replication values ("%North", "nether%s", 0, NULL, "NDB$N()"); +Unique match (A) +create table europenorth.netherlands (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.netherlands' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$A(), unknown conflict resolution function at 'NDB$A()' +Error 1005 Can't create table 'europenorth.netherlands' (errno: 1627) +delete from mysql.ndb_replication where db="europenorth" and table_name="netherlands" and server_id=1; +Unique match with wild serverid (B) +create table europenorth.netherlands (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.netherlands' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$B(), unknown conflict resolution function at 'NDB$B()' +Error 1005 Can't create table 'europenorth.netherlands' (errno: 1627) +delete from mysql.ndb_replication where db="europenorth" and table_name="netherlands" and server_id=0; +Ambiguous wild table name +create table europenorth.netherlands (a int primary key) engine=ndb; +Warnings: +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +show warnings; +Level Code Message +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +drop table europenorth.netherlands; +delete from mysql.ndb_replication where db="europenorth" and table_name="%lands" and server_id=1; +Wild table name (D) +create table europenorth.netherlands (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.netherlands' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$D(), unknown conflict resolution function at 'NDB$D()' +Error 1005 Can't create table 'europenorth.netherlands' (errno: 1627) +delete from mysql.ndb_replication where db="europenorth" and table_name="nether%s" and server_id=1; +Ambiguous wild server id and table name +create table europenorth.netherlands (a int primary key) engine=ndb; +Warnings: +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +show warnings; +Level Code Message +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +drop table europenorth.netherlands; +delete from mysql.ndb_replication where db="europenorth" and table_name="nether%s" and server_id=0; +Wild server id and table name (E) +create table europenorth.netherlands (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.netherlands' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$E(), unknown conflict resolution function at 'NDB$E()' +Error 1005 Can't create table 'europenorth.netherlands' (errno: 1627) +delete from mysql.ndb_replication where db="europenorth" and table_name="%lands" and server_id=0; +Amiguous wild db +create table europenorth.netherlands (a int primary key) engine=ndb; +Warnings: +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +show warnings; +Level Code Message +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +drop table europenorth.netherlands; +delete from mysql.ndb_replication where db="Europe%" and table_name="netherlands" and server_id=1; +Wild db (H) +create table europenorth.netherlands (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.netherlands' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$H(), unknown conflict resolution function at 'NDB$H()' +Error 1005 Can't create table 'europenorth.netherlands' (errno: 1627) +delete from mysql.ndb_replication where db="%North" and table_name="netherlands" and server_id=1; +Ambiguous wild db + server_id +create table europenorth.netherlands (a int primary key) engine=ndb; +Warnings: +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +show warnings; +Level Code Message +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +drop table europenorth.netherlands; +delete from mysql.ndb_replication where db="Europe%" and table_name="netherlands" and server_id=0; +Wild db + server id (J) +create table europenorth.netherlands (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.netherlands' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$J(), unknown conflict resolution function at 'NDB$J()' +Error 1005 Can't create table 'europenorth.netherlands' (errno: 1627) +delete from mysql.ndb_replication where db="%North" and table_name="netherlands" and server_id=0; +Ambiguous wild db + table_name +create table europenorth.netherlands (a int primary key) engine=ndb; +Warnings: +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +show warnings; +Level Code Message +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +drop table europenorth.netherlands; +delete from mysql.ndb_replication where db="Europe%" and table_name="%lands" and server_id=1; +Wild db + table_name (L) +create table europenorth.netherlands (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.netherlands' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$L(), unknown conflict resolution function at 'NDB$L()' +Error 1005 Can't create table 'europenorth.netherlands' (errno: 1627) +delete from mysql.ndb_replication where db="%North" and table_name="nether%s" and server_id=1; +Ambiguous all wild +create table europenorth.netherlands (a int primary key) engine=ndb; +Warnings: +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +show warnings; +Level Code Message +Warning 1626 Bad schema for mysql.ndb_replication table. Message: Ambiguous matches in mysql.ndb_replication for europenorth.nethe +drop table europenorth.netherlands; +delete from mysql.ndb_replication where db="Europe%" and table_name="%lands" and server_id=0; +All wild (N) +create table europenorth.netherlands (a int primary key) engine=ndb; +ERROR HY000: Can't create table 'europenorth.netherlands' (errno: 1627) +show warnings; +Level Code Message +Error 1627 Error in parsing conflict function. Message: NDB$N(), unknown conflict resolution function at 'NDB$N()' +Error 1005 Can't create table 'europenorth.netherlands' (errno: 1627) +delete from mysql.ndb_replication; +drop database europenorth; +drop database europesouth; +drop database usnorth; +drop database ussouth; === modified file 'mysql-test/suite/ndb_rpl/t/ndb_rpl_rep_error.test' --- a/mysql-test/suite/ndb_rpl/t/ndb_rpl_rep_error.test 2012-01-17 13:51:35 +0000 +++ b/mysql-test/suite/ndb_rpl/t/ndb_rpl_rep_error.test 2012-01-25 17:13:13 +0000 @@ -6,8 +6,25 @@ --source include/have_binlog_format_mixed_or_row.inc --source suite/ndb_rpl/ndb_master-slave.inc +# Need suppressions on all servers where warnings/errors can be seen. +--disable_query_log +--connection server1 +call mtr.add_suppression("NDB: .*Bad schema for mysql.ndb_replication table.*"); +call mtr.add_suppression("NDB Slave: .* unknown conflict resolution function .*"); +call mtr.add_suppression("NDB Slave: .* has wrong datatype.*"); +call mtr.add_suppression("NDB Slave: .* missing function argument .*"); +call mtr.add_suppression("NDB Slave: .* missing \')\' .*"); +--connection server2 +call mtr.add_suppression("NDB: .*Bad schema for mysql.ndb_replication table.*"); +call mtr.add_suppression("NDB Slave: .* unknown conflict resolution function .*"); +call mtr.add_suppression("NDB Slave: .* has wrong datatype.*"); +call mtr.add_suppression("NDB Slave: .* missing function argument .*"); +call mtr.add_suppression("NDB Slave: .* missing \')\' .*"); +--connection default +--enable_query_log + # -# wrong schema for the table +--echo Wrong schema for the table, too few pks # --disable_warnings --disable_query_log @@ -28,37 +45,129 @@ CREATE TABLE mysql.ndb_replication create table t1 (a int key, X int) engine ndb; drop table t1; + # -# correct schema for the table -# but other errors +--echo Wrong schema for the table, incorrect pk # --disable_warnings --disable_query_log -drop table mysql.ndb_replication; +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,binlog_type)) + ENGINE=NDB PARTITION BY KEY(db,table_name); +--enable_warnings +--enable_query_log + +# gives warning when trying to create table as logging +# may not be as intended +create table t1 (a int key, X int) engine ndb; +drop table t1; + +# +--echo Wrong schema for the table, binlog_type is signed +# + +--disable_warnings +--disable_query_log +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, + 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 -# Need suppressions on all servers where warnings/errors can be seen. +# gives warning when trying to create table as logging +# may not be as intended +create table t1 (a int key, X int) engine ndb; +drop table t1; + +# +--echo Wrong schema for the table, conflict_fn is too long +# +--disable_warnings --disable_query_log ---connection server1 -call mtr.add_suppression("NDB Slave: .* unknown conflict resolution function .*"); -call mtr.add_suppression("NDB Slave: .* has wrong datatype.*"); -call mtr.add_suppression("NDB Slave: .* missing function argument .*"); -call mtr.add_suppression("NDB Slave: .* missing \')\' .*"); ---connection server2 -call mtr.add_suppression("NDB Slave: .* unknown conflict resolution function .*"); -call mtr.add_suppression("NDB Slave: .* has wrong datatype.*"); -call mtr.add_suppression("NDB Slave: .* missing function argument .*"); -call mtr.add_suppression("NDB Slave: .* missing \')\' .*"); ---connection default +drop table 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(257), + PRIMARY KEY USING HASH (db,table_name,server_id)) + ENGINE=NDB PARTITION BY KEY(db,table_name); +--enable_warnings +--enable_query_log + +# gives warning when trying to create table as logging +# may not be as intended +create table t1 (a int key, X int) engine ndb; +drop table t1; + +# +--echo Correct schema for the table but no conflict fn +# +--disable_warnings +--disable_query_log +drop table mysql.ndb_replication; +CREATE TABLE mysql.ndb_replication + (db VARBINARY(63), + table_name VARBINARY(63), + server_id INT UNSIGNED, + binlog_type INT UNSIGNED, + PRIMARY KEY USING HASH (db,table_name,server_id)) + ENGINE=NDB PARTITION BY KEY(db,table_name); +--enable_warnings +--enable_query_log + +insert into mysql.ndb_replication values ("test", "t1", 0, 7); +create table test.t1 (a int primary key) engine=ndb; +show warnings; +drop table test.t1; + +--let server_num=1.1 +--let $pattern=%NDB Binlog: logging% +--let $limit=1 +--source suite/ndb_rpl/t/show_mysqld_warnings.inc + +delete from mysql.ndb_replication; + +--echo Check that NULL uses server defaults +show variables like 'ndb_log_update_as_write'; +show variables like 'ndb_log_updated_only'; +insert into mysql.ndb_replication values ("test", "t1", 0, NULL); + +create table test.t1 (a int primary key) engine=ndb; +show warnings; +drop table test.t1; + +--source suite/ndb_rpl/t/show_mysqld_warnings.inc + + +# +--echo Correct schema for the table but other errors +# +--disable_warnings +--disable_query_log +drop table 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 # Non existant conflict_fn @@ -99,6 +208,246 @@ create table t1 (a int key, X int) engin show warnings; delete from mysql.ndb_replication; +show variables like 'server_id'; + +create database europenorth; +create database europesouth; +create database usnorth; +create database ussouth; + +--echo Basic wildcard tests +--echo Note that we put in bad conflict fn names so that the warnings generated +--echo when the table create fails give an indication of which ndb_replication +--echo table row was chosen. +--echo +--echo Wild serverid +insert into mysql.ndb_replication values ("europenorth", "france", 1, NULL, "NDB$A()"); +insert into mysql.ndb_replication values ("europenorth", "france", 0, NULL, "NDB$B()"); + +--echo Should match specific entry (1) with algorithm A. +--error 1005 +create table europenorth.france (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication where server_id=1; + +--echo Should match generic entry (0) with algorthin B. +--error 1005 +create table europenorth.france (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication; + +--echo Wild table_name +insert into mysql.ndb_replication values ("europenorth", "fr_nce", 1, NULL, "NDB$A()"); +insert into mysql.ndb_replication values ("europenorth", "%any", 1, NULL, "NDB$B()"); + +--echo Should match specific entry (fr_nce) with algorithm A. +--error 1005 +create table europenorth.france (a int primary key) engine=ndb; +show warnings; + +--echo Should match specific entry (%any) with algorithm B. +--error 1005 +create table europenorth.germany (a int primary key) engine=ndb; +show warnings; + +--echo Should match specific entry (%any) with algorithm B. +--error 1005 +create table europenorth.romany (a int primary key) engine=ndb; +show warnings; + +--echo No match, should be fine +create table europenorth.uk (a int primary key) engine=ndb; +show warnings; +drop table europenorth.uk; + +delete from mysql.ndb_replication; + +--echo Wild db +insert into mysql.ndb_replication values ("%north", "countries", 1, NULL, "NDB$A()"); +insert into mysql.ndb_replication values ("%south", "countries", 1, NULL, "NDB$B()"); + +--echo Should match north with A +--error 1005 +create table europenorth.countries (a int primary key) engine=ndb; +show warnings; + +--echo Should match north with A +--error 1005 +create table usnorth.countries (a int primary key) engine=ndb; +show warnings; + +--echo Should match south with B +--error 1005 +create table europesouth.countries (a int primary key) engine=ndb; +show warnings; + +--echo Should match south with B +--error 1005 +create table ussouth.countries (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication; + +--echo Now test wildcard matching precedence +--echo Wildcards match in the following precedence (highest->lowest) +--echo Exact match +--echo Wild serverid +--echo Wild table_name +--echo Wild serverid + wild table_name +--echo Wild db +--echo Wild db + wild serverid +--echo Wild db + wild table_name +--echo All wild +--echo +--echo The 'wild serverid' is 0 +--echo +--echo Multiple matches at the same precedence are ambiguous and result +--echo in an error. +--echo + +--echo Start with full set of potential matches, and chip away +# Put in duplicate matches at every precedence +# Delete rows to get one then no matches at each precedence. + +# Unique +insert into mysql.ndb_replication values ("europenorth", "netherlands", 1, NULL, "NDB$A()"); + +# Wild serverid +insert into mysql.ndb_replication values ("europenorth", "netherlands", 0, NULL, "NDB$B()"); + +# Wild table_name (two) +insert into mysql.ndb_replication values ("europenorth", "%lands", 1, NULL, "NDB$C()"); +insert into mysql.ndb_replication values ("europenorth", "nether%s", 1, NULL, "NDB$D()"); + +# Wild server_id and table_name +insert into mysql.ndb_replication values ("europenorth", "%lands", 0, NULL, "NDB$E()"); +insert into mysql.ndb_replication values ("europenorth", "nether%s", 0, NULL, "NDB$F()"); + +# Wild db +insert into mysql.ndb_replication values ("Europe%", "netherlands", 1, NULL, "NDB$G()"); +insert into mysql.ndb_replication values ("%North", "netherlands", 1, NULL, "NDB$H()"); + +# Wild db + Wild server_id + +insert into mysql.ndb_replication values ("Europe%", "netherlands", 0, NULL, "NDB$I()"); +insert into mysql.ndb_replication values ("%North", "netherlands", 0, NULL, "NDB$J()"); + +# Wild db + Wild table_name + +insert into mysql.ndb_replication values ("Europe%", "%lands", 1, NULL, "NDB$K()"); +insert into mysql.ndb_replication values ("%North", "nether%s", 1, NULL, "NDB$L()"); + +# All wild + +insert into mysql.ndb_replication values ("Europe%", "%lands", 0, NULL, "NDB$M()"); +insert into mysql.ndb_replication values ("%North", "nether%s", 0, NULL, "NDB$N()"); + + +--echo Unique match (A) +--error 1005 +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication where db="europenorth" and table_name="netherlands" and server_id=1; + +--echo Unique match with wild serverid (B) +--error 1005 +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication where db="europenorth" and table_name="netherlands" and server_id=0; + +--echo Ambiguous wild table name +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; +drop table europenorth.netherlands; + +delete from mysql.ndb_replication where db="europenorth" and table_name="%lands" and server_id=1; + +--echo Wild table name (D) +--error 1005 +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication where db="europenorth" and table_name="nether%s" and server_id=1; + +--echo Ambiguous wild server id and table name +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; +drop table europenorth.netherlands; + +delete from mysql.ndb_replication where db="europenorth" and table_name="nether%s" and server_id=0; + +--echo Wild server id and table name (E) +--error 1005 +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication where db="europenorth" and table_name="%lands" and server_id=0; + +--echo Amiguous wild db +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; +drop table europenorth.netherlands; + +delete from mysql.ndb_replication where db="Europe%" and table_name="netherlands" and server_id=1; + +--echo Wild db (H) +--error 1005 +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication where db="%North" and table_name="netherlands" and server_id=1; + +--echo Ambiguous wild db + server_id +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; +drop table europenorth.netherlands; + +delete from mysql.ndb_replication where db="Europe%" and table_name="netherlands" and server_id=0; + +--echo Wild db + server id (J) +--error 1005 +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication where db="%North" and table_name="netherlands" and server_id=0; + +--echo Ambiguous wild db + table_name +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; +drop table europenorth.netherlands; + +delete from mysql.ndb_replication where db="Europe%" and table_name="%lands" and server_id=1; + +--echo Wild db + table_name (L) +--error 1005 +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication where db="%North" and table_name="nether%s" and server_id=1; + +--echo Ambiguous all wild +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; +drop table europenorth.netherlands; + +delete from mysql.ndb_replication where db="Europe%" and table_name="%lands" and server_id=0; + +--echo All wild (N) +--error 1005 +create table europenorth.netherlands (a int primary key) engine=ndb; +show warnings; + +delete from mysql.ndb_replication; + +drop database europenorth; +drop database europesouth; +drop database usnorth; +drop database ussouth; + --disable_query_log --sync_slave_with_master stop slave; === modified file 'mysql-test/suite/ndb_rpl/t/show_mysqld_warnings.inc' --- a/mysql-test/suite/ndb_rpl/t/show_mysqld_warnings.inc 2012-01-17 15:41:38 +0000 +++ b/mysql-test/suite/ndb_rpl/t/show_mysqld_warnings.inc 2012-01-25 17:13:13 +0000 @@ -2,9 +2,14 @@ --echo MySQLD error output for server $server_num matching pattern $pattern create table errlog (a int auto_increment primary key, txt text) engine=myisam; ---eval load data local infile "$MYSQLTEST_VARDIR/log/mysqld.$server_num.err" into table errlog columns terminated by '\n' (txt); +# Avoid win path separators being interpreted as escapes +# for next char by having no escape char +--eval load data local infile "$MYSQLTEST_VARDIR/log/mysqld.$server_num.err" into table errlog columns terminated by '\n' escaped by '' (txt); ---eval select replace( lower( right(txt, length(txt) - locate('[',txt) + 1)), '\r', '') as relevant from errlog where txt like '$pattern' order by a desc limit $limit; +--eval delete from errlog where txt not like '$pattern'; +# Trim time, win CRs and fix win path separators (or any other backslashes) +update errlog set txt= replace(replace( lower( right(txt, length(txt) - locate('[',txt) + 1)), '\r', ''), '\\', '/'); +--eval select txt as relevant from errlog order by a desc limit $limit drop table errlog; --enable_query_log === modified file 'sql/Makefile.am' --- a/sql/Makefile.am 2011-11-10 09:01:54 +0000 +++ b/sql/Makefile.am 2012-01-25 17:13:13 +0000 @@ -66,6 +66,8 @@ noinst_HEADERS = item.h item_func.h item ndb_conflict_trans.h \ ndb_component.h \ ndb_util_thread.h \ + ndb_table_guard.h \ + ndb_repl_tab.h \ ha_partition.h rpl_constants.h \ debug_sync.h \ opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \ @@ -144,7 +146,8 @@ libndb_la_SOURCES= ha_ndbcluster.cc \ ha_ndbinfo.cc \ ndb_mi.cc \ ndb_conflict_trans.cc \ - ndb_component.cc + ndb_component.cc \ + ndb_repl_tab.cc gen_lex_hash_SOURCES = gen_lex_hash.cc gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@ === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc 2012-01-17 13:51:35 +0000 +++ b/sql/ha_ndbcluster.cc 2012-01-25 17:13:13 +0000 @@ -48,6 +48,7 @@ #include "ndb_conflict_trans.h" #include "ndb_component.h" #include "ndb_util_thread.h" +#include "ndb_table_guard.h" #ifdef ndb_dynamite #undef assert === modified file 'sql/ha_ndbcluster_binlog.cc' --- a/sql/ha_ndbcluster_binlog.cc 2012-01-17 13:52:58 +0000 +++ b/sql/ha_ndbcluster_binlog.cc 2012-01-25 17:13:13 +0000 @@ -33,6 +33,18 @@ #include #include #include +#include "ndb_table_guard.h" + +/* + defines for cluster replication table names +*/ +#include "ha_ndbcluster_tables.h" +#define NDB_APPLY_TABLE_FILE "./" NDB_REP_DB "/" NDB_APPLY_TABLE +#define NDB_SCHEMA_TABLE_FILE "./" NDB_REP_DB "/" NDB_SCHEMA_TABLE +static char repdb[]= NDB_REP_DB; +static char reptable[]= NDB_REP_TABLE; + +#include "ndb_repl_tab.h" #ifdef ndb_dynamite #undef assert @@ -55,15 +67,6 @@ bool ndb_log_empty_epochs(void); void ndb_index_stat_restart(); /* - defines for cluster replication table names -*/ -#include "ha_ndbcluster_tables.h" -#define NDB_APPLY_TABLE_FILE "./" NDB_REP_DB "/" NDB_APPLY_TABLE -#define NDB_SCHEMA_TABLE_FILE "./" NDB_REP_DB "/" NDB_SCHEMA_TABLE -static char repdb[]= NDB_REP_DB; -static char reptable[]= NDB_REP_TABLE; - -/* Timeout for syncing schema events between mysql servers, and between mysql server and the binlog */ @@ -4641,288 +4644,6 @@ setup_conflict_fn(THD *thd, NDB_SHARE *s 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"; -static const char *nrt_table_name= "table_name"; -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_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_replication_table"); - NdbError ndberror; - int error= 0; - const char *error_str= ""; - - ndb->setDatabaseName(ndb_rep_db); - NDBDICT *dict= ndb->getDictionary(); - Ndb_table_guard ndbtab_g(dict, ndb_replication_table); - const NDBTAB *reptab= ndbtab_g.get_table(); - if (reptab == NULL && - (dict->getNdbError().classification == NdbError::SchemaError || - dict->getNdbError().code == 4009)) - { - DBUG_PRINT("info", ("No %s.%s table", ndb_rep_db, ndb_replication_table)); - *binlog_flags= NBT_DEFAULT; - *conflict_fn_spec= NULL; - DBUG_RETURN(0); - } - const NDBCOL - *col_db, *col_table_name, *col_server_id, *col_binlog_type, *col_conflict_fn; - char tmp_buf[FN_REFLEN]; - uint retries= 100; - int retry_sleep= 30; /* 30 milliseconds, transaction */ - if (reptab == NULL) - { - ndberror= dict->getNdbError(); - goto err; - } - if (reptab->getNoOfPrimaryKeys() != 3) - { - error= -2; - error_str= "Wrong number of primary key parts, expected 3"; - goto err; - } - error= -1; - col_db= reptab->getColumn(error_str= nrt_db); - if (col_db == NULL || - !col_db->getPrimaryKey() || - col_db->getType() != NDBCOL::Varbinary) - goto err; - col_table_name= reptab->getColumn(error_str= nrt_table_name); - if (col_table_name == NULL || - !col_table_name->getPrimaryKey() || - col_table_name->getType() != NDBCOL::Varbinary) - goto err; - col_server_id= reptab->getColumn(error_str= nrt_server_id); - if (col_server_id == NULL || - !col_server_id->getPrimaryKey() || - col_server_id->getType() != NDBCOL::Unsigned) - goto err; - col_binlog_type= reptab->getColumn(error_str= nrt_binlog_type); - if (col_binlog_type == NULL || - col_binlog_type->getPrimaryKey() || - col_binlog_type->getType() != NDBCOL::Unsigned) - goto err; - col_conflict_fn= reptab->getColumn(error_str= nrt_conflict_fn); - if (col_conflict_fn == NULL) - { - col_conflict_fn= NULL; - } - else if (col_conflict_fn->getPrimaryKey() || - col_conflict_fn->getType() != NDBCOL::Varbinary) - goto err; - - error= 0; - for (;;) - { - NdbTransaction *trans= ndb->startTransaction(); - if (trans == NULL) - { - ndberror= ndb->getNdbError(); - break; - } - NdbRecAttr *col_binlog_type_rec_attr[2]; - NdbRecAttr *col_conflict_fn_rec_attr[2]= {NULL, NULL}; - uint32 ndb_binlog_type[2]; - const uint sz= 256; - char ndb_conflict_fn_buf[2*sz]; - 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; - DBUG_PRINT("info", ("reading[%u]: %s,%s,%u", i, db, table_name, id)); - if ((_op= trans->getNdbOperation(reptab)) == NULL) abort(); - if (_op->readTuple(NdbOperation::LM_CommittedRead)) abort(); - ndb_pack_varchar(col_db, tmp_buf, db, (int)strlen(db)); - if (_op->equal(col_db->getColumnNo(), tmp_buf)) abort(); - ndb_pack_varchar(col_table_name, tmp_buf, table_name, (int)strlen(table_name)); - if (_op->equal(col_table_name->getColumnNo(), tmp_buf)) abort(); - if (_op->equal(col_server_id->getColumnNo(), id)) abort(); - if ((col_binlog_type_rec_attr[i]= - _op->getValue(col_binlog_type, (char *)&(ndb_binlog_type[i]))) == 0) abort(); - /* optional columns */ - if (col_conflict_fn) - { - if ((col_conflict_fn_rec_attr[i]= - _op->getValue(col_conflict_fn, ndb_conflict_fn[i])) == 0) abort(); - } - id= server_id; - op[i]= _op; - } - - if (trans->execute(NdbTransaction::Commit, - NdbOperation::AO_IgnoreError)) - { - if (ndb->getNdbError().status == NdbError::TemporaryError) - { - if (retries--) - { - if (trans) - ndb->closeTransaction(trans); - do_retry_sleep(retry_sleep); - continue; - } - } - ndberror= trans->getNdbError(); - ndb->closeTransaction(trans); - break; - } - for (i= 0; i < 2; i++) - { - if (op[i]->getNdbError().code) - { - if (op[i]->getNdbError().classification == NdbError::NoDataFound) - { - col_binlog_type_rec_attr[i]= NULL; - col_conflict_fn_rec_attr[i]= NULL; - DBUG_PRINT("info", ("not found row[%u]", i)); - continue; - } - ndberror= op[i]->getNdbError(); - break; - } - DBUG_PRINT("info", ("found row[%u]", i)); - } - 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 (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()) - { - /* No conflict function */ - *conflict_fn_spec = NULL; - } - else - { - 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) - { - 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); - } - -err: - DBUG_PRINT("info", ("error %d, error_str %s, ndberror.code %u", - error, error_str, ndberror.code)); - if (error < 0) - { - char msg[FN_REFLEN]; - switch (error) - { - case -1: - my_snprintf(msg, sizeof(msg), - "Missing or wrong type for column '%s'", error_str); - break; - case -2: - my_snprintf(msg, sizeof(msg), "%s", error_str); - break; - default: - abort(); - } - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_NDB_REPLICATION_SCHEMA_ERROR, - ER(ER_NDB_REPLICATION_SCHEMA_ERROR), - msg); - } - else - { - char msg[FN_REFLEN]; - my_snprintf(tmp_buf, sizeof(tmp_buf), "ndberror %u", ndberror.code); - my_snprintf(msg, sizeof(msg), "Unable to retrieve %s.%s, logging and " - "conflict resolution may not function as intended (%s)", - ndb_rep_db, ndb_replication_table, tmp_buf); - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_ILLEGAL_HA_CREATE_OPTION, - ER(ER_ILLEGAL_HA_CREATE_OPTION), - ndbcluster_hton_name, msg); - } - *binlog_flags= NBT_DEFAULT; - *conflict_fn_spec= NULL; - - if (ndberror.code && opt_ndb_extra_logging) - print_warning_list("NDB", thd_warn_list(thd)); - DBUG_RETURN(ndberror.code); -} - /* ndbcluster_get_binlog_replication_info @@ -4967,48 +4688,54 @@ ndbcluster_get_binlog_replication_info(T } } - 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) + Ndb_rep_tab_reader rep_tab_reader; + + int rc = rep_tab_reader.lookup(ndb, + db, + table_name, + server_id); + + const char* msg = rep_tab_reader.get_warning_message(); + if (msg != NULL) { - DBUG_RETURN(ER_NDB_REPLICATION_SCHEMA_ERROR); + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NDB_REPLICATION_SCHEMA_ERROR, + ER(ER_NDB_REPLICATION_SCHEMA_ERROR), + msg); + sql_print_warning("NDB Binlog: %s", + msg); } + if (rc != 0) + DBUG_RETURN(ER_NDB_REPLICATION_SCHEMA_ERROR); + + *binlog_flags= rep_tab_reader.get_binlog_flags(); + const char* conflict_fn_spec= rep_tab_reader.get_conflict_fn_spec(); + if (conflict_fn_spec != NULL) { - char tmp_buf[FN_REFLEN]; - + char msgbuf[ FN_REFLEN ]; if (parse_conflict_fn_spec(conflict_fn_spec, conflict_fn, args, num_args, - tmp_buf, - sizeof(tmp_buf)) != 0) + msgbuf, + sizeof(msgbuf)) != 0) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_CONFLICT_FN_PARSE_ERROR, ER(ER_CONFLICT_FN_PARSE_ERROR), - tmp_buf); + msgbuf); /* - Log as well, useful for contexts where the thd's stack of - warnings are ignored - */ + Log as well, useful for contexts where the thd's stack of + warnings are ignored + */ if (opt_ndb_extra_logging) { sql_print_warning("NDB Slave: Table %s.%s : Parse error on conflict fn : %s", db, table_name, - tmp_buf); + msgbuf); } DBUG_RETURN(ER_CONFLICT_FN_PARSE_ERROR); === modified file 'sql/ha_ndbcluster_binlog.h' --- a/sql/ha_ndbcluster_binlog.h 2012-01-17 13:51:35 +0000 +++ b/sql/ha_ndbcluster_binlog.h 2012-01-25 17:13:13 +0000 @@ -113,67 +113,6 @@ private: pthread_mutex_t &m_mutex; }; -class Ndb_table_guard -{ -public: - Ndb_table_guard(NDBDICT *dict) - : m_dict(dict), m_ndbtab(NULL), m_invalidate(0) - {} - Ndb_table_guard(NDBDICT *dict, const char *tabname) - : m_dict(dict), m_ndbtab(NULL), m_invalidate(0) - { - DBUG_ENTER("Ndb_table_guard"); - init(tabname); - DBUG_VOID_RETURN; - } - ~Ndb_table_guard() - { - DBUG_ENTER("~Ndb_table_guard"); - reinit(); - DBUG_VOID_RETURN; - } - void init(const char *tabname) - { - DBUG_ENTER("Ndb_table_guard::init"); - /* must call reinit() if already initialized */ - DBUG_ASSERT(m_ndbtab == NULL); - m_ndbtab= m_dict->getTableGlobal(tabname); - m_invalidate= 0; - DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab)); - DBUG_VOID_RETURN; - } - void reinit(const char *tabname= 0) - { - DBUG_ENTER("Ndb_table_guard::reinit"); - if (m_ndbtab) - { - DBUG_PRINT("info", ("m_ndbtab: %p m_invalidate: %d", - m_ndbtab, m_invalidate)); - m_dict->removeTableGlobal(*m_ndbtab, m_invalidate); - m_ndbtab= NULL; - m_invalidate= 0; - } - if (tabname) - init(tabname); - DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab)); - DBUG_VOID_RETURN; - } - const NDBTAB *get_table() { return m_ndbtab; } - void invalidate() { m_invalidate= 1; } - const NDBTAB *release() - { - DBUG_ENTER("Ndb_table_guard::release"); - const NDBTAB *tmp= m_ndbtab; - DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab)); - m_ndbtab = 0; - DBUG_RETURN(tmp); - } -private: - NDBDICT *m_dict; - const NDBTAB *m_ndbtab; - int m_invalidate; -}; - class Thd_proc_info_guard { public: === added file 'sql/ndb_repl_tab.cc' --- a/sql/ndb_repl_tab.cc 1970-01-01 00:00:00 +0000 +++ b/sql/ndb_repl_tab.cc 2012-01-25 17:13:13 +0000 @@ -0,0 +1,559 @@ +/* + Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "ha_ndbcluster_tables.h" +#include "ndb_repl_tab.h" + +#ifdef HAVE_NDB_BINLOG +#include "mysql_priv.h" +#include "ha_ndbcluster_connection.h" /* do_retry_sleep() */ +#include "ndb_table_guard.h" + +Ndb_rep_tab_key::Ndb_rep_tab_key(const char* _db, + const char* _table_name, + uint _server_id) +{ + uint db_len= (uint) strlen(_db); + uint tabname_len = (uint) strlen(_table_name); + assert(DB_MAXLEN < 256); /* Fits in Varchar */ + assert(db_len <= DB_MAXLEN); + assert(tabname_len <= TABNAME_MAXLEN); + + memcpy(&db[1], _db, db_len); + db[ 0 ]= db_len; + + memcpy(&table_name[1], _table_name, tabname_len); + table_name[ 0 ]= tabname_len; + + server_id= _server_id; + + null_terminate_strings(); +} + +void Ndb_rep_tab_key::null_terminate_strings() +{ + assert((uint) db[0] <= DB_MAXLEN); + assert((uint) table_name[0] <= TABNAME_MAXLEN); + db[ db[0] + 1] = '\0'; + table_name[ table_name[0] + 1] = '\0'; +} + +int +Ndb_rep_tab_key::attempt_match(const char* keyptr, + const uint keylen, + const char* candidateptr, + const uint candidatelen, + const int exactmatchvalue) +{ + if (my_strnncoll(system_charset_info, + (const uchar*) keyptr, + keylen, + (const uchar*) candidateptr, + candidatelen) == 0) + { + /* Exact match */ + return exactmatchvalue; + } + else if (my_wildcmp(system_charset_info, + keyptr, + keyptr + keylen, + candidateptr, + candidateptr + candidatelen, + '\\', wild_one, wild_many) == 0) + { + /* Wild match */ + return 0; + } + + /* No match */ + return -1; +}; + +int +Ndb_rep_tab_key::get_match_quality(const Ndb_rep_tab_key* key, + const Ndb_rep_tab_key* candidate_row) +{ + /* 0= No match + 1= Loosest match + 8= Best match + + Actual mapping is : + db table serverid Quality + W W W 1 + W W = 2 + W = W 3 + W = = 4 + = W W 5 + = W = 6 + = = W 7 + = = = 8 + */ + int quality = MIN_MATCH_VAL; + + int rc; + if ((rc = attempt_match(&key->db[1], + key->db[0], + &candidate_row->db[1], + candidate_row->db[0], + EXACT_MATCH_DB)) == -1) + { + /* No match, drop out now */ + return 0; + } + quality+= rc; + + if ((rc = attempt_match(&key->table_name[1], + key->table_name[0], + &candidate_row->table_name[1], + candidate_row->table_name[0], + EXACT_MATCH_TABLE_NAME)) == -1) + { + /* No match, drop out now */ + return 0; + } + quality+= rc; + + if (candidate_row->server_id == key->server_id) + { + /* Exact match */ + quality += EXACT_MATCH_SERVER_ID; + } + else if (candidate_row->server_id != 0) + { + /* No match */ + return 0; + } + + return quality; +}; + +Ndb_rep_tab_row::Ndb_rep_tab_row() + : binlog_type(0), cfs_is_null(true) +{ + memset(conflict_fn_spec, 0, sizeof(conflict_fn_spec)); +} +const char* Ndb_rep_tab_reader::ndb_rep_db= NDB_REP_DB; +const char* Ndb_rep_tab_reader::ndb_replication_table= NDB_REPLICATION_TABLE; +const char* Ndb_rep_tab_reader::nrt_db= "db"; +const char* Ndb_rep_tab_reader::nrt_table_name= "table_name"; +const char* Ndb_rep_tab_reader::nrt_server_id= "server_id"; +const char* Ndb_rep_tab_reader::nrt_binlog_type= "binlog_type"; +const char* Ndb_rep_tab_reader::nrt_conflict_fn= "conflict_fn"; + +Ndb_rep_tab_reader::Ndb_rep_tab_reader() + : binlog_flags(NBT_DEFAULT), + conflict_fn_spec(NULL), + warning_msg(NULL) +{ +} + +int Ndb_rep_tab_reader::check_schema(const NdbDictionary::Table* reptab, + NdbDictionary::Dictionary* dict, + const char** error_str) +{ + DBUG_ENTER("check_schema"); + *error_str= NULL; + + const NdbDictionary::Column + *col_db, *col_table_name, *col_server_id, *col_binlog_type, *col_conflict_fn; + if (reptab->getNoOfPrimaryKeys() != 3) + { + *error_str= "Wrong number of primary key parts, expected 3"; + DBUG_RETURN(-2); + } + col_db= reptab->getColumn(*error_str= nrt_db); + if (col_db == NULL || + !col_db->getPrimaryKey() || + col_db->getType() != NdbDictionary::Column::Varbinary) + DBUG_RETURN(-1); + col_table_name= reptab->getColumn(*error_str= nrt_table_name); + if (col_table_name == NULL || + !col_table_name->getPrimaryKey() || + col_table_name->getType() != NdbDictionary::Column::Varbinary) + DBUG_RETURN(-1); + col_server_id= reptab->getColumn(*error_str= nrt_server_id); + if (col_server_id == NULL || + !col_server_id->getPrimaryKey() || + col_server_id->getType() != NdbDictionary::Column::Unsigned) + DBUG_RETURN(-1); + col_binlog_type= reptab->getColumn(*error_str= nrt_binlog_type); + if (col_binlog_type == NULL || + col_binlog_type->getPrimaryKey() || + col_binlog_type->getType() != NdbDictionary::Column::Unsigned) + DBUG_RETURN(-1); + col_conflict_fn= reptab->getColumn(*error_str= nrt_conflict_fn); + if (col_conflict_fn != NULL) + { + if ((col_conflict_fn->getPrimaryKey()) || + (col_conflict_fn->getType() != NdbDictionary::Column::Varbinary)) + DBUG_RETURN(-1); + } + + DBUG_RETURN(0); +} + +int +Ndb_rep_tab_reader::scan_candidates(Ndb* ndb, + const NdbDictionary::Table* reptab, + const char* db, + const char* table_name, + uint server_id, + Ndb_rep_tab_row& best_match) +{ + uint retries= 100; + int retry_sleep= 30; /* 30 milliseconds, transaction */ + int best_match_quality= 0; + NdbError ok; + NdbError ndberror; + + /* Loop to enable temporary error retries */ + while(true) + { + ndberror = ok; /* reset */ + NdbTransaction *trans= ndb->startTransaction(); + if (trans == NULL) + { + ndberror= ndb->getNdbError(); + + if (ndberror.status == NdbError::TemporaryError) + { + if (retries--) + { + do_retry_sleep(retry_sleep); + continue; + } + } + break; + } + NdbRecAttr* ra_binlog_type= NULL; + NdbRecAttr* ra_conflict_fn_spec= NULL; + Ndb_rep_tab_row row; + bool have_conflict_fn_col = (reptab->getColumn(nrt_conflict_fn) != NULL); + + /* Define scan op on ndb_replication */ + NdbScanOperation* scanOp = trans->getNdbScanOperation(reptab); + if (scanOp == NULL) { ndberror= trans->getNdbError(); break; } + + if ((scanOp->readTuples(NdbScanOperation::LM_CommittedRead) != 0) || + (scanOp->getValue(nrt_db, (char*) row.key.db) == NULL) || + (scanOp->getValue(nrt_table_name, (char*) row.key.table_name) == NULL) || + (scanOp->getValue(nrt_server_id, (char*) &row.key.server_id) == NULL) || + ((ra_binlog_type = scanOp->getValue(nrt_binlog_type, (char*) &row.binlog_type)) == NULL) || + (have_conflict_fn_col && + ((ra_conflict_fn_spec= + scanOp->getValue(nrt_conflict_fn, (char*) row.conflict_fn_spec)) == NULL))) + { + ndberror= scanOp->getNdbError(); + break; + } + + if (trans->execute(NdbTransaction::NoCommit, + NdbOperation::AO_IgnoreError)) + { + ndberror= trans->getNdbError(); + ndb->closeTransaction(trans); + + if (ndberror.status == NdbError::TemporaryError) + { + if (retries--) + { + do_retry_sleep(retry_sleep); + continue; + } + } + break; + } + + /* Scroll through results, looking for best match */ + DBUG_PRINT("info", ("Searching ndb_replication for %s.%s %u", + db, table_name, server_id)); + + bool ambiguous_match = false; + Ndb_rep_tab_key searchkey(db, table_name, server_id); + int scan_rc; + while ((scan_rc= scanOp->nextResult(true)) == 0) + { + if (ra_binlog_type->isNULL() == 1) + { + row.binlog_type= NBT_DEFAULT; + } + if (ra_conflict_fn_spec) + { + row.set_conflict_fn_spec_null(ra_conflict_fn_spec->isNULL() == 1); + } + + /* Compare row to searchkey to get quality of match */ + int match_quality= Ndb_rep_tab_key::get_match_quality(&searchkey, + &row.key); +#ifndef DBUG_OFF + { + row.null_terminate_strings(); + + DBUG_PRINT("info", ("Candidate : %s.%s %u : %u %s" + " Match quality : %u.", + row.key.get_db(), + row.key.get_table_name(), + row.key.server_id, + row.binlog_type, + row.get_conflict_fn_spec(), + match_quality)); + } +#endif + + if (match_quality > 0) + { + if (match_quality == best_match_quality) + { + ambiguous_match = true; + /* Ambiguous matches...*/ + my_snprintf(warning_msg_buffer, sizeof(warning_msg_buffer), + "Ambiguous matches in %s.%s for %s.%s (%u)." + "Candidates : %s.%s (%u), %s.%s (%u).", + ndb_rep_db, ndb_replication_table, + db, table_name, server_id, + &best_match.key.db[1], + &best_match.key.table_name[1], + best_match.key.server_id, + &row.key.db[1], + &row.key.table_name[1], + row.key.server_id); + DBUG_PRINT("info", ("%s", warning_msg_buffer)); + } + if (match_quality > best_match_quality) + { + /* New best match */ + best_match= row; + best_match_quality = match_quality; + ambiguous_match = false; + + if (best_match_quality == Ndb_rep_tab_key::EXACT_MATCH_QUALITY) + { + /* We're done */ + break; + } + } + } /* if (match_quality > 0) */ + } /* while ((scan_rc= scanOp->nextResult(true)) */ + + if (scan_rc < 0) + { + ndberror= scanOp->getNdbError(); + if (ndberror.status == NdbError::TemporaryError) + { + if (retries--) + { + ndb->closeTransaction(trans); + do_retry_sleep(retry_sleep); + continue; + } + } + } + + ndb->closeTransaction(trans); + + if (ambiguous_match) + { + warning_msg= warning_msg_buffer; + best_match_quality = -1; + } + + break; + } /* while(true) */ + + if (ndberror.code != 0) + { + my_snprintf(warning_msg_buffer, sizeof(warning_msg_buffer), + "Unable to retrieve %s.%s, logging and " + "conflict resolution may not function " + "as intended (ndberror %u)", + ndb_rep_db, ndb_replication_table, + ndberror.code); + warning_msg= warning_msg_buffer; + best_match_quality = -1; + } + + return best_match_quality; +} + +int +Ndb_rep_tab_reader::lookup(Ndb* ndb, + /* Keys */ + const char* db, + const char* table_name, + uint server_id) +{ + DBUG_ENTER("lookup"); + int error= 0; + NdbError ndberror; + const char *error_str= ""; + + /* Set results to defaults */ + binlog_flags= NBT_DEFAULT; + conflict_fn_spec= NULL; + warning_msg= NULL; + + ndb->setDatabaseName(ndb_rep_db); + NdbDictionary::Dictionary *dict= ndb->getDictionary(); + Ndb_table_guard ndbtab_g(dict, ndb_replication_table); + const NdbDictionary::Table *reptab= ndbtab_g.get_table(); + + do + { + if (reptab == NULL) + { + if (dict->getNdbError().classification == NdbError::SchemaError || + dict->getNdbError().code == 4009) + { + DBUG_PRINT("info", ("No %s.%s table", ndb_rep_db, ndb_replication_table)); + DBUG_RETURN(0); + } + else + { + error= 0; + ndberror= dict->getNdbError(); + break; + } + } + + if ((error= check_schema(reptab, + dict, + &error_str)) != 0) + { + DBUG_PRINT("info", ("check_schema failed : %u, error_str : %s", + error, error_str)); + break; + } + + + Ndb_rep_tab_row best_match_row; + + int best_match_quality = scan_candidates(ndb, + reptab, + db, + table_name, + server_id, + best_match_row); + + DBUG_PRINT("info", ("Best match at quality : %u", best_match_quality)); + + if (best_match_quality == -1) + { + /* Problem in matching, message already set */ + assert(warning_msg != NULL); + error= -3; + break; + } + if (best_match_quality == 0) + { + /* No match : Use defaults */ + } + else + { + /* Have a matching row, copy out values */ + /* Ensure VARCHARs are usable as strings */ + best_match_row.null_terminate_strings(); + + binlog_flags= (enum Ndb_binlog_type) best_match_row.binlog_type; + + if (best_match_row.cfs_is_null) + { + DBUG_PRINT("info", ("Conflict FN SPEC is Null")); + /* No conflict fn spec */ + conflict_fn_spec= NULL; + } + else + { + const char* conflict_fn = best_match_row.get_conflict_fn_spec(); + uint len= (uint) strlen(conflict_fn); + if ((len + 1) > sizeof(conflict_fn_buffer)) + { + error= -2; + error_str= "Conflict function specification too long."; + break; + } + memcpy(conflict_fn_buffer, conflict_fn, len); + conflict_fn_buffer[len] = '\0'; + conflict_fn_spec = conflict_fn_buffer; + } + } + } while(0); + + /* Error handling */ + if (error == 0) + { + if (ndberror.code != 0) + { + my_snprintf(warning_msg_buffer, sizeof(warning_msg_buffer), + "Unable to retrieve %s.%s, logging and " + "conflict resolution may not function " + "as intended (ndberror %u)", + ndb_rep_db, ndb_replication_table, + ndberror.code); + warning_msg= warning_msg_buffer; + error= -4; + } + } + else + { + switch (error) + { + case -1: + my_snprintf(warning_msg_buffer, sizeof(warning_msg_buffer), + "Missing or wrong type for column '%s'", error_str); + break; + case -2: + my_snprintf(warning_msg_buffer, sizeof(warning_msg_buffer), "%s", error_str); + break; + case -3: + /* Message already set */ + break; + default: + abort(); + } + warning_msg= warning_msg_buffer; + error= 0; /* No real error, just use defaults */ + } + + DBUG_PRINT("info", ("Rc : %d Retrieved Binlog flags : %u and function spec : %s", + error, binlog_flags, (conflict_fn_spec != NULL ?conflict_fn_spec: + "NULL"))); + + DBUG_RETURN(error); +}; + +Uint32 +Ndb_rep_tab_reader::get_binlog_flags() const +{ + return binlog_flags; +} + +const char* +Ndb_rep_tab_reader::get_conflict_fn_spec() const +{ + return conflict_fn_spec; +} + +const char* +Ndb_rep_tab_reader::get_warning_message() const +{ + return warning_msg; +} + + +/* #ifdef HAVE_NDB_BINLOG */ + +#endif === added file 'sql/ndb_repl_tab.h' --- a/sql/ndb_repl_tab.h 1970-01-01 00:00:00 +0000 +++ b/sql/ndb_repl_tab.h 2012-01-25 17:13:13 +0000 @@ -0,0 +1,254 @@ +/* + Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef NDB_REPL_TAB_H +#define NDB_REPL_TAB_H + +#include + +#ifdef HAVE_NDB_BINLOG +#include /* NAME_CHAR_LEN */ +#include + +/* + Ndb_rep_tab_key + + This class represents the key columns of the + mysql.ndb_replication system table + It is used when reading values from that table +*/ +class Ndb_rep_tab_key +{ +public: + static const uint DB_MAXLEN= NAME_CHAR_LEN - 1; + static const uint TABNAME_MAXLEN= NAME_CHAR_LEN - 1; + + /* Char arrays in varchar format with 1 length byte and + * trailing 0 + */ + char db[ DB_MAXLEN + 2 ]; + char table_name[ TABNAME_MAXLEN + 2 ]; + uint server_id; + + Ndb_rep_tab_key() + { + db[0] = 0; + table_name[0] = 0; + server_id = 0; + } + + /* Constructor from normal null terminated strings */ + Ndb_rep_tab_key(const char* _db, + const char* _table_name, + uint _server_id); + + /* Add null terminators to VARCHAR format string values */ + void null_terminate_strings(); + + const char* get_db() const + { + return &db[1]; + }; + + const char* get_table_name() const + { + return &table_name[1]; + }; + + static const int MIN_MATCH_VAL = 1; + static const int EXACT_MATCH_DB = 4; + static const int EXACT_MATCH_TABLE_NAME = 2; + static const int EXACT_MATCH_SERVER_ID = 1; + + static const int EXACT_MATCH_QUALITY = + MIN_MATCH_VAL + + EXACT_MATCH_DB + + EXACT_MATCH_TABLE_NAME + + EXACT_MATCH_SERVER_ID; + + /* + This static method attempts an exact, then a wild + match between the passed key (with optional wild + characters), and the passed candidate row + returns : + 1 : Exact match + 0 : Wild match + -1 : No match + */ + static int attempt_match(const char* keyptr, + const uint keylen, + const char* candidateptr, + const uint candidatelen, + const int exactmatchvalue); + + /* This static method compares a fixed key value with + * a possibly wildcard containing candidate_row. + * If there is no match, 0 is returned. + * >0 means there is a match, with larger numbers + * indicating a better match quality. + * An exact match returns EXACT_MATCH_QUALITY + */ + static int get_match_quality(const Ndb_rep_tab_key* key, + const Ndb_rep_tab_key* candidate_row); +}; + +/* + Ndb_rep_tab_row + + This class represents a row in the mysql.ndb_replication table +*/ +class Ndb_rep_tab_row +{ +public: + static const uint MAX_CONFLICT_FN_SPEC_LEN = 255; + static const uint CONFLICT_FN_SPEC_BUF_LEN = + MAX_CONFLICT_FN_SPEC_LEN + 1; /* Trailing '\0' */ + + Ndb_rep_tab_key key; + uint binlog_type; + bool cfs_is_null; + /* Buffer has space for leading length byte */ + char conflict_fn_spec[ CONFLICT_FN_SPEC_BUF_LEN + 1 ]; + + Ndb_rep_tab_row(); + + void null_terminate_strings() + { + key.null_terminate_strings(); + uint speclen= 0; + speclen = conflict_fn_spec[0]; + + assert(speclen <= MAX_CONFLICT_FN_SPEC_LEN); + conflict_fn_spec[1 + speclen] = '\0'; + } + + const char* get_conflict_fn_spec() + { + return &conflict_fn_spec[1]; + } + + void set_conflict_fn_spec_null(bool null) + { + if (null) + { + cfs_is_null = true; + conflict_fn_spec[0] = 0; + conflict_fn_spec[1] = 0; + } + else + { + cfs_is_null = false; + } + } +}; + +/** + Ndb_rep_tab_reader + + A helper class for accessing the mysql.ndb_replication + table +*/ +class Ndb_rep_tab_reader +{ +private: + static const char *ndb_rep_db; + static const char *ndb_replication_table; + static const char *nrt_db; + static const char *nrt_table_name; + static const char *nrt_server_id; + static const char *nrt_binlog_type; + static const char *nrt_conflict_fn; + + Uint32 binlog_flags; + char conflict_fn_buffer[ Ndb_rep_tab_row::CONFLICT_FN_SPEC_BUF_LEN ]; + char warning_msg_buffer[ FN_REFLEN ]; + + const char* conflict_fn_spec; + const char* warning_msg; + + /** + check_schema + + Checks that the schema of the mysql.ndb_replication table + is acceptable. + Returns + 0 if ok + -1 if a column has an error. Col name in error_str + -2 if there's a more general error. Error description in + error_str + */ + static + int check_schema(const NdbDictionary::Table* reptab, + NdbDictionary::Dictionary* dict, + const char** error_str); + + /** + scan_candidates + + Scans the ndb_replication table for rows matching the + passed db, table_name, server_id triple. + Returns the quality of the match made. + + -1 = Error in processing, see msg + 0 = No match, use defaults. + >0 = Use data in best_match + + if msg is set on return it contains a warning. + Warnings may be produces in non error scenarios + */ + int scan_candidates(Ndb* ndb, + const NdbDictionary::Table* reptab, + const char* db, + const char* table_name, + uint server_id, + Ndb_rep_tab_row& best_match); +public: + Ndb_rep_tab_reader(); + ~Ndb_rep_tab_reader() {}; + + /** + lookup + + lookup scans the mysql.ndb_replication table for + the best matching entry for the supplied db, + table_name, server_id triple. + A buffer for the conflict_fn spec, and for any + error or warning messages must be supplied. + The passed binlog_flags, conflict_fn_spec and + message may be updated as a result + + Returns : + 0 : Success. + <0 : Error. + */ + int lookup(Ndb* ndb, + /* Keys */ + const char* db, + const char* table_name, + uint server_id); + + /* Following only valid after a call to lookup() */ + Uint32 get_binlog_flags() const; + const char* get_conflict_fn_spec() const; + const char* get_warning_message() const; +}; + +/* #ifdef HAVE_NDB_BINLOG */ +#endif + +/* #ifdef NDB_REPL_TAB_H */ +#endif === added file 'sql/ndb_table_guard.h' --- a/sql/ndb_table_guard.h 1970-01-01 00:00:00 +0000 +++ b/sql/ndb_table_guard.h 2012-01-25 17:13:13 +0000 @@ -0,0 +1,85 @@ +/* + Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef NDB_TABLE_GUARD_H +#define NDB_TABLE_GUARD_H + +#include + +class Ndb_table_guard +{ +public: + Ndb_table_guard(NdbDictionary::Dictionary *dict) + : m_dict(dict), m_ndbtab(NULL), m_invalidate(0) + {} + Ndb_table_guard(NdbDictionary::Dictionary *dict, const char *tabname) + : m_dict(dict), m_ndbtab(NULL), m_invalidate(0) + { + DBUG_ENTER("Ndb_table_guard"); + init(tabname); + DBUG_VOID_RETURN; + } + ~Ndb_table_guard() + { + DBUG_ENTER("~Ndb_table_guard"); + reinit(); + DBUG_VOID_RETURN; + } + void init(const char *tabname) + { + DBUG_ENTER("Ndb_table_guard::init"); + /* must call reinit() if already initialized */ + DBUG_ASSERT(m_ndbtab == NULL); + m_ndbtab= m_dict->getTableGlobal(tabname); + m_invalidate= 0; + DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab)); + DBUG_VOID_RETURN; + } + void reinit(const char *tabname= 0) + { + DBUG_ENTER("Ndb_table_guard::reinit"); + if (m_ndbtab) + { + DBUG_PRINT("info", ("m_ndbtab: %p m_invalidate: %d", + m_ndbtab, m_invalidate)); + m_dict->removeTableGlobal(*m_ndbtab, m_invalidate); + m_ndbtab= NULL; + m_invalidate= 0; + } + if (tabname) + init(tabname); + DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab)); + DBUG_VOID_RETURN; + } + const NdbDictionary::Table *get_table() { return m_ndbtab; } + void invalidate() { m_invalidate= 1; } + const NdbDictionary::Table *release() + { + DBUG_ENTER("Ndb_table_guard::release"); + const NdbDictionary::Table *tmp= m_ndbtab; + DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab)); + m_ndbtab = 0; + DBUG_RETURN(tmp); + } +private: + NdbDictionary::Dictionary *m_dict; + const NdbDictionary::Table *m_ndbtab; + int m_invalidate; +}; + +/* NDB_TABLE_GUARD_H */ +#endif === modified file 'storage/ndb/CMakeLists.txt' --- a/storage/ndb/CMakeLists.txt 2011-11-10 08:16:52 +0000 +++ b/storage/ndb/CMakeLists.txt 2012-01-25 17:13:13 +0000 @@ -150,7 +150,8 @@ SET(NDBCLUSTER_SOURCES ../../sql/ha_ndbinfo.cc ../../sql/ndb_mi.cc ../../sql/ndb_conflict_trans.cc - ../../sql/ndb_component.cc) + ../../sql/ndb_component.cc + ../../sql/ndb_repl_tab.cc) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/ndb/include) IF(EXISTS ${CMAKE_SOURCE_DIR}/storage/mysql_storage_engine.cmake) No bundle (reason: useless for push emails).