#At file:///home/jonas/src/70-spj/ based on revid:jonas@stripped
3014 Jonas Oreland 2009-12-06 [merge]
ndb spj - merge 70-main
added:
mysql-test/suite/ndb/r/ndb_short_sigs.result
mysql-test/suite/ndb/t/ndb_short_sigs.cnf
mysql-test/suite/ndb/t/ndb_short_sigs.test
storage/ndb/src/common/util/require.c
modified:
mysql-test/suite/ndb/r/ndb_restore.result
mysql-test/suite/ndb/r/ndb_restore_options.result
mysql-test/suite/ndb/t/ndb_restore.test
mysql-test/suite/ndb/t/ndb_restore_options.test
mysql-test/suite/ndb_binlog/r/ndb_binlog_restore.result
mysql-test/suite/ndb_binlog/t/ndb_binlog_restore.test
scripts/make_win_bin_dist
sql/ha_ndbcluster.cc
sql/ha_ndbcluster_connection.cc
storage/ndb/include/kernel/kernel_config_parameters.h
storage/ndb/include/kernel/signaldata/ConfigChange.hpp
storage/ndb/include/kernel/signaldata/GetTabInfo.hpp
storage/ndb/include/ndb_global.h
storage/ndb/include/ndb_version.h.in
storage/ndb/include/ndbapi/Ndb.hpp
storage/ndb/include/ndbapi/NdbDictionary.hpp
storage/ndb/include/ndbapi/NdbError.hpp
storage/ndb/include/ndbapi/NdbOperation.hpp
storage/ndb/include/util/NdbOut.hpp
storage/ndb/src/common/debugger/EventLogger.cpp
storage/ndb/src/common/util/BaseString.cpp
storage/ndb/src/common/util/CMakeLists.txt
storage/ndb/src/common/util/Makefile.am
storage/ndb/src/common/util/NdbOut.cpp
storage/ndb/src/cw/cpcd/CMakeLists.txt
storage/ndb/src/cw/cpcd/Process.cpp
storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.hpp
storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
storage/ndb/src/kernel/blocks/pgman.cpp
storage/ndb/src/kernel/blocks/pgman.hpp
storage/ndb/src/kernel/vm/Configuration.cpp
storage/ndb/src/kernel/vm/DynArr256.cpp
storage/ndb/src/kernel/vm/SimulatedBlock.cpp
storage/ndb/src/kernel/vm/SimulatedBlock.hpp
storage/ndb/src/kernel/vm/mt.cpp
storage/ndb/src/mgmapi/mgmapi.cpp
storage/ndb/src/mgmsrv/CMakeLists.txt
storage/ndb/src/mgmsrv/Config.cpp
storage/ndb/src/mgmsrv/Config.hpp
storage/ndb/src/mgmsrv/ConfigInfo.cpp
storage/ndb/src/mgmsrv/ConfigManager.cpp
storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
storage/ndb/src/mgmsrv/MgmtSrvr.cpp
storage/ndb/src/mgmsrv/MgmtSrvr.hpp
storage/ndb/src/mgmsrv/main.cpp
storage/ndb/src/mgmsrv/testConfig.cpp
storage/ndb/src/ndbapi/Ndb.cpp
storage/ndb/src/ndbapi/NdbDictionary.cpp
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
storage/ndb/src/ndbapi/NdbImpl.hpp
storage/ndb/src/ndbapi/NdbOperationDefine.cpp
storage/ndb/src/ndbapi/NdbOperationExec.cpp
storage/ndb/src/ndbapi/NdbOperationSearch.cpp
storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp
storage/ndb/src/ndbapi/NdbScanOperation.cpp
storage/ndb/src/ndbapi/Ndbinit.cpp
storage/ndb/src/ndbapi/TransporterFacade.hpp
storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
storage/ndb/src/ndbapi/ndberror.c
storage/ndb/test/include/NDBT_Test.hpp
storage/ndb/test/ndbapi/slow_select.cpp
storage/ndb/test/ndbapi/testBlobs.cpp
storage/ndb/test/ndbapi/testIndex.cpp
storage/ndb/test/ndbapi/testLcp.cpp
storage/ndb/test/ndbapi/testMgmd.cpp
storage/ndb/test/ndbapi/testNdbinfo.cpp
storage/ndb/test/ndbapi/testPartitioning.cpp
storage/ndb/test/run-test/CMakeLists.txt
storage/ndb/test/run-test/atrt.hpp
storage/ndb/test/run-test/daily-basic-tests.txt
storage/ndb/test/run-test/daily-devel-tests.txt
storage/ndb/test/run-test/main.cpp
storage/ndb/test/src/CMakeLists.txt
storage/ndb/test/src/Makefile.am
storage/ndb/test/src/NDBT_Test.cpp
storage/ndb/tools/ndbinfo_sql.cpp
storage/ndb/tools/restore/Restore.cpp
storage/ndb/tools/restore/Restore.hpp
storage/ndb/tools/restore/consumer_printer.cpp
storage/ndb/tools/restore/consumer_restore.cpp
storage/ndb/tools/restore/consumer_restore.hpp
storage/ndb/tools/restore/restore_main.cpp
=== modified file 'mysql-test/suite/ndb/r/ndb_restore.result'
--- a/mysql-test/suite/ndb/r/ndb_restore.result 2009-10-09 18:43:30 +0000
+++ b/mysql-test/suite/ndb/r/ndb_restore.result 2009-12-01 10:15:25 +0000
@@ -582,3 +582,21 @@ epoch
select epoch > (1 << 32) from mysql.ndb_apply_status where server_id=0;
epoch > (1 << 32)
1
+create table t1 (a int not null primary key auto_increment, b int) auto_increment=200
+engine=ndb;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL AUTO_INCREMENT,
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=ndbcluster AUTO_INCREMENT=200 DEFAULT CHARSET=latin1
+drop table t1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL AUTO_INCREMENT,
+ `b` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=ndbcluster AUTO_INCREMENT=200 DEFAULT CHARSET=latin1
+drop table t1;
=== modified file 'mysql-test/suite/ndb/r/ndb_restore_options.result'
--- a/mysql-test/suite/ndb/r/ndb_restore_options.result 2009-05-08 17:58:13 +0000
+++ b/mysql-test/suite/ndb/r/ndb_restore_options.result 2009-12-02 10:40:46 +0000
@@ -374,10 +374,12 @@ drop table db2.tab1, db2.tab2;
*********************************
Include db1, and include db2.tab1
*********************************
-Should result in db2.tab1 only restored.
+Should result in all tables in db1 and db2.tab1 being restored.
use db1;
show tables;
Tables_in_db1
+tab1
+tab2
use db2;
show tables;
Tables_in_db2
@@ -394,7 +396,7 @@ a
7
8
9
-drop table db2.tab1;
+drop table db1.tab1,db1.tab2,db2.tab1;
************************
Include unknown database
************************
@@ -479,13 +481,14 @@ a b c d
7 Highlea 7 UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
UUUUUUUUUUUUUUUUUUUUUUU
drop table db1.tab1, db1.tab2;
drop table db2.tab1, db2.tab2;
-*********************************************
-Check that last argument of each type is used
-*********************************************
-Should result in just db1.tab2 restored.
+************************************
+Check accumulative include arguments
+************************************
+Should result in both db1.tab1 and db1.tab2 restored.
use db1;
show tables;
Tables_in_db1
+tab1
tab2
select * from tab2 order by a;
a b c d
@@ -499,6 +502,19 @@ a b c d
use db2;
show tables;
Tables_in_db2
-drop table db1.tab2;
+drop table db1.tab1, db1.tab2;
+************************************
+Check accumulative exclude arguments
+************************************
+Should result in both db2.tab1 and db2.tab2 restored.
+use db1;
+show tables;
+Tables_in_db1
+use db2;
+show tables;
+Tables_in_db2
+tab1
+tab2
+drop table db2.tab1, db2.tab2;
drop database db1;
drop database db2;
=== added file 'mysql-test/suite/ndb/r/ndb_short_sigs.result'
--- a/mysql-test/suite/ndb/r/ndb_short_sigs.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_short_sigs.result 2009-11-18 11:05:02 +0000
@@ -0,0 +1,105 @@
+create table t1 (
+th int primary key,
+un int,
+de int,
+rb varchar(1000),
+al longtext,
+key(de),
+unique(rb))
+engine=ndb;
+insert into t1 values (1, 1, 1, repeat('O', 1000), repeat('L', 60000));
+insert into t1 values (2, 2, 2, repeat('W', 999), repeat('B', 60001));
+insert into t1 values (3, 3, 3, repeat('P', 998), repeat('P', 60002));
+insert into t1 values (4, 4, 4, repeat('Q', 997), repeat('E', 60003));
+insert into t1 values (5, 5, 5, repeat('E', 996), repeat('A', 60004));
+select th, un, de, length(rb), length(al)
+from t1
+where th in (2,4)
+order by th;
+th un de length(rb) length(al)
+2 2 2 999 60001
+4 4 4 997 60003
+select th, un, de, length(rb), length(al)
+from t1
+where rb
+in (repeat('O', 1000), repeat('Q', 997))
+order by th;
+th un de length(rb) length(al)
+1 1 1 1000 60000
+4 4 4 997 60003
+select th, un, de, length(rb), length(al)
+from t1
+where de between 3 and 5
+order by th;
+th un de length(rb) length(al)
+3 3 3 998 60002
+4 4 4 997 60003
+5 5 5 996 60004
+select th, un, de, length(rb), length(al)
+from t1
+order by th;
+th un de length(rb) length(al)
+1 1 1 1000 60000
+2 2 2 999 60001
+3 3 3 998 60002
+4 4 4 997 60003
+5 5 5 996 60004
+update t1
+set un=6, de=6, rb= repeat('S', 995), al = repeat('O', 60005)
+where th = 1;
+update t1
+set un=7, de=7, al = repeat('F', 60006)
+where rb = repeat('W', 999);
+update t1
+set un= un + 5, rb = repeat('U', 1000 - un), al = repeat('U', 60000 + un)
+where de >= 3 and de <= 5;
+select th, un, de, length(rb), length(al)
+from t1
+order by th;
+th un de length(rb) length(al)
+1 6 6 995 60005
+2 7 7 999 60006
+3 8 3 992 60008
+4 9 4 991 60009
+5 10 5 990 60010
+alter table t1 add column extra varchar(2000);
+Warnings:
+Warning 1478 Converted FIXED field to DYNAMIC to enable on-line ADD COLUMN
+update t1 set extra = repeat(rb, 2);
+select th, un, de, length(rb), length(al), length(extra)
+from t1
+order by th;
+th un de length(rb) length(al) length(extra)
+1 6 6 995 60005 1990
+2 7 7 999 60006 1998
+3 8 3 992 60008 1984
+4 9 4 991 60009 1982
+5 10 5 990 60010 1980
+select th, un, de, length(rb), length(al), length(extra)
+from t1
+where extra in (
+repeat('U', 2000),
+repeat('U', 1998),
+repeat('U', 1996),
+repeat('U', 1994),
+repeat('U', 1992),
+repeat('U', 1990),
+repeat('U', 1988),
+repeat('U', 1986),
+repeat('U', 1984),
+repeat('U', 1982),
+repeat('U', 1980),
+repeat('U', 1978),
+repeat('U', 1976),
+repeat('U', 1974),
+repeat('U', 1972),
+repeat('U', 1970),
+repeat('U', 1968),
+repeat('U', 1966),
+repeat('U', 1964))
+order by th;
+th un de length(rb) length(al) length(extra)
+3 8 3 992 60008 1984
+4 9 4 991 60009 1982
+5 10 5 990 60010 1980
+drop table t1;
=== modified file 'mysql-test/suite/ndb/t/ndb_restore.test'
--- a/mysql-test/suite/ndb/t/ndb_restore.test 2009-10-11 12:04:37 +0000
+++ b/mysql-test/suite/ndb/t/ndb_restore.test 2009-12-01 10:15:25 +0000
@@ -497,3 +497,16 @@ select epoch > (1 << 32) from mysql.ndb_
#
--exec $NDB_RESTORE --print_log -b 1 -n 1 $MYSQL_TEST_DIR/std_data/ndb_backup50 >> $NDB_TOOLS_OUTPUT
+#
+# Bug#48005 ndb backup / restore does not restore the auto_increment
+#
+create table t1 (a int not null primary key auto_increment, b int) auto_increment=200
+engine=ndb;
+show create table t1;
+--source include/ndb_backup.inc
+drop table t1;
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -m -r --print_meta $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -r --print_meta $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
+show create table t1;
+drop table t1;
+
=== modified file 'mysql-test/suite/ndb/t/ndb_restore_options.test'
--- a/mysql-test/suite/ndb/t/ndb_restore_options.test 2009-04-09 15:25:11 +0000
+++ b/mysql-test/suite/ndb/t/ndb_restore_options.test 2009-12-02 13:54:07 +0000
@@ -163,9 +163,8 @@ drop table db1.tab2, db2.tab1;
--echo *********************************
--echo Should result in only db1.tab1 being restored
---exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -r -m $NDB_BACKUPS-$the_backup_id --include-tables db1.tab1 --exclude-databases db1 >> $NDB_TOOLS_OUTPUT
---exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -r $NDB_BACKUPS-$the_backup_id --include-tables db1.tab1 --exclude-databases db1 >> $NDB_TOOLS_OUTPUT
-
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -r -m $NDB_BACKUPS-$the_backup_id --exclude-databases db1 --include-tables db1.tab1 >> $NDB_TOOLS_OUTPUT
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -r $NDB_BACKUPS-$the_backup_id --exclude-databases db1 --include-tables db1.tab1>> $NDB_TOOLS_OUTPUT
use db1;
show tables;
@@ -181,9 +180,8 @@ drop table db1.tab1;
--echo Exclude db1.tab1, but include db1
--echo *********************************
--echo Should result in only db1.tab2 being restored
---exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -r -m $NDB_BACKUPS-$the_backup_id --exclude-tables db1.tab1 --include-databases db1 >> $NDB_TOOLS_OUTPUT
---exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -r $NDB_BACKUPS-$the_backup_id --exclude-tables db1.tab1 --include-databases db1 >> $NDB_TOOLS_OUTPUT
-
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -r -m $NDB_BACKUPS-$the_backup_id --include-databases db1 --exclude-tables db1.tab1 >> $NDB_TOOLS_OUTPUT
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -r $NDB_BACKUPS-$the_backup_id --include-databases db1 --exclude_tables db1.tab1 >> $NDB_TOOLS_OUTPUT
use db1;
show tables;
@@ -234,19 +232,20 @@ drop table db2.tab1, db2.tab2;
--echo *********************************
--echo Include db1, and include db2.tab1
--echo *********************************
---echo Should result in db2.tab1 only restored.
+--echo Should result in all tables in db1 and db2.tab1 being restored.
--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -r -m $NDB_BACKUPS-$the_backup_id --include-databases db1 --include-tables db2.tab1 >> $NDB_TOOLS_OUTPUT
--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -r $NDB_BACKUPS-$the_backup_id --include-databases db1 --include-tables db2.tab1 >> $NDB_TOOLS_OUTPUT
use db1;
+--sorted_result
show tables;
use db2;
show tables;
# checksum table tab1;
select * from tab1 order by a;
-drop table db2.tab1;
+drop table db1.tab1,db1.tab2,db2.tab1;
--echo ************************
@@ -285,14 +284,15 @@ select * from tab2 order by a;
drop table db1.tab1, db1.tab2;
drop table db2.tab1, db2.tab2;
---echo *********************************************
---echo Check that last argument of each type is used
---echo *********************************************
---echo Should result in just db1.tab2 restored.
+--echo ************************************
+--echo Check accumulative include arguments
+--echo ************************************
+--echo Should result in both db1.tab1 and db1.tab2 restored.
--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -r -m $NDB_BACKUPS-$the_backup_id --include-tables db1.tab1 --include-tables db1.tab2 >> $NDB_TOOLS_OUTPUT
--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -r $NDB_BACKUPS-$the_backup_id --include-tables db1.tab1 --include-tables db1.tab2 >> $NDB_TOOLS_OUTPUT
use db1;
+--sorted_result
show tables;
# checksum table tab2;
select * from tab2 order by a;
@@ -300,8 +300,22 @@ select * from tab2 order by a;
use db2;
show tables;
-drop table db1.tab2;
+drop table db1.tab1, db1.tab2;
+
+--echo ************************************
+--echo Check accumulative exclude arguments
+--echo ************************************
+--echo Should result in both db2.tab1 and db2.tab2 restored.
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -r -m $NDB_BACKUPS-$the_backup_id --exclude-tables db1.tab1 --exclude-tables db1.tab2 >> $NDB_TOOLS_OUTPUT
+--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -r $NDB_BACKUPS-$the_backup_id --exclude-tables db1.tab1 --exclude-tables db1.tab2 >> $NDB_TOOLS_OUTPUT
+use db1;
+show tables;
+use db2;
+--sorted_result
+show tables;
+
+drop table db2.tab1, db2.tab2;
drop database db1;
drop database db2;
=== added file 'mysql-test/suite/ndb/t/ndb_short_sigs.cnf'
--- a/mysql-test/suite/ndb/t/ndb_short_sigs.cnf 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_short_sigs.cnf 2009-11-18 11:05:02 +0000
@@ -0,0 +1,9 @@
+#
+# Config used when testing short NdbApi request handling
+# functionality
+#
+!include suite/ndb/my.cnf
+
+[ENV]
+# Activate short signal requests
+NDB_FORCE_SHORT_REQUESTS=Y
=== added file 'mysql-test/suite/ndb/t/ndb_short_sigs.test'
--- a/mysql-test/suite/ndb/t/ndb_short_sigs.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_short_sigs.test 2009-11-18 11:05:02 +0000
@@ -0,0 +1,102 @@
+-- source include/have_ndb.inc
+
+
+# Create table with unique key, ordered index + blob
+
+create table t1 (
+ th int primary key,
+ un int,
+ de int,
+ rb varchar(1000),
+ al longtext,
+ key(de),
+ unique(rb))
+ engine=ndb;
+
+insert into t1 values (1, 1, 1, repeat('O', 1000), repeat('L', 60000));
+insert into t1 values (2, 2, 2, repeat('W', 999), repeat('B', 60001));
+insert into t1 values (3, 3, 3, repeat('P', 998), repeat('P', 60002));
+insert into t1 values (4, 4, 4, repeat('Q', 997), repeat('E', 60003));
+insert into t1 values (5, 5, 5, repeat('E', 996), repeat('A', 60004));
+
+# Pk lookup
+select th, un, de, length(rb), length(al)
+ from t1
+ where th in (2,4)
+ order by th;
+
+# Uk lookup
+select th, un, de, length(rb), length(al)
+ from t1
+ where rb
+ in (repeat('O', 1000), repeat('Q', 997))
+ order by th;
+
+# Secondary Index scan
+select th, un, de, length(rb), length(al)
+ from t1
+ where de between 3 and 5
+ order by th;
+
+# Table scan
+select th, un, de, length(rb), length(al)
+ from t1
+ order by th;
+
+# Update via Pk
+update t1
+ set un=6, de=6, rb= repeat('S', 995), al = repeat('O', 60005)
+ where th = 1;
+
+# Update via Uk
+update t1
+ set un=7, de=7, al = repeat('F', 60006)
+ where rb = repeat('W', 999);
+
+# Update via Index Scan
+update t1
+ set un= un + 5, rb = repeat('U', 1000 - un), al = repeat('U', 60000 + un)
+ where de >= 3 and de <= 5;
+
+# Table scan
+select th, un, de, length(rb), length(al)
+ from t1
+ order by th;
+
+# Online alter table
+alter table t1 add column extra varchar(2000);
+
+# Table scanning update
+update t1 set extra = repeat(rb, 2);
+
+# Table scan
+select th, un, de, length(rb), length(al), length(extra)
+ from t1
+ order by th;
+
+# Table scan with large pushed filter
+select th, un, de, length(rb), length(al), length(extra)
+ from t1
+ where extra in (
+ repeat('U', 2000),
+ repeat('U', 1998),
+ repeat('U', 1996),
+ repeat('U', 1994),
+ repeat('U', 1992),
+ repeat('U', 1990),
+ repeat('U', 1988),
+ repeat('U', 1986),
+ repeat('U', 1984),
+ repeat('U', 1982),
+ repeat('U', 1980),
+ repeat('U', 1978),
+ repeat('U', 1976),
+ repeat('U', 1974),
+ repeat('U', 1972),
+ repeat('U', 1970),
+ repeat('U', 1968),
+ repeat('U', 1966),
+ repeat('U', 1964))
+ order by th;
+
+drop table t1;
=== modified file 'mysql-test/suite/ndb_binlog/r/ndb_binlog_restore.result'
--- a/mysql-test/suite/ndb_binlog/r/ndb_binlog_restore.result 2009-02-01 21:05:19 +0000
+++ b/mysql-test/suite/ndb_binlog/r/ndb_binlog_restore.result 2009-12-04 17:15:03 +0000
@@ -5,40 +5,35 @@ drop table if exists t1;
create table t1 (a int key, b int) engine ndb;
insert into t1 values (1,1);
#
-# extra table to be used to ensure data has arrived to binlog
-create table t2 (a int key, b int) engine ndb;
-#
# reset and restore schema
drop table t1;
reset master;
show tables;
Tables_in_test
-t2
t1
#
# restore and _no_ binlog
#
-# check the binlog, should be empty
-# extra insert (not logged) to ensure data has arrived to binlog
-set SQL_LOG_BIN=0;
-insert into t2 values (1,1);
+# check the binlog, should be empty apart from our marker
+# create dummy table to wait for to ensure Binlog contains any previous events
+create table binlogmarker (a int) engine=ndb;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
+mysqld-bin.000001 # Query 1 # use `test`; create table binlogmarker (a int) engine=ndb
#
# reset and restore schema again
+drop table binlogmarker;
drop table t1;
reset master;
show tables;
Tables_in_test
-t2
t1
#
-# restore and binlog should now happen
+# restore and binlog should now happen as well as the marker
#
# check the binlog, should contain data
-# extra insert (not logged) to ensure data has arrived to binlog
-set SQL_LOG_BIN=0;
-insert into t2 values (2,2);
+# create dummy table to wait for to ensure Binlog contains any previous events
+create table binlogmarker (a int) engine=ndb;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
mysqld-bin.000001 # Query 1 # BEGIN
@@ -47,7 +42,8 @@ mysqld-bin.000001 # Table_map 1 # table_
mysqld-bin.000001 # Write_rows 1 # table_id: #
mysqld-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
mysqld-bin.000001 # Query 1 # COMMIT
-drop table t1, t2;
+mysqld-bin.000001 # Query 1 # use `test`; create table binlogmarker (a int) engine=ndb
+drop table binlogmarker, t1;
#
# Now more complex using "BANK schema" including restore of log
#
=== modified file 'mysql-test/suite/ndb_binlog/t/ndb_binlog_restore.test'
--- a/mysql-test/suite/ndb_binlog/t/ndb_binlog_restore.test 2008-10-22 10:12:53 +0000
+++ b/mysql-test/suite/ndb_binlog/t/ndb_binlog_restore.test 2009-12-04 17:27:44 +0000
@@ -17,10 +17,6 @@ insert into t1 values (1,1);
--enable_query_log
--echo #
---echo # extra table to be used to ensure data has arrived to binlog
-create table t2 (a int key, b int) engine ndb;
-
---echo #
--echo # reset and restore schema
drop table t1;
reset master;
@@ -33,32 +29,39 @@ show tables;
--exec $NDB_RESTORE --no-defaults --no-binlog -b $the_backup_id -n 2 -r --print --print_meta $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
--echo #
---echo # check the binlog, should be empty
---echo # extra insert (not logged) to ensure data has arrived to binlog
-set SQL_LOG_BIN=0;
-insert into t2 values (1,1);
+--echo # check the binlog, should be empty apart from our marker
+--echo # create dummy table to wait for to ensure Binlog contains any previous events
+
+create table binlogmarker (a int) engine=ndb;
+let $wait_binlog_event= binlogmarker;
+--source include/wait_for_binlog_event.inc
+
--source include/show_binlog_events2.inc
--echo #
--echo # reset and restore schema again
+drop table binlogmarker;
drop table t1;
reset master;
--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -m --print --print_meta $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
show tables;
--echo #
---echo # restore and binlog should now happen
+--echo # restore and binlog should now happen as well as the marker
--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 1 -r --print --print_meta $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_RESTORE --no-defaults -b $the_backup_id -n 2 -r --print --print_meta $NDB_BACKUPS-$the_backup_id >> $NDB_TOOLS_OUTPUT
--echo #
--echo # check the binlog, should contain data
---echo # extra insert (not logged) to ensure data has arrived to binlog
-set SQL_LOG_BIN=0;
-insert into t2 values (2,2);
+--echo # create dummy table to wait for to ensure Binlog contains any previous events
+
+create table binlogmarker (a int) engine=ndb;
+let $wait_binlog_event= binlogmarker;
+--source include/wait_for_binlog_event.inc
+
--source include/show_binlog_events2.inc
-drop table t1, t2;
+drop table binlogmarker, t1;
=== modified file 'scripts/make_win_bin_dist'
--- a/scripts/make_win_bin_dist 2009-10-01 07:16:52 +0000
+++ b/scripts/make_win_bin_dist 2009-11-17 16:30:37 +0000
@@ -340,7 +340,7 @@ fi
mkdir $DESTDIR/mysql-test
cp mysql-test/mysql-test-run.pl $DESTDIR/mysql-test/
cp mysql-test/README $DESTDIR/mysql-test/
-cp -R mysql-test/{t,r,include,suite,std_data,lib} $DESTDIR/mysql-test/
+cp -R mysql-test/{t,r,include,suite,std_data,lib,collections} $DESTDIR/mysql-test/
# Note that this will not copy "extra" if a soft link
if [ -d mysql-test/extra ] ; then
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2009-12-04 18:23:46 +0000
+++ b/sql/ha_ndbcluster.cc 2009-12-06 17:12:40 +0000
@@ -1961,7 +1961,7 @@ void ha_ndbcluster::release_blobs_buffer
DBUG_ENTER("releaseBlobsBuffer");
if (m_blobs_buffer_size > 0)
{
- DBUG_PRINT("info", ("Deleting blobs buffer, size %u", m_blobs_buffer_size));
+ DBUG_PRINT("info", ("Deleting blobs buffer, size %llu", m_blobs_buffer_size));
my_free(m_blobs_buffer, MYF(MY_ALLOW_ZERO_PTR));
m_blobs_buffer= 0;
m_blobs_row_total_size= 0;
@@ -13581,6 +13581,7 @@ int ha_ndbcluster::alter_table_phase1(TH
DBUG_PRINT("info", ("Failed to start schema transaction"));
ERR_PRINT(dict->getNdbError());
error= ndb_to_mysql_error(&dict->getNdbError());
+ table->file->print_error(error, MYF(0));
goto err;
}
=== modified file 'sql/ha_ndbcluster_connection.cc'
--- a/sql/ha_ndbcluster_connection.cc 2009-11-08 18:23:30 +0000
+++ b/sql/ha_ndbcluster_connection.cc 2009-11-17 15:57:14 +0000
@@ -72,7 +72,7 @@ int ndbcluster_connect(int (*connect_cal
DBUG_PRINT("error",("Ndb_cluster_connection(%s)",
opt_ndb_connectstring));
my_errno= HA_ERR_OUT_OF_MEM;
- goto ndbcluster_connect_error;
+ DBUG_RETURN(-1);
}
{
char buf[128];
@@ -89,14 +89,14 @@ int ndbcluster_connect(int (*connect_cal
sql_print_error("NDB: failed to allocate global ndb object");
DBUG_PRINT("error", ("failed to create global ndb object"));
my_errno= HA_ERR_OUT_OF_MEM;
- goto ndbcluster_connect_error;
+ DBUG_RETURN(-1);
}
if (g_ndb->init() != 0)
{
DBUG_PRINT("error", ("%d message: %s",
g_ndb->getNdbError().code,
g_ndb->getNdbError().message));
- goto ndbcluster_connect_error;
+ DBUG_RETURN(-1);
}
/* Connect to management server */
@@ -110,7 +110,7 @@ int ndbcluster_connect(int (*connect_cal
break;
do_retry_sleep(100);
if (abort_loop)
- goto ndbcluster_connect_error;
+ DBUG_RETURN(-1);
}
{
@@ -131,7 +131,7 @@ int ndbcluster_connect(int (*connect_cal
i);
DBUG_PRINT("error",("Ndb_cluster_connection[%u](%s)",
i, opt_ndb_connectstring));
- goto ndbcluster_connect_error;
+ DBUG_RETURN(-1);
}
{
char buf[128];
@@ -200,7 +200,7 @@ int ndbcluster_connect(int (*connect_cal
{
sql_print_error("NDB[%u]: failed to start connect thread", i);
DBUG_PRINT("error", ("g_ndb_cluster_connection->start_connect_thread()"));
- goto ndbcluster_connect_error;
+ DBUG_RETURN(-1);
}
}
#ifndef DBUG_OFF
@@ -221,11 +221,9 @@ int ndbcluster_connect(int (*connect_cal
sql_print_error("NDB: error (%u) %s",
g_ndb_cluster_connection->get_latest_error(),
g_ndb_cluster_connection->get_latest_error_msg());
- goto ndbcluster_connect_error;
+ DBUG_RETURN(-1);
}
DBUG_RETURN(0);
-ndbcluster_connect_error:
- DBUG_RETURN(-1);
}
void ndbcluster_disconnect(void)
=== modified file 'storage/ndb/include/kernel/kernel_config_parameters.h'
--- a/storage/ndb/include/kernel/kernel_config_parameters.h 2009-10-15 12:36:53 +0000
+++ b/storage/ndb/include/kernel/kernel_config_parameters.h 2009-12-04 12:45:23 +0000
@@ -36,7 +36,6 @@
#define CFG_DIH_API_CONNECT (PRIVATE_BASE + 15)
#define CFG_DIH_FRAG_CONNECT (PRIVATE_BASE + 17)
-#define CFG_DIH_MORE_NODES (PRIVATE_BASE + 18)
#define CFG_DIH_REPLICAS (PRIVATE_BASE + 19)
#define CFG_DIH_TABLE (PRIVATE_BASE + 20)
=== modified file 'storage/ndb/include/kernel/signaldata/ConfigChange.hpp'
--- a/storage/ndb/include/kernel/signaldata/ConfigChange.hpp 2009-09-25 07:57:29 +0000
+++ b/storage/ndb/include/kernel/signaldata/ConfigChange.hpp 2009-11-17 18:13:29 +0000
@@ -204,11 +204,13 @@ class ConfigCheckReq {
friend class ConfigManager;
public:
- STATIC_CONST( SignalLength = 2 );
+ STATIC_CONST( SignalLengthBeforeChecksum = 2 );
+ STATIC_CONST( SignalLength = 3 );
private:
Uint32 state;
Uint32 generation;
+ Uint32 checksum;
};
@@ -246,7 +248,8 @@ class ConfigCheckRef {
enum ErrorCode {
WrongState = 1,
- WrongGeneration = 2
+ WrongGeneration = 2,
+ WrongChecksum = 3
};
static const char* errorMessage(Uint32 error) {
@@ -255,6 +258,8 @@ class ConfigCheckRef {
return "Wrong state";
case WrongGeneration:
return "Wrong generation";
+ case WrongChecksum:
+ return "Wrong checksum";
default:
return "ConfigCheckRef, unknown error";
=== modified file 'storage/ndb/include/kernel/signaldata/GetTabInfo.hpp'
--- a/storage/ndb/include/kernel/signaldata/GetTabInfo.hpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/include/kernel/signaldata/GetTabInfo.hpp 2009-11-18 11:05:02 +0000
@@ -74,6 +74,9 @@ class GetTabInfoRef {
friend bool printGET_TABINFO_REF(FILE *, const Uint32 *, Uint32, Uint16);
public:
STATIC_CONST( SignalLength = 7 );
+ /* 6.3 <-> 7.0 upgrade code */
+ STATIC_CONST( OriginalSignalLength = 5 );
+ STATIC_CONST( OriginalErrorOffset = 4 );
public:
Uint32 senderData;
Uint32 senderRef;
=== modified file 'storage/ndb/include/ndb_global.h'
--- a/storage/ndb/include/ndb_global.h 2009-10-09 14:12:17 +0000
+++ b/storage/ndb/include/ndb_global.h 2009-12-04 05:53:03 +0000
@@ -211,4 +211,34 @@ extern "C" {
#define ASSERT_TYPE_HAS_CONSTRUCTOR(x)
#endif
+/*
+ * require is like a normal assert, only it's always on (eg. in release)
+*/
+C_MODE_START
+// see below
+typedef int(*RequirePrinter)(const char *fmt, ...);
+void require_failed(int exitcode, RequirePrinter p,
+ const char* expr, const char* file, int line);
+int ndbout_printer(const char * fmt, ...);
+C_MODE_END
+/*
+ * this allows for an exit() call if exitcode is not zero
+ * and takes a Printer to print the error
+*/
+#define require_exit_or_core_with_printer(v, exitcode, printer) \
+ do { if (likely(!(!(v)))) break; \
+ require_failed((exitcode), (printer), #v, __FILE__, __LINE__); \
+ } while (0)
+
+/*
+ * this allows for an exit() call if exitcode is not zero
+*/
+#define require_exit_or_core(v, exitcode) \
+ require_exit_or_core_with_printer((v), (exitcode), 0)
+
+/*
+ * this require is like a normal assert. (only it's always on)
+*/
+#define require(v) require_exit_or_core_with_printer((v), 0, 0)
+
#endif
=== modified file 'storage/ndb/include/ndb_version.h.in'
--- a/storage/ndb/include/ndb_version.h.in 2009-11-02 17:15:29 +0000
+++ b/storage/ndb/include/ndb_version.h.in 2009-12-02 16:01:50 +0000
@@ -102,11 +102,16 @@ Uint32 ndbGetOwnVersion();
#define NDBD_MICRO_GCP_62 NDB_MAKE_VERSION(6,2,5)
#define NDBD_MICRO_GCP_63 NDB_MAKE_VERSION(6,3,2)
#define NDBD_RAW_LCP MAKE_VERSION(6,3,11)
+#define NDBD_LONG_TCKEYREQ NDB_MAKE_VERSION(6,4,0)
#define NDBD_LONG_LQHKEYREQ MAKE_VERSION(6,4,0)
#define NDBD_MAX_RECVBYTESIZE_32K MAKE_VERSION(6,3,18)
+#define NDBD_LONG_SCANTABREQ NDB_MAKE_VERSION(6,4,0)
#define NDBD_LONG_SCANFRAGREQ MAKE_VERSION(6,4,0)
#define NDBD_MT_LQH_VERSION MAKE_VERSION(6,4,0)
+#define NDBD_SCHEMA_TRANS_VERSION NDB_MAKE_VERSION(6,4,0)
+#define MGMD_MGMAPI_PROTOCOL_CHANGE NDB_MAKE_VERSION(6,4,0)
+
static
inline
=== modified file 'storage/ndb/include/ndbapi/Ndb.hpp'
--- a/storage/ndb/include/ndbapi/Ndb.hpp 2009-08-26 08:33:16 +0000
+++ b/storage/ndb/include/ndbapi/Ndb.hpp 2009-12-06 17:12:40 +0000
@@ -1626,6 +1626,18 @@ public:
*/
const NdbError & getNdbError(int errorCode);
+ /**
+ * Get a string containing any extra error details in the supplied
+ * buffer
+ * Where there is extra detail available a ptr to the start of
+ * the supplied buffer will be returned.
+ * If the extra detail string is longer than the passed buffer
+ * then it will be truncated to fit.
+ * Where there is no extra detail, NULL will be returned.
+ */
+ const char* getNdbErrorDetail(const NdbError& err,
+ char* buff,
+ Uint32 buffLen) const;
/** @} *********************************************************************/
=== modified file 'storage/ndb/include/ndbapi/NdbDictionary.hpp'
--- a/storage/ndb/include/ndbapi/NdbDictionary.hpp 2009-10-07 02:56:19 +0000
+++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp 2009-12-03 10:19:24 +0000
@@ -741,6 +741,11 @@ public:
int getNoOfColumns() const;
/**
+ * Get number of auto_increment columns in the table
+ */
+ int getNoOfAutoIncrementColumns() const;
+
+ /**
* Get number of primary keys in the table
*/
int getNoOfPrimaryKeys() const;
@@ -2033,6 +2038,9 @@ public:
#endif
int listObjects(List & list,
Object::Type type = Object::TypeUndefined) const;
+ int listObjects(List & list,
+ Object::Type type,
+ bool fullyQualified) const;
/**
* Get the latest error
=== modified file 'storage/ndb/include/ndbapi/NdbError.hpp'
--- a/storage/ndb/include/ndbapi/NdbError.hpp 2009-06-15 06:15:20 +0000
+++ b/storage/ndb/include/ndbapi/NdbError.hpp 2009-12-03 09:48:37 +0000
@@ -208,6 +208,7 @@ struct NdbError {
*/
const char * message;
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/**
* The detailed description. This is extra information regarding the
* error which is not included in the error message.
@@ -215,6 +216,7 @@ struct NdbError {
* @note Is NULL when no details specified
*/
char * details;
+#endif
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
NdbError(){
=== modified file 'storage/ndb/include/ndbapi/NdbOperation.hpp'
--- a/storage/ndb/include/ndbapi/NdbOperation.hpp 2009-10-21 12:51:50 +0000
+++ b/storage/ndb/include/ndbapi/NdbOperation.hpp 2009-12-06 17:12:40 +0000
@@ -36,6 +36,7 @@ class NdbBlob;
class TcKeyReq;
class NdbRecord;
class NdbInterpretedCode;
+struct GenericSectionPtr;
/**
* @class NdbOperation
@@ -1207,8 +1208,8 @@ protected:
* was sent, then the connection object is told about this situation.
*****************************************************************************/
+ int doSendKeyReq(int processorId, GenericSectionPtr* secs, Uint32 numSecs);
int doSend(int ProcessorId, Uint32 lastFlag);
- int doSendNdbRecord(int aNodeId);
virtual int prepareSend(Uint32 TC_ConnectPtr,
Uint64 TransactionId,
AbortOption);
=== modified file 'storage/ndb/include/util/NdbOut.hpp'
--- a/storage/ndb/include/util/NdbOut.hpp 2009-09-08 13:48:12 +0000
+++ b/storage/ndb/include/util/NdbOut.hpp 2009-12-03 05:53:33 +0000
@@ -120,6 +120,8 @@ inline NdbOut& dec(NdbOut& _NdbOut) {
}
extern "C"
void ndbout_c(const char * fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
+extern "C"
+void vndbout_c(const char * fmt, va_list ap);
class FilteredNdbOut : public NdbOut {
public:
=== modified file 'storage/ndb/src/common/debugger/EventLogger.cpp'
--- a/storage/ndb/src/common/debugger/EventLogger.cpp 2009-10-21 07:22:23 +0000
+++ b/storage/ndb/src/common/debugger/EventLogger.cpp 2009-11-30 10:45:52 +0000
@@ -1093,7 +1093,7 @@ const EventLoggerBase::EventRepLogLevelM
ROW(GlobalCheckpointStarted, LogLevel::llCheckpoint, 9, Logger::LL_INFO ),
ROW(GlobalCheckpointCompleted,LogLevel::llCheckpoint,10, Logger::LL_INFO ),
ROW(LocalCheckpointStarted, LogLevel::llCheckpoint, 7, Logger::LL_INFO ),
- ROW(LocalCheckpointCompleted,LogLevel::llCheckpoint, 8, Logger::LL_INFO ),
+ ROW(LocalCheckpointCompleted,LogLevel::llCheckpoint, 7, Logger::LL_INFO ),
ROW(LCPStoppedInCalcKeepGci, LogLevel::llCheckpoint, 0, Logger::LL_ALERT ),
ROW(LCPFragmentCompleted, LogLevel::llCheckpoint, 11, Logger::LL_INFO ),
ROW(UndoLogBlocked, LogLevel::llCheckpoint, 7, Logger::LL_INFO ),
@@ -1119,11 +1119,11 @@ const EventLoggerBase::EventRepLogLevelM
ROW(LogFileInitCompStatus, LogLevel::llStartUp, 7, Logger::LL_INFO),
// NODERESTART
- ROW(NR_CopyDict, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
- ROW(NR_CopyDistr, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
- ROW(NR_CopyFragsStarted, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
+ ROW(NR_CopyDict, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
+ ROW(NR_CopyDistr, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
+ ROW(NR_CopyFragsStarted, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
ROW(NR_CopyFragDone, LogLevel::llNodeRestart,10, Logger::LL_INFO ),
- ROW(NR_CopyFragsCompleted, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
+ ROW(NR_CopyFragsCompleted, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
ROW(NodeFailCompleted, LogLevel::llNodeRestart, 8, Logger::LL_ALERT),
ROW(NODE_FAILREP, LogLevel::llNodeRestart, 8, Logger::LL_ALERT),
=== modified file 'storage/ndb/src/common/util/BaseString.cpp'
--- a/storage/ndb/src/common/util/BaseString.cpp 2009-07-16 16:36:20 +0000
+++ b/storage/ndb/src/common/util/BaseString.cpp 2009-11-13 11:11:12 +0000
@@ -500,9 +500,10 @@ BaseString
BaseString::getPrettyText(unsigned size, const Uint32 data[])
{
const char* delimiter = "";
- unsigned i, found = 0, MAX_BITS = 8 * size;
+ unsigned found = 0;
+ const unsigned MAX_BITS = sizeof(Uint32) * 8 * size;
BaseString to;
- for (i = 0; i < MAX_BITS; i++)
+ for (unsigned i = 0; i < MAX_BITS; i++)
{
if (BitmaskImpl::get(size, data, i))
{
@@ -521,9 +522,9 @@ BaseString
BaseString::getPrettyTextShort(unsigned size, const Uint32 data[])
{
const char* delimiter = "";
- unsigned i, MAX_BITS = 8 * size;
+ const unsigned MAX_BITS = sizeof(Uint32) * 8 * size;
BaseString to;
- for (i = 0; i < MAX_BITS; i++)
+ for (unsigned i = 0; i < MAX_BITS; i++)
{
if (BitmaskImpl::get(size, data, i))
{
=== modified file 'storage/ndb/src/common/util/CMakeLists.txt'
--- a/storage/ndb/src/common/util/CMakeLists.txt 2009-11-08 12:52:27 +0000
+++ b/storage/ndb/src/common/util/CMakeLists.txt 2009-12-03 05:53:33 +0000
@@ -53,6 +53,7 @@ ADD_LIBRARY(ndbgeneral STATIC
ndb_opts.c
basestring_vsnprintf.c
Bitmask.cpp
+ require.c
)
TARGET_LINK_LIBRARIES(ndbgeneral zlib mysys ws2_32)
@@ -70,3 +71,7 @@ ADD_EXECUTABLE(Parser-t Parser.cpp)
SET_TARGET_PROPERTIES(Parser-t
PROPERTIES COMPILE_FLAGS "-DTEST_PARSER")
TARGET_LINK_LIBRARIES(Parser-t ndbgeneral)
+
+ADD_EXECUTABLE(require-test require.c)
+SET_TARGET_PROPERTIES(require-test
+ PROPERTIES COMPILE_FLAGS "-DTEST")
=== modified file 'storage/ndb/src/common/util/Makefile.am'
--- a/storage/ndb/src/common/util/Makefile.am 2009-11-08 12:52:27 +0000
+++ b/storage/ndb/src/common/util/Makefile.am 2009-12-03 05:53:33 +0000
@@ -28,7 +28,7 @@ libgeneral_la_SOURCES = \
strdup.c \
ConfigValues.cpp ndb_init.cpp basestring_vsnprintf.c \
Bitmask.cpp \
- ndb_rand.c
+ ndb_rand.c require.c
INCLUDES_LOC = @ZLIB_INCLUDES@
=== modified file 'storage/ndb/src/common/util/NdbOut.cpp'
--- a/storage/ndb/src/common/util/NdbOut.cpp 2009-09-09 12:34:25 +0000
+++ b/storage/ndb/src/common/util/NdbOut.cpp 2009-12-04 05:53:03 +0000
@@ -136,17 +136,37 @@ NdbOut::println(const char * fmt, ...){
extern "C"
void
-ndbout_c(const char * fmt, ...){
- va_list ap;
+vndbout_c(const char * fmt, va_list ap){
char buf[1000];
- va_start(ap, fmt);
if (fmt != 0)
+ {
BaseString::vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+ }
ndbout << buf << endl;
+}
+
+extern "C"
+void
+ndbout_c(const char * fmt, ...){
+ va_list ap;
+
+ va_start(ap, fmt);
+ vndbout_c(fmt, ap);
+ va_end(ap);
+}
+
+extern "C" int ndbout_printer(const char * fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vndbout_c(fmt, ap);
va_end(ap);
+ return 1;
}
+
FilteredNdbOut::FilteredNdbOut(OutputStream & out,
int threshold, int level)
: NdbOut(out) {
=== added file 'storage/ndb/src/common/util/require.c'
--- a/storage/ndb/src/common/util/require.c 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/util/require.c 2009-12-03 11:39:48 +0000
@@ -0,0 +1,32 @@
+#include <ndb_global.h>
+
+void require_failed(int exitcode, RequirePrinter printer,
+ const char* expr, const char* file, int line)
+{
+#define FMT "%s:%d: require(%s) failed\n", file, line, expr
+ if (!printer)
+ {
+ fprintf(stderr, FMT);
+ fflush(stderr);
+ }
+ else
+ {
+ printer(FMT);
+ }
+#ifdef _WIN32
+ DebugBreak();
+#endif
+ if(exitcode)
+ {
+ exit(exitcode);
+ }
+ abort();
+}
+
+#ifdef TEST
+int main()
+{
+ require(1);
+ require(0);
+}
+#endif
=== modified file 'storage/ndb/src/cw/cpcd/CMakeLists.txt'
--- a/storage/ndb/src/cw/cpcd/CMakeLists.txt 2009-10-08 09:20:37 +0000
+++ b/storage/ndb/src/cw/cpcd/CMakeLists.txt 2009-11-16 05:21:53 +0000
@@ -39,3 +39,4 @@ ADD_EXECUTABLE(ndb_cpcd
common.cpp
main.cpp)
+INSTALL(TARGETS ndb_cpcd DESTINATION bin)
=== modified file 'storage/ndb/src/cw/cpcd/Process.cpp'
--- a/storage/ndb/src/cw/cpcd/Process.cpp 2009-11-13 04:58:24 +0000
+++ b/storage/ndb/src/cw/cpcd/Process.cpp 2009-11-16 05:22:47 +0000
@@ -471,6 +471,8 @@ CPCD::Process::do_exec() {
CloseHandle(proc);
if (!pid) {
logger.critical("Couldn't get process ID");
+ } else {
+ logger.debug("new pid: %d\n", pid);
}
m_status = RUNNING;
@@ -642,38 +644,51 @@ static void get_processes(Pairs & pairs)
*/
static int kill_tree(pid_t pid, Pairs & pairs)
{
- size_t i, j;
- Vector<pid_t> parents;
+ size_t i, j, k, new_count;
+ Vector<pid_t> parents, new_parents;
parents.push_back(pid);
- for(i = 0; i < pairs.size(); i++)
+ do
{
- Vector<pid_t> new_parents;
- for(j = 0; j < parents.size(); j++)
+ for(i = 0; i < pairs.size(); i++)
{
- if(pairs[i].parent == parents[j])
+ for(j = 0; j < parents.size(); j++)
{
- new_parents.push_back(pairs[i].child);
+ if(pairs[i].parent == parents[j])
+ {
+ bool already_a_parent = false;
+ for(size_t x = 0; x < parents.size(); x++)
+ {
+ if(parents[x] == pairs[i].child)
+ {
+ already_a_parent = true;
+ break;
+ }
+ }
+ if (!already_a_parent)
+ {
+ new_parents.push_back(pairs[i].child);
+ }
+ }
}
}
- if(!new_parents.size())
- {
- break;
- }
- for(j = 0; j < new_parents.size(); j++)
+
+ new_count = new_parents.size();
+ for(k = 0; k < new_count; k++)
{
- parents.push_back(new_parents[j]);
+ parents.push_back(new_parents[k]);
}
- }
+ new_parents.clear();
+ } while(new_count);
logger.debug("killing processes in order: ");
- for(i = parents.size() - 1; i >= 0; i--)
+ for(long i = (long)parents.size() - 1; i >= 0; i--)
{
logger.debug(" %d", parents[i]);
}
logger.debug(".\n");
- for(i = parents.size() - 1; i >= 0; i--)
+ for(long i = (long)parents.size() - 1; i >= 0; i--)
{
pid_t pid = parents[i];
HANDLE proc = OpenProcess(PROCESS_TERMINATE, 0, pid);
=== modified file 'storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp'
--- a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp 2009-11-02 17:15:29 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp 2009-12-04 12:45:23 +0000
@@ -69,6 +69,7 @@
// Error Codes for Add Table
// --------------------------------------
#define ZREPLERROR1 306
+#define ZREPLERROR2 307
// --------------------------------------
// Crash Codes
=== modified file 'storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp 2009-11-05 21:14:04 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp 2009-12-04 12:45:23 +0000
@@ -7541,7 +7541,7 @@ void Dbdih::execDIADDTABREQ(Signal* sign
}//if
if (noFragments > cremainingfrags) {
jam();
- addtabrefuseLab(signal, connectPtr, ZREPLERROR1);
+ addtabrefuseLab(signal, connectPtr, ZREPLERROR2);
return;
}//if
=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2009-11-16 13:36:35 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2009-12-06 17:12:40 +0000
@@ -1183,12 +1183,12 @@ void Dblqh::execREAD_CONFIG_REQ(Signal*
if (!ndb_mgm_get_string_parameter(p, CFG_DB_INIT_REDO, &conf) && conf)
{
jam();
- if (strcmp(conf, "sparse") == 0)
+ if (strcasecmp(conf, "sparse") == 0)
{
jam();
m_use_om_init = 0;
}
- else if (strcmp(conf, "full") == 0)
+ else if (strcasecmp(conf, "full") == 0)
{
jam();
m_use_om_init = 1;
=== modified file 'storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.hpp'
--- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.hpp 2009-10-12 07:07:14 +0000
+++ b/storage/ndb/src/kernel/blocks/ndbfs/AsyncIoThread.hpp 2009-11-30 11:53:55 +0000
@@ -104,6 +104,8 @@ public:
// Information for open, needed if the first open action fails.
AsyncFile* file;
Uint32 theTrace;
+
+ MemoryChannel<Request>::ListMember m_mem_channel;
};
NdbOut& operator <<(NdbOut&, const Request&);
=== modified file 'storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp'
--- a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp 2009-11-30 11:53:55 +0000
@@ -78,20 +78,26 @@ template <class T>
class MemoryChannel
{
public:
- // wl4391_todo. adds 4*. could set per ndb version. why 512 ?
- MemoryChannel( int size= 4* 512);
- virtual ~MemoryChannel( );
+ MemoryChannel();
+ virtual ~MemoryChannel();
- void writeChannel( T *t);
- void writeChannelNoSignal( T *t);
+ void writeChannel(T *t);
+ void writeChannelNoSignal(T *t);
T* readChannel();
T* tryReadChannel();
+ /**
+ * Should be made class using MemoryChannel
+ */
+ struct ListMember
+ {
+ T* m_next;
+ };
+
private:
- int theSize;
- T **theChannel;
- CircularIndex theWriteIndex;
- CircularIndex theReadIndex;
+ Uint32 m_occupancy;
+ T* m_head; // First element in list (e.g will be read by readChannel)
+ T* m_tail;
NdbMutex* theMutexPtr;
NdbCondition* theConditionPtr;
@@ -103,18 +109,14 @@ template <class T>
NdbOut& operator<<(NdbOut& out, const MemoryChannel<T> & chn)
{
NdbMutex_Lock(chn.theMutexPtr);
- out << "[ theSize: " << chn.theSize
- << " theReadIndex: " << (int)chn.theReadIndex
- << " theWriteIndex: " << (int)chn.theWriteIndex << " ]";
+ out << "[ occupancy: " << chn.m_occupancy
+ << " ]";
NdbMutex_Unlock(chn.theMutexPtr);
return out;
}
-template <class T> MemoryChannel<T>::MemoryChannel( int size):
- theSize(size),
- theChannel(new T*[size] ),
- theWriteIndex(0, size),
- theReadIndex(0, size)
+template <class T> MemoryChannel<T>::MemoryChannel() :
+ m_occupancy(0), m_head(0), m_tail(0)
{
theMutexPtr = NdbMutex_Create();
theConditionPtr = NdbCondition_Create();
@@ -124,55 +126,79 @@ template <class T> MemoryChannel<T>::~Me
{
NdbMutex_Destroy(theMutexPtr);
NdbCondition_Destroy(theConditionPtr);
- delete [] theChannel;
}
template <class T> void MemoryChannel<T>::writeChannel( T *t)
{
-
- NdbMutex_Lock(theMutexPtr);
- if(full(theWriteIndex, theReadIndex) || theChannel == NULL) abort();
- theChannel[theWriteIndex]= t;
- ++theWriteIndex;
+ writeChannelNoSignal(t);
NdbCondition_Signal(theConditionPtr);
- NdbMutex_Unlock(theMutexPtr);
}
template <class T> void MemoryChannel<T>::writeChannelNoSignal( T *t)
{
-
NdbMutex_Lock(theMutexPtr);
- if(full(theWriteIndex, theReadIndex) || theChannel == NULL) abort();
- theChannel[theWriteIndex]= t;
- ++theWriteIndex;
+ if (m_head == 0)
+ {
+ assert(m_occupancy == 0);
+ m_head = m_tail = t;
+ }
+ else
+ {
+ assert(m_tail != 0);
+ m_tail->m_mem_channel.m_next = t;
+ m_tail = t;
+ }
+ t->m_mem_channel.m_next = 0;
+ m_occupancy++;
NdbMutex_Unlock(theMutexPtr);
}
template <class T> T* MemoryChannel<T>::readChannel()
{
- T* tmp;
-
NdbMutex_Lock(theMutexPtr);
- while ( empty(theWriteIndex, theReadIndex) )
+ while (m_head == 0)
{
+ assert(m_occupancy == 0);
NdbCondition_Wait(theConditionPtr,
- theMutexPtr);
+ theMutexPtr);
}
-
- tmp= theChannel[theReadIndex];
- ++theReadIndex;
+ assert(m_occupancy > 0);
+ T* tmp = m_head;
+ if (m_head == m_tail)
+ {
+ assert(m_occupancy == 1);
+ m_head = m_tail = 0;
+ }
+ else
+ {
+ m_head = m_head->m_mem_channel.m_next;
+ }
+ m_occupancy--;
NdbMutex_Unlock(theMutexPtr);
return tmp;
}
template <class T> T* MemoryChannel<T>::tryReadChannel()
{
- T* tmp= 0;
NdbMutex_Lock(theMutexPtr);
- if ( !empty(theWriteIndex, theReadIndex) )
- {
- tmp= theChannel[theReadIndex];
- ++theReadIndex;
+ T* tmp = m_head;
+ if (m_head != 0)
+ {
+ assert(m_occupancy > 0);
+ if (m_head == m_tail)
+ {
+ assert(m_occupancy == 1);
+ m_head = m_tail = 0;
+ }
+ else
+ {
+ m_head = m_head->m_mem_channel.m_next;
+ }
+ m_occupancy--;
+ }
+ else
+ {
+ assert(m_occupancy == 0);
}
NdbMutex_Unlock(theMutexPtr);
return tmp;
=== modified file 'storage/ndb/src/kernel/blocks/pgman.cpp'
--- a/storage/ndb/src/kernel/blocks/pgman.cpp 2009-10-09 11:15:22 +0000
+++ b/storage/ndb/src/kernel/blocks/pgman.cpp 2009-11-27 10:26:10 +0000
@@ -50,6 +50,10 @@ Pgman::Pgman(Block_context& ctx, Uint32
m_page_hashlist(m_page_entry_pool),
m_page_stack(m_page_entry_pool),
m_page_queue(m_page_entry_pool)
+#ifdef VM_TRACE
+ ,debugFlag(false)
+ ,debugSummaryFlag(false)
+#endif
{
BLOCK_CONSTRUCTOR(Pgman);
@@ -150,6 +154,7 @@ Pgman::execREAD_CONFIG_REQ(Signal* signa
m_param.m_max_pages = page_cnt;
m_page_entry_pool.setSize(m_param.m_lirs_stack_mult * page_cnt);
m_param.m_max_hot_pages = (page_cnt * 9) / 10;
+ ndbrequire(m_param.m_max_hot_pages >= 1);
}
Pool_context pc;
@@ -177,9 +182,10 @@ Pgman::Param::Param() :
Pgman::Stats::Stats() :
m_num_pages(0),
+ m_num_hot_pages(0),
+ m_current_io_waits(0),
m_page_hits(0),
- m_page_faults(0),
- m_current_io_waits(0)
+ m_page_faults(0)
{
}
@@ -313,10 +319,6 @@ Pgman::Page_entry::Page_entry(Uint32 fil
Uint32
Pgman::get_sublist_no(Page_state state)
{
- if (state == 0)
- {
- return ZNIL;
- }
if (state & Page_entry::REQUEST)
{
if (! (state & Page_entry::BOUND))
@@ -348,7 +350,11 @@ Pgman::get_sublist_no(Page_state state)
if (state == Page_entry::ONSTACK) {
return Page_entry::SL_IDLE;
}
- return Page_entry::SL_OTHER;
+ if (state != 0)
+ {
+ return Page_entry::SL_OTHER;
+ }
+ return ZNIL;
}
void
@@ -381,9 +387,26 @@ Pgman::set_page_state(Ptr<Page_entry> pt
}
}
ptr.p->m_state = new_state;
+
+ bool old_hot = (old_state & Page_entry::HOT);
+ bool new_hot = (new_state & Page_entry::HOT);
+ if (! old_hot && new_hot)
+ {
+ jam();
+ m_stats.m_num_hot_pages++;
+ }
+ if (old_hot && ! new_hot)
+ {
+ jam();
+ ndbrequire(m_stats.m_num_hot_pages != 0);
+ m_stats.m_num_hot_pages--;
+ }
}
D(ptr << ": after");
+#ifdef VM_TRACE
+ verify_page_entry(ptr);
+#endif
D("<set_page_state");
}
@@ -641,8 +664,10 @@ Pgman::lirs_reference(Ptr<Page_entry> pt
Page_state state = ptr.p->m_state;
ndbrequire(! (state & Page_entry::LOCKED));
- // even non-LIRS cache pages are counted on l.h.s.
- if (m_stats.m_num_pages >= m_param.m_max_hot_pages)
+ ndbrequire(m_stats.m_num_hot_pages <= m_param.m_max_hot_pages);
+
+ // LIRS kicks in when we have max hot pages
+ if (m_stats.m_num_hot_pages == m_param.m_max_hot_pages)
{
if (state & Page_entry::HOT)
{
@@ -684,6 +709,12 @@ Pgman::lirs_reference(Ptr<Page_entry> pt
jam();
pl_stack.add(ptr);
state |= Page_entry::ONSTACK;
+ /*
+ * bug#48910. Using hot page count (not total page count)
+ * guarantees that stack is not empty here. Therefore the new
+ * entry (added to top) is not at bottom and need not be hot.
+ */
+ ndbrequire(pl_stack.hasPrev(ptr));
if (state & Page_entry::ONQUEUE)
{
jam();
@@ -706,7 +737,8 @@ Pgman::lirs_reference(Ptr<Page_entry> pt
}
else
{
- D("hot: " << m_stats.m_num_pages << " of " << m_param.m_max_hot_pages);
+ D("filling up hot pages: " << m_stats.m_num_hot_pages << "/"
+ << m_param.m_max_hot_pages);
jam();
if (state & Page_entry::ONSTACK)
{
@@ -1005,11 +1037,11 @@ Pgman::process_callback(Signal* signal,
{
D(ptr << " : process_callback");
int max_count = 1;
- Page_state state = ptr.p->m_state;
while (! ptr.p->m_requests.isEmpty() && --max_count >= 0)
{
jam();
+ Page_state state = ptr.p->m_state;
SimulatedBlock* b;
Callback callback;
{
@@ -1051,19 +1083,18 @@ Pgman::process_callback(Signal* signal,
}
ndbrequire(state & Page_entry::BOUND);
ndbrequire(state & Page_entry::MAPPED);
+
+ // make REQUEST state consistent before set_page_state()
+ if (ptr.p->m_requests.isEmpty())
+ {
+ jam();
+ state &= ~ Page_entry::REQUEST;
+ }
// callback may re-enter PGMAN and change page state
set_page_state(ptr, state);
b->execute(signal, callback, ptr.p->m_real_page_i);
- state = ptr.p->m_state;
}
-
- if (ptr.p->m_requests.isEmpty())
- {
- jam();
- state &= ~ Page_entry::REQUEST;
- }
- set_page_state(ptr, state);
return true;
}
@@ -1608,7 +1639,7 @@ Pgman::execFSWRITEREF(Signal* signal)
// client methods
int
-Pgman::get_page(Signal* signal, Ptr<Page_entry> ptr, Page_request page_req)
+Pgman::get_page_no_lirs(Signal* signal, Ptr<Page_entry> ptr, Page_request page_req)
{
jamEntry();
Ptr<Page_request> tmp = { &page_req, RNIL};
@@ -1649,16 +1680,6 @@ Pgman::get_page(Signal* signal, Ptr<Page
jam();
}
- // update LIRS
- if (! (state & Page_entry::LOCKED) &&
- ! (req_flags & Page_request::CORR_REQ))
- {
- jam();
- set_page_state(ptr, state);
- lirs_reference(ptr);
- state = ptr.p->m_state;
- }
-
const Page_state LOCKED = Page_entry::LOCKED | Page_entry::MAPPED;
if ((state & LOCKED) == LOCKED &&
! (req_flags & Page_request::UNLOCK_PAGE))
@@ -1746,14 +1767,43 @@ Pgman::get_page(Signal* signal, Ptr<Page
ptr.p->m_busy_count += busy_count;
ptr.p->m_dirty_count += !!(req_flags & DIRTY_FLAGS);
set_page_state(ptr, state);
-
- do_busy_loop(signal, true);
D(req_ptr);
D("<get_page: queued");
return 0;
}
+int
+Pgman::get_page(Signal* signal, Ptr<Page_entry> ptr, Page_request page_req)
+{
+ int i = get_page_no_lirs(signal, ptr, page_req);
+ if (unlikely(i == -1))
+ {
+ jam();
+ return -1;
+ }
+
+ Uint32 req_flags = page_req.m_flags;
+ Page_state state = ptr.p->m_state;
+
+ // update LIRS
+ if (! (state & Page_entry::LOCKED) &&
+ ! (req_flags & Page_request::CORR_REQ))
+ {
+ jam();
+ lirs_reference(ptr);
+ }
+
+ // start processing if request was queued
+ if (i == 0)
+ {
+ jam();
+ do_busy_loop(signal, true);
+ }
+
+ return i;
+}
+
void
Pgman::update_lsn(Ptr<Page_entry> ptr, Uint32 block, Uint64 lsn)
{
@@ -1910,9 +1960,6 @@ Pgman::drop_page(Ptr<Page_entry> ptr)
Page_state state = ptr.p->m_state;
if (! (state & (Page_entry::PAGEIN | Page_entry::PAGEOUT)))
{
- ndbrequire(state & Page_entry::BOUND);
- ndbrequire(state & Page_entry::MAPPED);
-
if (state & Page_entry::ONSTACK)
{
jam();
@@ -1922,9 +1969,13 @@ Pgman::drop_page(Ptr<Page_entry> ptr)
if (at_bottom)
{
jam();
- ndbassert(state & Page_entry::HOT);
lirs_stack_prune();
}
+ if (state & Page_entry::HOT)
+ {
+ jam();
+ state &= ~ Page_entry::HOT;
+ }
}
if (state & Page_entry::ONQUEUE)
@@ -1934,12 +1985,37 @@ Pgman::drop_page(Ptr<Page_entry> ptr)
state &= ~ Page_entry::ONQUEUE;
}
- ndbassert(ptr.p->m_real_page_i != RNIL);
- if (ptr.p->m_real_page_i != RNIL)
+ if (state & Page_entry::BUSY)
{
jam();
+ state &= ~ Page_entry::BUSY;
+ }
+
+ if (state & Page_entry::DIRTY)
+ {
+ jam();
+ state &= ~ Page_entry::DIRTY;
+ }
+
+ if (state & Page_entry::EMPTY)
+ {
+ jam();
+ state &= ~ Page_entry::EMPTY;
+ }
+
+ if (state & Page_entry::MAPPED)
+ {
+ jam();
+ state &= ~ Page_entry::MAPPED;
+ }
+
+ if (state & Page_entry::BOUND)
+ {
+ jam();
+ ndbrequire(ptr.p->m_real_page_i != RNIL);
release_cache_page(ptr.p->m_real_page_i);
ptr.p->m_real_page_i = RNIL;
+ state &= ~ Page_entry::BOUND;
}
set_page_state(ptr, state);
@@ -2152,6 +2228,8 @@ Page_cache_client::free_data_file(Signal
void
Pgman::verify_page_entry(Ptr<Page_entry> ptr)
{
+ Page_stack& pl_stack = m_page_stack;
+
Uint32 ptrI = ptr.i;
Page_state state = ptr.p->m_state;
@@ -2174,6 +2252,10 @@ Pgman::verify_page_entry(Ptr<Page_entry>
// hot entry must be on stack
ndbrequire(! is_hot || on_stack || dump_page_lists(ptrI));
+ // stack bottom is hot
+ bool at_bottom = on_stack && ! pl_stack.hasPrev(ptr);
+ ndbrequire(! at_bottom || is_hot || dump_page_lists(ptrI));
+
bool on_queue = state & Page_entry::ONQUEUE;
// hot entry is not on queue
ndbrequire(! is_hot || ! on_queue || dump_page_lists(ptrI));
@@ -2185,9 +2267,12 @@ Pgman::verify_page_entry(Ptr<Page_entry>
// entries waiting to enter queue
bool to_queue = ! is_locked && ! is_hot && ! is_bound && has_req;
- // page is either LOCKED or under LIRS
+ // page is about to be released
+ bool to_release = (state == 0);
+
+ // page is either LOCKED or under LIRS or about to be released
bool is_lirs = on_stack || to_queue || on_queue;
- ndbrequire(is_locked == ! is_lirs || dump_page_lists(ptrI));
+ ndbrequire(to_release || is_locked == ! is_lirs || dump_page_lists(ptrI));
bool pagein = state & Page_entry::PAGEIN;
bool pageout = state & Page_entry::PAGEOUT;
@@ -2219,6 +2304,9 @@ Pgman::verify_page_entry(Ptr<Page_entry>
break;
case Page_entry::SL_OTHER:
break;
+ case ZNIL:
+ ndbrequire(to_release || dump_page_lists(ptrI));
+ break;
default:
ndbrequire(false || dump_page_lists(ptrI));
break;
@@ -2228,124 +2316,114 @@ Pgman::verify_page_entry(Ptr<Page_entry>
void
Pgman::verify_page_lists()
{
+ const Stats& stats = m_stats;
+ const Param& param = m_param;
Page_hashlist& pl_hash = m_page_hashlist;
Page_stack& pl_stack = m_page_stack;
Page_queue& pl_queue = m_page_queue;
Ptr<Page_entry> ptr;
- Uint32 stack_count = 0;
- Uint32 queue_count = 0;
- Uint32 queuewait_count = 0;
- Uint32 locked_bound_count = 0;
+ Uint32 is_locked = 0;
+ Uint32 is_bound = 0;
+ Uint32 is_mapped = 0;
+ Uint32 is_hot = 0;
+ Uint32 on_stack = 0;
+ Uint32 on_queue = 0;
+ Uint32 to_queue = 0;
Page_hashlist::Iterator iter;
pl_hash.next(0, iter);
while (iter.curr.i != RNIL)
{
- verify_page_entry(iter.curr);
+ ptr = iter.curr;
+ Page_state state = ptr.p->m_state;
+ // (state == 0) occurs only within a time-slice
+ ndbrequire(state != 0);
+ verify_page_entry(ptr);
- Page_state state = iter.curr.p->m_state;
+ if (state & Page_entry::LOCKED)
+ is_locked++;
+ if (state & Page_entry::BOUND)
+ is_bound++;
+ if (state & Page_entry::MAPPED)
+ is_mapped++;
+ if (state & Page_entry::HOT)
+ is_hot++;
if (state & Page_entry::ONSTACK)
- stack_count++;
+ on_stack++;
if (state & Page_entry::ONQUEUE)
- queue_count++;
+ on_queue++;
if (! (state & Page_entry::LOCKED) &&
! (state & Page_entry::HOT) &&
(state & Page_entry::REQUEST) &&
! (state & Page_entry::BOUND))
- queuewait_count++;
- if (state & Page_entry::LOCKED &&
- state & Page_entry::BOUND)
- locked_bound_count++;
+ to_queue++;
pl_hash.next(iter);
}
- ndbrequire(stack_count == pl_stack.count() || dump_page_lists());
- ndbrequire(queue_count == pl_queue.count() || dump_page_lists());
-
- Uint32 hot_count = 0;
- Uint32 hot_bound_count = 0;
- Uint32 cold_bound_count = 0;
- Uint32 stack_request_count = 0;
- Uint32 queue_request_count = 0;
-
- Uint32 i1 = RNIL;
for (pl_stack.first(ptr); ptr.i != RNIL; pl_stack.next(ptr))
{
- ndbrequire(i1 != ptr.i);
- i1 = ptr.i;
Page_state state = ptr.p->m_state;
- ndbrequire(state & Page_entry::ONSTACK || dump_page_lists());
+ ndbrequire(state & Page_entry::ONSTACK || dump_page_lists(ptr.i));
if (! pl_stack.hasPrev(ptr))
- ndbrequire(state & Page_entry::HOT || dump_page_lists());
- if (state & Page_entry::HOT) {
- hot_count++;
- if (state & Page_entry::BOUND)
- hot_bound_count++;
- }
- if (state & Page_entry::REQUEST)
- stack_request_count++;
+ ndbrequire(state & Page_entry::HOT || dump_page_lists(ptr.i));
}
- Uint32 i2 = RNIL;
for (pl_queue.first(ptr); ptr.i != RNIL; pl_queue.next(ptr))
{
- ndbrequire(i2 != ptr.i);
- i2 = ptr.i;
Page_state state = ptr.p->m_state;
- ndbrequire(state & Page_entry::ONQUEUE || dump_page_lists());
- ndbrequire(state & Page_entry::BOUND || dump_page_lists());
- cold_bound_count++;
- if (state & Page_entry::REQUEST)
- queue_request_count++;
+ ndbrequire(state & Page_entry::ONQUEUE || dump_page_lists(ptr.i));
+ ndbrequire(state & Page_entry::BOUND || dump_page_lists(ptr.i));
+ ndbrequire(! (state & Page_entry::HOT) || dump_page_lists(ptr.i));
}
- Uint32 tot_bound_count =
- locked_bound_count + hot_bound_count + cold_bound_count;
- ndbrequire(m_stats.m_num_pages == tot_bound_count || dump_page_lists());
+ ndbrequire(is_bound == stats.m_num_pages || dump_page_lists());
+ ndbrequire(is_hot == stats.m_num_hot_pages || dump_page_lists());
+ ndbrequire(on_stack == pl_stack.count() || dump_page_lists());
+ ndbrequire(on_queue == pl_queue.count() || dump_page_lists());
Uint32 k;
Uint32 entry_count = 0;
-
+ char sublist_info[200] = "";
for (k = 0; k < Page_entry::SUBLIST_COUNT; k++)
{
const Page_sublist& pl = *m_page_sublist[k];
for (pl.first(ptr); ptr.i != RNIL; pl.next(ptr))
- {
- ndbrequire(get_sublist_no(ptr.p->m_state) == k || dump_page_lists());
- entry_count++;
- }
+ ndbrequire(get_sublist_no(ptr.p->m_state) == k || dump_page_lists(ptr.i));
+ entry_count += pl.count();
+ sprintf(sublist_info + strlen(sublist_info),
+ " %s:%u", get_sublist_name(k), pl.count());
}
-
ndbrequire(entry_count == pl_hash.count() || dump_page_lists());
+ Uint32 hit_pct = 0;
+ char hit_pct_str[20];
+ if (stats.m_page_hits + stats.m_page_faults != 0)
+ hit_pct = 10000 * stats.m_page_hits /
+ (stats.m_page_hits + stats.m_page_faults);
+ sprintf(hit_pct_str, "%u.%02u", hit_pct / 100, hit_pct % 100);
+
D("loop"
- << " stats=" << m_stats_loop_on
- << " busy=" << m_busy_loop_on
- << " cleanup=" << m_cleanup_loop_on
- << " lcp=" << m_lcp_loop_on);
-
- D("stat"
- << " entry:" << pl_hash.count()
- << " cache:" << m_stats.m_num_pages
- << "(" << locked_bound_count << "L)"
+ << " stats:" << m_stats_loop_on
+ << " busy:" << m_busy_loop_on
+ << " cleanup:" << m_cleanup_loop_on
+ << " lcp:" << m_lcp_loop_on);
+
+ D("page"
+ << " entries:" << pl_hash.count()
+ << " pages:" << stats.m_num_pages << "/" << param.m_max_pages
+ << " mapped:" << is_mapped
+ << " hot:" << is_hot
+ << " io:" << stats.m_current_io_waits << "/" << param.m_max_io_waits
+ << " hit pct:" << hit_pct_str);
+
+ D("list"
+ << " locked:" << is_locked
<< " stack:" << pl_stack.count()
- << " hot:" << hot_count
- << " hot_bound:" << hot_bound_count
- << " stack_request:" << stack_request_count
<< " queue:" << pl_queue.count()
- << " queue_request:" << queue_request_count
- << " queuewait:" << queuewait_count);
+ << " to queue:" << to_queue);
- char countbuf[200];
- countbuf[0] = 0;
- for (k = 0; k < Page_entry::SUBLIST_COUNT; k++)
- {
- const Page_sublist& pl = *m_page_sublist[k];
- sprintf(countbuf + strlen(countbuf), " %s:%u",
- get_sublist_name(k), pl.count());
- }
- D("list" << countbuf);
+ D(sublist_info);
}
void
@@ -2368,54 +2446,35 @@ Pgman::dump_page_lists(Uint32 ptrI)
// use debugOut directly
debugOut << "PGMAN: page list dump" << endl;
if (ptrI != RNIL)
- debugOut << "PGMAN: error on PE [" << ptrI << "]" << endl;
+ debugOut << "PGMAN: error on PE [" << ptrI << "]" << "\n";
Page_hashlist& pl_hash = m_page_hashlist;
Page_stack& pl_stack = m_page_stack;
Page_queue& pl_queue = m_page_queue;
Ptr<Page_entry> ptr;
Uint32 n;
- char buf[40];
- debugOut << "hash:" << endl;
- Page_hashlist::Iterator iter;
- pl_hash.next(0, iter);
- n = 0;
- while (iter.curr.i != RNIL)
- {
- sprintf(buf, "%03d", n++);
- debugOut << buf << " " << iter.curr << endl;
- pl_hash.next(iter);
- }
-
- debugOut << "stack:" << endl;
+ debugOut << "stack:" << "\n";
n = 0;
for (pl_stack.first(ptr); ptr.i != RNIL; pl_stack.next(ptr))
- {
- sprintf(buf, "%03d", n++);
- debugOut << buf << " " << ptr << endl;
- }
+ debugOut << n++ << " " << ptr << "\n";
- debugOut << "queue:" << endl;
+ debugOut << "queue:" << "\n";
n = 0;
for (pl_queue.first(ptr); ptr.i != RNIL; pl_queue.next(ptr))
- {
- sprintf(buf, "%03d", n++);
- debugOut << buf << " " << ptr << endl;
- }
+ debugOut << n++ << " " << ptr << "\n";
Uint32 k;
for (k = 0; k < Page_entry::SUBLIST_COUNT; k++)
{
- debugOut << get_sublist_name(k) << ":" << endl;
+ debugOut << get_sublist_name(k) << ":" << "\n";
const Page_sublist& pl = *m_page_sublist[k];
+ n = 0;
for (pl.first(ptr); ptr.i != RNIL; pl.next(ptr))
- {
- sprintf(buf, "%03d", n++);
- debugOut << buf << " " << ptr << endl;
- }
+ debugOut << n++ << " " << ptr << "\n";
}
+ debugOut.flushline();
return false;
}
@@ -2432,9 +2491,9 @@ Pgman::get_sublist_name(Uint32 list_no)
case Page_entry::SL_MAP_IO:
return "map_io";
case Page_entry::SL_CALLBACK:
- return "callback";
+ return "cb";
case Page_entry::SL_CALLBACK_IO:
- return "callback_io";
+ return "cb_io";
case Page_entry::SL_BUSY:
return "busy";
case Page_entry::SL_LOCKED:
@@ -2580,6 +2639,15 @@ Pgman::execDUMP_STATE_ORD(Signal* signal
{
jamEntry();
Page_hashlist& pl_hash = m_page_hashlist;
+#ifdef VM_TRACE
+ if (signal->theData[0] == 11000 && signal->getLength() == 2)
+ {
+ // has no effect currently
+ Uint32 flag = signal->theData[1];
+ debugFlag = flag & 1;
+ debugSummaryFlag = flag & 2;
+ }
+#endif
if (signal->theData[0] == 11001)
{
=== modified file 'storage/ndb/src/kernel/blocks/pgman.hpp'
--- a/storage/ndb/src/kernel/blocks/pgman.hpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/kernel/blocks/pgman.hpp 2009-11-27 09:22:07 +0000
@@ -54,7 +54,7 @@
* Updating a resident cache page makes it "dirty". A background
* clean-up process makes dirty pages "clean" via "pageout" to disk.
* Write ahead logging (WAL) of the page is done first i.e. UNDO log is
- * flushed up to the page log sequence number (LSN) by calling a TSMAN
+ * flushed up to the page log sequence number (LSN) by calling a LGMAN
* method. The reason for this is obvious but not relevant to PGMAN.
*
* A local check point (LCP) periodically performs a complete pageout of
@@ -420,9 +420,10 @@ private:
struct Stats {
Stats();
Uint32 m_num_pages; // current number of cache pages
- Uint32 m_page_hits;
- Uint32 m_page_faults;
+ Uint32 m_num_hot_pages;
Uint32 m_current_io_waits;
+ Uint64 m_page_hits;
+ Uint64 m_page_faults;
} m_stats;
enum CallbackIndex {
@@ -495,6 +496,7 @@ private:
void fswritereq(Signal*, Ptr<Page_entry>);
void fswriteconf(Signal*, Ptr<Page_entry>);
+ int get_page_no_lirs(Signal*, Ptr<Page_entry>, Page_request page_req);
int get_page(Signal*, Ptr<Page_entry>, Page_request page_req);
void update_lsn(Ptr<Page_entry>, Uint32 block, Uint64 lsn);
Uint32 create_data_file();
@@ -504,6 +506,8 @@ private:
int drop_page(Ptr<Page_entry>);
#ifdef VM_TRACE
+ bool debugFlag; // not yet in use in 7.0
+ bool debugSummaryFlag; // loop summary to signal log even if ! debugFlag
void verify_page_entry(Ptr<Page_entry> ptr);
void verify_page_lists();
void verify_all();
=== modified file 'storage/ndb/src/kernel/vm/Configuration.cpp'
--- a/storage/ndb/src/kernel/vm/Configuration.cpp 2009-11-09 13:29:20 +0000
+++ b/storage/ndb/src/kernel/vm/Configuration.cpp 2009-12-04 12:45:23 +0000
@@ -788,23 +788,14 @@ Configuration::calcSizeAlt(ConfigValues
cfg.put(CFG_DIH_API_CONNECT,
2 * noOfTransactions);
- Uint32 noFragPerTable= ((noOfDBNodes + NO_OF_FRAGS_PER_CHUNK - 1) >>
- LOG_NO_OF_FRAGS_PER_CHUNK) <<
- LOG_NO_OF_FRAGS_PER_CHUNK;
+ Uint32 noFragPerTable= (((noOfDBNodes * lqhInstances) +
+ NO_OF_FRAGS_PER_CHUNK - 1) >>
+ LOG_NO_OF_FRAGS_PER_CHUNK) <<
+ LOG_NO_OF_FRAGS_PER_CHUNK;
cfg.put(CFG_DIH_FRAG_CONNECT,
noFragPerTable * noOfMetaTables);
- int temp;
- temp = noOfReplicas - 2;
- if (temp < 0)
- temp = 1;
- else
- temp++;
- cfg.put(CFG_DIH_MORE_NODES,
- temp * NO_OF_FRAG_PER_NODE *
- noOfMetaTables * noOfDBNodes);
-
cfg.put(CFG_DIH_REPLICAS,
NO_OF_FRAG_PER_NODE * noOfMetaTables *
noOfDBNodes * noOfReplicas * lqhInstances);
=== modified file 'storage/ndb/src/kernel/vm/DynArr256.cpp'
--- a/storage/ndb/src/kernel/vm/DynArr256.cpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/kernel/vm/DynArr256.cpp 2009-12-04 05:53:03 +0000
@@ -47,7 +47,8 @@ struct DA256Page
struct DA256Node m_nodes[30];
};
-#define require(x) require_impl(x, __LINE__)
+#undef require
+#define require(x) require_exit_or_core_with_printer((x), 0, ndbout_printer)
//#define DA256_USE_PX
//#define DA256_USE_PREFETCH
#define DA256_EXTRA_SAFE
=== modified file 'storage/ndb/src/kernel/vm/SimulatedBlock.cpp'
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp 2009-11-16 13:36:35 +0000
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp 2009-12-06 17:12:40 +0000
@@ -335,6 +335,38 @@ SimulatedBlock::handle_invalid_fragmentI
#endif
}
+void
+SimulatedBlock::handle_out_of_longsignal_memory(Signal * signal) const
+{
+ ErrorReporter::handleError(NDBD_EXIT_OUT_OF_LONG_SIGNAL_MEMORY,
+ "Out of LongMessageBuffer in sendSignal",
+ "");
+}
+
+void
+SimulatedBlock::handle_send_failed(SendStatus ss, Signal * signal) const
+{
+ switch(ss){
+ case SEND_BUFFER_FULL:
+ ErrorReporter::handleError(NDBD_EXIT_GENERIC,
+ "Out of SendBufferMemory in sendSignal", "");
+ break;
+ case SEND_MESSAGE_TOO_BIG:
+ ErrorReporter::handleError(NDBD_EXIT_NDBREQUIRE,
+ "Message to big in sendSignal", "");
+ break;
+ case SEND_UNKNOWN_NODE:
+ ErrorReporter::handleError(NDBD_EXIT_NDBREQUIRE,
+ "Unknown node in sendSignal", "");
+ break;
+ case SEND_OK:
+ case SEND_BLOCKED:
+ case SEND_DISCONNECTED:
+ break;
+ }
+ ndbrequire(false);
+}
+
static void
linkSegments(Uint32 head, Uint32 tail){
@@ -522,18 +554,13 @@ SimulatedBlock::sendSignal(BlockReferenc
&signal->theData[0], recNode,
(LinearSectionPtr*)0);
#endif
-/* if(!(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED)){
- * ndbout << "Failed to send signal no " << gsn
- * << " sender blockNumber=" << refToMain(sendBRef)
- * << " sender Nodeno=" << refToNode(sendBRef)
- * << " sender instanceNo=" << refToInstance(sendBRef)
- * << " blockNumber=" << refToMain(ref)
- * << " Nodeno=" << refToNode(ref)
- * << " instanceNo=" << refToInstance(ref) << endl;
- * ndbout.flushline();
- * }
- */
- ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
+
+ if (unlikely(! (ss == SEND_OK ||
+ ss == SEND_BLOCKED ||
+ ss == SEND_DISCONNECTED)))
+ {
+ handle_send_failed(ss, signal);
+ }
}
return;
}
@@ -635,7 +662,12 @@ SimulatedBlock::sendSignal(NodeReceiverG
(LinearSectionPtr*)0);
#endif
- ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
+ if (unlikely(! (ss == SEND_OK ||
+ ss == SEND_BLOCKED ||
+ ss == SEND_DISCONNECTED)))
+ {
+ handle_send_failed(ss, signal);
+ }
}
return;
@@ -692,11 +724,17 @@ SimulatedBlock::sendSignal(BlockReferenc
/**
* We have to copy the data
*/
+ bool ok = true;
Ptr<SectionSegment> segptr[3];
for(Uint32 i = 0; i<noOfSections; i++){
- ndbrequire(::import(SB_SP_ARG segptr[i], ptr[i].p, ptr[i].sz));
+ ok &= ::import(SB_SP_ARG segptr[i], ptr[i].p, ptr[i].sz);
signal->theData[length+i] = segptr[i].i;
}
+
+ if (unlikely(! ok))
+ {
+ handle_out_of_longsignal_memory(signal);
+ }
#ifdef NDBD_MULTITHREADED
if (jobBuffer == JBB)
@@ -743,7 +781,12 @@ SimulatedBlock::sendSignal(BlockReferenc
ptr);
#endif
- ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
+ if (unlikely(! (ss == SEND_OK ||
+ ss == SEND_BLOCKED ||
+ ss == SEND_DISCONNECTED)))
+ {
+ handle_send_failed(ss, signal);
+ }
}
signal->header.m_noOfSections = 0;
@@ -807,12 +850,18 @@ SimulatedBlock::sendSignal(NodeReceiverG
/**
* We have to copy the data
*/
+ bool ok = true;
Ptr<SectionSegment> segptr[3];
for(Uint32 i = 0; i<noOfSections; i++){
- ndbrequire(::import(SB_SP_ARG segptr[i], ptr[i].p, ptr[i].sz));
+ ok &= ::import(SB_SP_ARG segptr[i], ptr[i].p, ptr[i].sz);
signal->theData[length+i] = segptr[i].i;
}
+ if (unlikely(! ok))
+ {
+ handle_out_of_longsignal_memory(signal);
+ }
+
#ifdef NDBD_MULTITHREADED
if (jobBuffer == JBB)
sendlocal(m_threadId, &signal->header, signal->theData,
@@ -862,7 +911,12 @@ SimulatedBlock::sendSignal(NodeReceiverG
ptr);
#endif
- ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
+ if (unlikely(! (ss == SEND_OK ||
+ ss == SEND_BLOCKED ||
+ ss == SEND_DISCONNECTED)))
+ {
+ handle_send_failed(ss, signal);
+ }
}
signal->header.m_noOfSections = 0;
@@ -967,7 +1021,13 @@ SimulatedBlock::sendSignal(BlockReferenc
sections->m_ptr);
#endif
- ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
+ if (unlikely(! (ss == SEND_OK ||
+ ss == SEND_BLOCKED ||
+ ss == SEND_DISCONNECTED)))
+ {
+ handle_send_failed(ss, signal);
+ }
+
::releaseSections(SB_SP_ARG noOfSections, sections->m_ptr);
}
@@ -1090,7 +1150,12 @@ SimulatedBlock::sendSignal(NodeReceiverG
sections->m_ptr);
#endif
- ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
+ if (unlikely(! (ss == SEND_OK ||
+ ss == SEND_BLOCKED ||
+ ss == SEND_DISCONNECTED)))
+ {
+ handle_send_failed(ss, signal);
+ }
}
if (release)
@@ -2679,8 +2744,9 @@ SimulatedBlock::sendFirstFragment(Fragme
/* Store main signal data in a segment for sending later */
Ptr<SectionSegment> tmp;
- if(!import(tmp, &signal->theData[0], length)){
- ndbrequire(false);
+ if(!import(tmp, &signal->theData[0], length))
+ {
+ handle_out_of_longsignal_memory(0);
return false;
}
info.m_theDataSection.p = &tmp.p->theData[0];
@@ -3019,8 +3085,9 @@ SimulatedBlock::sendFirstFragment(Fragme
info.m_callback.m_callbackFunction = 0;
Ptr<SectionSegment> tmp;
- if(!import(tmp, &signal->theData[0], length)){
- ndbrequire(false);
+ if(unlikely(!import(tmp, &signal->theData[0], length)))
+ {
+ handle_out_of_longsignal_memory(0);
return false;
}
@@ -3739,7 +3806,10 @@ SimulatedBlock::sendRoutedSignal(RoutePa
handle.m_ptr[2] = handle.m_ptr[1];
handle.m_ptr[1] = handle.m_ptr[0];
Ptr<SectionSegment> tmp;
- ndbrequire(import(tmp, signal->theData, sigLen));
+ if (unlikely(! import(tmp, signal->theData, sigLen)))
+ {
+ handle_out_of_longsignal_memory(0);
+ }
handle.m_ptr[0].p = tmp.p;
handle.m_ptr[0].i = tmp.i;
handle.m_ptr[0].sz = sigLen;
=== modified file 'storage/ndb/src/kernel/vm/SimulatedBlock.hpp'
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp 2009-11-10 09:50:28 +0000
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp 2009-12-06 17:12:40 +0000
@@ -336,6 +336,8 @@ protected:
void handle_lingering_sections_after_execute(Signal*) const;
void handle_lingering_sections_after_execute(SectionHandle*) const;
void handle_invalid_fragmentInfo(Signal*) const;
+ void handle_send_failed(SendStatus, Signal*) const;
+ void handle_out_of_longsignal_memory(Signal*) const;
/**
* Send routed signals (ONLY LOCALLY)
=== modified file 'storage/ndb/src/kernel/vm/mt.cpp'
--- a/storage/ndb/src/kernel/vm/mt.cpp 2009-11-02 18:03:43 +0000
+++ b/storage/ndb/src/kernel/vm/mt.cpp 2009-12-06 17:12:40 +0000
@@ -259,14 +259,6 @@ wakeup(struct thr_wait* wait)
#endif
-static inline
-void
-require(bool x)
-{
- if (unlikely(!(x)))
- abort();
-}
-
#ifdef NDB_HAVE_XCNG
struct thr_spin_lock
{
=== modified file 'storage/ndb/src/mgmapi/mgmapi.cpp'
--- a/storage/ndb/src/mgmapi/mgmapi.cpp 2009-11-08 12:52:27 +0000
+++ b/storage/ndb/src/mgmapi/mgmapi.cpp 2009-12-02 16:01:50 +0000
@@ -40,6 +40,7 @@
#include <base64.h>
+//#define MGMAPI_LOG
#define MGM_CMD(name, fun, desc) \
{ name, \
0, \
@@ -1163,6 +1164,27 @@ ndb_mgm_stop2(NdbMgmHandle handle, int n
extern "C"
int
+ndb_mgm_obtain_mgmd_version(NdbMgmHandle handle)
+{
+ if (handle->mgmd_version_build == -1)
+ {
+ char verStr[64]; /* Long enough? */
+
+ if (!ndb_mgm_get_version(handle,
+ &(handle->mgmd_version_major),
+ &(handle->mgmd_version_minor),
+ &(handle->mgmd_version_build),
+ sizeof(verStr),
+ verStr))
+ {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+extern "C"
+int
ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
int abort, int *disconnect)
{
@@ -1184,19 +1206,11 @@ ndb_mgm_stop3(NdbMgmHandle handle, int n
CHECK_CONNECTED(handle, -1);
- if(handle->mgmd_version_build==-1)
+ if(ndb_mgm_obtain_mgmd_version(handle) == -1)
{
- char verstr[50];
- if(!ndb_mgm_get_version(handle,
- &(handle->mgmd_version_major),
- &(handle->mgmd_version_minor),
- &(handle->mgmd_version_build),
- sizeof(verstr),
- verstr))
- {
return -1;
- }
}
+
int use_v2= ((handle->mgmd_version_major==5)
&& (
(handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
@@ -2211,6 +2225,20 @@ ndb_mgm_start_backup3(NdbMgmHandle handl
unsigned int input_backupId,
unsigned int backuppoint)
{
+ /* Before we start the backup, first get the version of the
+ * management node we are connected to
+ */
+ if (ndb_mgm_obtain_mgmd_version(handle) == -1)
+ {
+ return -1;
+ }
+
+ Uint32 mgmdVersion = NDB_MAKE_VERSION(handle->mgmd_version_major,
+ handle->mgmd_version_minor,
+ handle->mgmd_version_build);
+
+ bool sendBackupPoint = (mgmdVersion >= MGMD_MGMAPI_PROTOCOL_CHANGE);
+
CHECK_HANDLE(handle, -1);
SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_backup");
const ParserRow<ParserDummy> start_backup_reply[] = {
@@ -2225,7 +2253,9 @@ ndb_mgm_start_backup3(NdbMgmHandle handl
args.put("completed", wait_completed);
if(input_backupId > 0)
args.put("backupid", input_backupId);
- args.put("backuppoint", backuppoint);
+ if (sendBackupPoint)
+ args.put("backuppoint", backuppoint);
+
const Properties *reply;
{ // start backup can take some time, set timeout high
int old_timeout= handle->timeout;
@@ -2308,13 +2338,30 @@ struct ndb_mgm_configuration *
ndb_mgm_get_configuration2(NdbMgmHandle handle, unsigned int version,
enum ndb_mgm_node_type nodetype)
{
+ /* Before we get the config, first get the version of the
+ * managment node we are connected to
+ */
+ if (ndb_mgm_obtain_mgmd_version(handle) == -1)
+ {
+ return NULL;
+ }
+
+ Uint32 mgmdVersion = NDB_MAKE_VERSION(handle->mgmd_version_major,
+ handle->mgmd_version_minor,
+ handle->mgmd_version_build);
+
+ bool getConfigUsingNodetype = (mgmdVersion >= MGMD_MGMAPI_PROTOCOL_CHANGE);
+
CHECK_HANDLE(handle, 0);
SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_configuration");
CHECK_CONNECTED(handle, 0);
Properties args;
args.put("version", version);
- args.put("nodetype", nodetype);
+ if (getConfigUsingNodetype)
+ {
+ args.put("nodetype", nodetype);
+ }
const ParserRow<ParserDummy> reply[] = {
MGM_CMD("get config reply", NULL, ""),
=== modified file 'storage/ndb/src/mgmsrv/CMakeLists.txt'
--- a/storage/ndb/src/mgmsrv/CMakeLists.txt 2009-11-13 04:50:47 +0000
+++ b/storage/ndb/src/mgmsrv/CMakeLists.txt 2009-11-17 18:13:57 +0000
@@ -45,3 +45,7 @@ ADD_EXECUTABLE(ndb_mgmd
TARGET_LINK_LIBRARIES(ndb_mgmd ndbconf)
INSTALL(TARGETS ndb_mgmd DESTINATION libexec)
+
+ADD_EXECUTABLE(MgmConfig-t
+ testConfig.cpp)
+TARGET_LINK_LIBRARIES(ndb_mgmd ndbconf)
=== modified file 'storage/ndb/src/mgmsrv/Config.cpp'
--- a/storage/ndb/src/mgmsrv/Config.cpp 2009-10-09 12:47:49 +0000
+++ b/storage/ndb/src/mgmsrv/Config.cpp 2009-12-03 05:53:33 +0000
@@ -24,12 +24,6 @@
#include <HashMap.hpp>
-static void require(bool b)
-{
- if (!b)
- abort();
-}
-
Config::Config(struct ndb_mgm_configuration *config_values) :
m_configValues(config_values)
{
@@ -824,3 +818,19 @@ Config::get_nodemask(NodeBitmask& mask,
}
}
+
+Uint32
+Config::checksum(void) const {
+ Uint32 chk;
+
+ UtilBuffer buf;
+ pack(buf);
+
+ // Checksum is the last 4 bytes in buffer
+ const char* chk_ptr = (const char*)buf.get_data();
+ chk_ptr += buf.length() - sizeof(Uint32);
+ chk = *(Uint32*) chk_ptr;
+
+ return chk;
+}
+
=== modified file 'storage/ndb/src/mgmsrv/Config.hpp'
--- a/storage/ndb/src/mgmsrv/Config.hpp 2009-09-25 07:57:29 +0000
+++ b/storage/ndb/src/mgmsrv/Config.hpp 2009-11-17 18:13:29 +0000
@@ -120,6 +120,14 @@ public:
bool equal(const Config*, const unsigned* exclude = NULL) const;
/*
+ Return the checksum of the config. The checksum can be used to compare
+ two configs without having the whole config available(for example on
+ a remote host). It can also be printed to log files for manual verification
+ that same config is used
+ */
+ Uint32 checksum(void) const;
+
+ /*
Return bitmask of all defined nodes of a certain type
returns all defined nodes by default.
*/
=== modified file 'storage/ndb/src/mgmsrv/ConfigInfo.cpp'
--- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp 2009-11-03 16:16:09 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp 2009-12-03 05:53:33 +0000
@@ -2789,21 +2789,8 @@ const int ConfigInfo::m_NoOfParams = siz
/****************************************************************************
* Ctor
****************************************************************************/
-static void
-_require(bool v, const char* expr, unsigned line)
-{
- if(!v)
- {
- fprintf(stderr, "require(%s) failed at %s:%d\n",
- expr, __FILE__, line);
- fflush(stderr);
- if (opt_core)
- abort();
- else
- exit(-1);
- }
-}
-#define require(x) _require(x, #x, __LINE__)
+#undef require
+#define require(x) require_exit_or_core(x, -1)
ConfigInfo::ConfigInfo()
: m_info(true), m_systemDefaults(true)
@@ -3860,21 +3847,21 @@ applyDefaultValues(InitConfigFileParser:
case ConfigInfo::CI_INT:
case ConfigInfo::CI_BOOL:{
Uint32 val = 0;
- ::require(defaults->get(name, &val));
+ require(defaults->get(name, &val));
ctx.m_currentSection->put(name, val);
DBUG_PRINT("info",("%s=%d #default",name,val));
break;
}
case ConfigInfo::CI_INT64:{
Uint64 val = 0;
- ::require(defaults->get(name, &val));
+ require(defaults->get(name, &val));
ctx.m_currentSection->put64(name, val);
DBUG_PRINT("info",("%s=%lld #default",name,val));
break;
}
case ConfigInfo::CI_STRING:{
const char * val;
- ::require(defaults->get(name, &val));
+ require(defaults->get(name, &val));
ctx.m_currentSection->put(name, val);
DBUG_PRINT("info",("%s=%s #default",name,val));
break;
@@ -3890,20 +3877,20 @@ applyDefaultValues(InitConfigFileParser:
case ConfigInfo::CI_INT:
case ConfigInfo::CI_BOOL:{
Uint32 val = 0;
- ::require(ctx.m_currentSection->get(name, &val));
+ require(ctx.m_currentSection->get(name, &val));
DBUG_PRINT("info",("%s=%d",name,val));
break;
}
case ConfigInfo::CI_INT64:{
Uint64 val = 0;
- ::require(ctx.m_currentSection->get(name, &val));
+ require(ctx.m_currentSection->get(name, &val));
DBUG_PRINT("info",("%s=%lld",name,val));
break;
}
case ConfigInfo::CI_ENUM:
case ConfigInfo::CI_STRING:{
const char * val;
- ::require(ctx.m_currentSection->get(name, &val));
+ require(ctx.m_currentSection->get(name, &val));
DBUG_PRINT("info",("%s=%s",name,val));
break;
}
@@ -3939,11 +3926,11 @@ checkMandatory(InitConfigFileParser::Con
Properties::Iterator it(ctx.m_currentInfo);
for(const char * name = it.first(); name != NULL; name = it.next()){
const Properties * info = NULL;
- ::require(ctx.m_currentInfo->get(name, &info));
+ require(ctx.m_currentInfo->get(name, &info));
Uint32 val;
if(info->get("Mandatory", &val)){
const char * fname;
- ::require(info->get("Fname", &fname));
+ require(info->get("Fname", &fname));
if(!ctx.m_currentSection->contains(fname)){
ctx.reportError("Mandatory parameter %s missing from section "
"[%s] starting at line: %d",
@@ -4444,24 +4431,24 @@ fixDepricated(InitConfigFileParser::Cont
case PropertiesType_Uint32:{
Uint32 val;
require(tmp.get(name, &val));
- ::require(ctx.m_currentSection->put(name, val));
+ require(ctx.m_currentSection->put(name, val));
break;
}
case PropertiesType_char:{
const char * val;
require(tmp.get(name, &val));
- ::require(ctx.m_currentSection->put(name, val));
+ require(ctx.m_currentSection->put(name, val));
break;
}
case PropertiesType_Uint64:{
Uint64 val;
require(tmp.get(name, &val));
- ::require(ctx.m_currentSection->put64(name, val));
+ require(ctx.m_currentSection->put64(name, val));
break;
}
case PropertiesType_Properties:
default:
- ::require(false);
+ require(false);
}
}
return true;
=== modified file 'storage/ndb/src/mgmsrv/ConfigManager.cpp'
--- a/storage/ndb/src/mgmsrv/ConfigManager.cpp 2009-10-27 16:50:41 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigManager.cpp 2009-12-03 05:53:33 +0000
@@ -28,19 +28,6 @@
#include <ndb_version.h>
-static void
-_require(bool v, const char* expr, const char* file, int line)
-{
- if (unlikely(!v))
- {
- fprintf(stderr, "%s:%d: require('%s') failed\n",
- file, line, expr);
- fflush(stderr);
- abort();
- }
-}
-#define require(v) _require((v), #v, __FILE__, __LINE__)
-
extern "C" const char* opt_connect_str;
ConfigManager::ConfigManager(const MgmtSrvr::MgmtOpts& opts,
@@ -1323,6 +1310,22 @@ ConfigManager::execCONFIG_CHANGE_REQ(Sig
}
+static Uint32
+config_check_checksum(const Config* config)
+{
+ Config copy(config);
+
+ // Make constants of a few values in SYSTEM section that are
+ // not part of the checksum used for "config check"
+ copy.setName("CHECKSUM");
+ copy.setPrimaryMgmNode(0);
+
+ Uint32 checksum = copy.checksum();
+
+ return checksum;
+}
+
+
void
ConfigManager::execCONFIG_CHECK_REQ(SignalSender& ss, SimpleSignal* sig)
{
@@ -1337,12 +1340,24 @@ ConfigManager::execCONFIG_CHECK_REQ(Sign
Uint32 generation = m_config->getGeneration();
- g_eventLogger->debug("Got CONFIG_CHECK_REQ from node: %d. " \
- "generation: %d, other_generation: %d, " \
- "our state: %d, other state: %d",
- nodeId, generation, other_generation,
- m_config_state, other_state);
+ // checksum
+ Uint32 checksum = config_check_checksum(m_config);
+ Uint32 other_checksum = req->checksum;
+ if (sig->header.theLength == ConfigCheckReq::SignalLengthBeforeChecksum)
+ {
+ // Other side uses old version without checksum, use our checksum to
+ // bypass the checks
+ g_eventLogger->debug("Other mgmd does not have checksum, using own");
+ other_checksum = checksum;
+ }
+ g_eventLogger->debug("Got CONFIG_CHECK_REQ from node: %d. "
+ "Our generation: %d, other generation: %d, "
+ "our state: %d, other state: %d, "
+ "our checksum: 0x%.8x, other checksum: 0x%.8x",
+ nodeId, generation, other_generation,
+ m_config_state, other_state,
+ checksum, other_checksum);
switch (m_config_state)
{
@@ -1376,6 +1391,17 @@ ConfigManager::execCONFIG_CHECK_REQ(Sign
m_config_state, other_state);
return;
}
+
+ if (other_checksum != checksum)
+ {
+ g_eventLogger->warning("Refusing other node, it has different "
+ "checksum: 0x%.8x, expected: 0x%.8x",
+ other_checksum, checksum);
+ sendConfigCheckRef(ss, from, ConfigCheckRef::WrongChecksum,
+ generation, other_generation,
+ m_config_state, other_state);
+ return;
+ }
break;
case CS_CONFIRMED:
@@ -1393,7 +1419,18 @@ ConfigManager::execCONFIG_CHECK_REQ(Sign
if (other_generation == generation)
{
- ;// OK
+ // Same generation, make sure it has same checksum
+ if (other_checksum != checksum)
+ {
+ g_eventLogger->warning("Refusing other node, it has different "
+ "checksum: 0x%.8x, expected: 0x%.8x",
+ other_checksum, checksum);
+ sendConfigCheckRef(ss, from, ConfigCheckRef::WrongChecksum,
+ generation, other_generation,
+ m_config_state, other_state);
+ return;
+ }
+ // OK!
}
else if (other_generation < generation)
{
@@ -1429,17 +1466,15 @@ ConfigManager::sendConfigCheckReq(Signal
CAST_PTR(ConfigCheckReq, ssig.getDataPtrSend());
req->state = m_config_state;
req->generation = m_config->getGeneration();
+ req->checksum = config_check_checksum(m_config);
- BaseString buf("Sending CONFIG_CHECK_REQ to node(s) ");
- unsigned i = 0;
- while((i = to.find(i+1)) != NodeBitmask::NotFound)
- buf.appfmt("%d ", i);
- g_eventLogger->debug(buf);
+ g_eventLogger->debug("Sending CONFIG_CHECK_REQ to %s",
+ BaseString::getPrettyText(to).c_str());
require(m_waiting_for.isclear());
m_waiting_for = ss.broadcastSignal(to, ssig, MGM_CONFIG_MAN,
- GSN_CONFIG_CHECK_REQ,
- ConfigCheckReq::SignalLength);
+ GSN_CONFIG_CHECK_REQ,
+ ConfigCheckReq::SignalLength);
}
static bool
@@ -1559,7 +1594,8 @@ ConfigManager::execCONFIG_CHECK_REF(Sign
m_config_state);
assert(ref->generation != ref->expected_generation ||
- ref->state != ref->expected_state);
+ ref->state != ref->expected_state ||
+ ref->error == ConfigCheckRef::WrongChecksum);
if((Uint32)m_config_state != ref->state)
{
// The config state changed while this check was in the air
@@ -1638,6 +1674,15 @@ ConfigManager::execCONFIG_CHECK_REF(Sign
break;
}
+ if (ref->error == ConfigCheckRef::WrongChecksum &&
+ m_node_id < nodeId)
+ {
+ g_eventLogger->warning("Ignoring CONFIG_CHECK_REF for wrong checksum "
+ "other node has higher node id and should "
+ "shutdown");
+ return;
+ }
+
g_eventLogger->error("Terminating");
exit(1);
}
@@ -1655,6 +1700,10 @@ ConfigManager::run()
m_started.set(m_facade->ownId());
+ // exclude nowait-nodes from config change protcol
+ m_all_mgm.bitANDC(m_opts.nowait_nodes);
+ m_all_mgm.set(m_facade->ownId()); // Never exclude own node
+
start_checkers();
while (!is_stopped())
=== modified file 'storage/ndb/src/mgmsrv/InitConfigFileParser.cpp'
--- a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp 2009-10-09 12:38:45 +0000
+++ b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp 2009-12-03 05:53:33 +0000
@@ -30,8 +30,6 @@ extern EventLogger *g_eventLogger;
const int MAX_LINE_LENGTH = 1024; // Max length of line of text in config file
static void trim(char *);
-static void require(bool v) { if(!v) abort();}
-
//****************************************************************************
// Ctor / Dtor
//****************************************************************************
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2009-11-08 12:52:27 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2009-12-03 05:53:33 +0000
@@ -77,18 +77,6 @@ int g_errorInsert;
extern "C" my_bool opt_core;
-static void require(bool v)
-{
- if(!v)
- {
- if (opt_core)
- abort();
- else
- exit(-1);
- }
-}
-
-
void *
MgmtSrvr::logLevelThread_C(void* m)
{
@@ -2605,7 +2593,7 @@ MgmtSrvr::alloc_node_id_req(NodeId free_
SimpleSignal ssig;
AllocNodeIdReq* req = CAST_PTR(AllocNodeIdReq, ssig.getDataPtrSend());
ssig.set(ss, TestOrd::TraceAPI, QMGR, GSN_ALLOC_NODEID_REQ,
- AllocNodeIdReq::SignalLength);
+ AllocNodeIdReq::SignalLength);
req->senderRef = ss.getOwnRef();
req->senderData = 19;
@@ -2661,7 +2649,9 @@ MgmtSrvr::alloc_node_id_req(NodeId free_
if (ref->errorCode != AllocNodeIdRef::NotMaster)
{
/* sleep for a while (100ms) before retrying */
+ ss.unlock();
NdbSleep_MilliSleep(100);
+ ss.lock();
}
continue;
}
@@ -2669,20 +2659,20 @@ MgmtSrvr::alloc_node_id_req(NodeId free_
}
case GSN_NF_COMPLETEREP:
{
- const NFCompleteRep * const rep =
- CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
-#ifdef VM_TRACE
- ndbout_c("Node %d fail completed", rep->failedNodeId);
-#endif
- if (rep->failedNodeId == nodeId)
- {
- do_send = 1;
- nodeId = 0;
- }
continue;
}
case GSN_NODE_FAILREP:{
- // ignore NF_COMPLETEREP will come
+ /**
+ * ok to trap using NODE_FAILREP
+ * as we don't really wait on anything interesting
+ */
+ const NodeFailRep * const rep =
+ CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
+ if (NdbNodeBitmask::get(rep->theNodes, nodeId))
+ {
+ do_send = 1;
+ nodeId = 0;
+ }
continue;
}
case GSN_API_REGCONF:
@@ -2894,7 +2884,6 @@ MgmtSrvr::try_alloc(unsigned id, const c
m_connect_address[id].s_addr= 0;
}
}
- m_reserved_nodes.set(id);
if (theFacade && id != theFacade->ownId())
{
/**
@@ -2980,12 +2969,21 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
continue;
const char *config_hostname= nodes_info[i].host.c_str();
+ /**
+ * set bit as reserved, release mutex, try-alloc reaquire mutex
+ * and clear bit if alloc failed
+ */
+ m_reserved_nodes.set(id);
+ NdbMutex_Unlock(m_node_id_mutex);
if (!try_alloc(id, config_hostname, type, client_addr, timeout_ms))
{
+ NdbMutex_Lock(m_node_id_mutex);
// success
*nodeId= id;
DBUG_RETURN(true);
}
+ NdbMutex_Lock(m_node_id_mutex);
+ m_reserved_nodes.clear(id);
}
/* now try the open nodes */
@@ -3001,12 +2999,21 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
if (exact_nodes.get(id))
continue;
+ /**
+ * set bit as reserved, release mutex, try-alloc reaquire mutex
+ * and clear bit if alloc failed
+ */
+ m_reserved_nodes.set(id);
+ NdbMutex_Unlock(m_node_id_mutex);
if (!try_alloc(id, NULL, type, client_addr, timeout_ms))
{
+ NdbMutex_Lock(m_node_id_mutex);
// success
*nodeId= id;
DBUG_RETURN(true);
}
+ NdbMutex_Lock(m_node_id_mutex);
+ m_reserved_nodes.clear(id);
}
/*
@@ -3315,9 +3322,15 @@ MgmtSrvr::Allocated_resources::Allocated
MgmtSrvr::Allocated_resources::~Allocated_resources()
{
- Guard g(m_mgmsrv.m_node_id_mutex);
- if (!m_reserved_nodes.isclear()) {
- m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes);
+ if (!m_reserved_nodes.isclear())
+ {
+ /**
+ * No need to aquire mutex if we didn't have any reservation in
+ * our sesssion
+ */
+ Guard g(m_mgmsrv.m_node_id_mutex);
+ m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes);
+
// node has been reserved, force update signal to ndb nodes
m_mgmsrv.updateStatus();
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2009-11-08 12:52:27 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2009-11-13 11:24:05 +0000
@@ -123,6 +123,7 @@ public:
MgmtOpts() : configdir(MYSQLCLUSTERDIR) {};
int reload;
int initial;
+ NodeBitmask nowait_nodes;
};
MgmtSrvr(); // Not implemented
=== modified file 'storage/ndb/src/mgmsrv/main.cpp'
--- a/storage/ndb/src/mgmsrv/main.cpp 2009-09-25 07:27:49 +0000
+++ b/storage/ndb/src/mgmsrv/main.cpp 2009-11-13 11:24:05 +0000
@@ -85,6 +85,7 @@ bool g_RestartServer= false;
static MgmtSrvr* mgm;
static MgmtSrvr::MgmtOpts opts;
static const char* opt_logname = "MgmtSrvr";
+static const char* opt_nowait_nodes = 0;
static struct my_option my_long_options[] =
{
@@ -142,6 +143,10 @@ static struct my_option my_long_options[
"Name to use when logging messages for this node",
(uchar**) &opt_logname, (uchar**) &opt_logname, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "nowait-nodes", 256,
+ "Nodes that will not be waited for during start",
+ (uchar**) &opt_nowait_nodes, (uchar**) &opt_nowait_nodes, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -221,6 +226,24 @@ static int mgmd_main(int argc, char** ar
mgmd_exit(1);
}
+
+ if (opt_nowait_nodes)
+ {
+ int res = opts.nowait_nodes.parseMask(opt_nowait_nodes);
+ if(res == -2 || (res > 0 && opts.nowait_nodes.get(0)))
+ {
+ g_eventLogger->error("Invalid nodeid specified in nowait-nodes: '%s'",
+ opt_nowait_nodes);
+ mgmd_exit(1);
+ }
+ else if (res < 0)
+ {
+ g_eventLogger->error("Unable to parse nowait-nodes argument: '%s'",
+ opt_nowait_nodes);
+ mgmd_exit(1);
+ }
+ }
+
/**
Install signal handler for SIGPIPE
Done in TransporterFacade as well.. what about Configretriever?
=== modified file 'storage/ndb/src/mgmsrv/testConfig.cpp'
--- a/storage/ndb/src/mgmsrv/testConfig.cpp 2009-11-03 16:40:26 +0000
+++ b/storage/ndb/src/mgmsrv/testConfig.cpp 2009-11-17 18:13:29 +0000
@@ -260,6 +260,40 @@ print_restart_info(void)
fprintf(stderr, "\n");
}
+
+static void
+checksum_config(void)
+{
+ Config* c1=
+ create_config("[ndbd]", "NoOfReplicas=1",
+ "[ndb_mgmd]", "HostName=localhost",
+ "[mysqld]", NULL);
+ Config* c2=
+ create_config("[ndbd]", "NoOfReplicas=1",
+ "[ndb_mgmd]", "HostName=localhost",
+ "[mysqld]", "[mysqld]", NULL);
+
+ ndbout_c("== checksum tests ==");
+ Uint32 c1_check = c1->checksum();
+ Uint32 c2_check = c2->checksum();
+ ndbout_c("c1->checksum(): 0x%x", c1_check);
+ ndbout_c("c2->checksum(): 0x%x", c2_check);
+ // Different config should not have same checksum
+ CHECK(c1_check != c2_check);
+
+ // Same config should have same checksum
+ CHECK(c1_check == c1->checksum());
+
+ // Copied config should have same checksum
+ Config c1_copy(c1);
+ CHECK(c1_check == c1_copy.checksum());
+
+ ndbout_c("==================");
+
+ delete c1;
+ delete c2;
+}
+
#include <NdbTap.hpp>
TAPTEST(MgmConfig)
@@ -267,6 +301,7 @@ TAPTEST(MgmConfig)
ndb_init();
diff_config();
CHECK(check_params());
+ checksum_config();
#if 0
print_restart_info();
#endif
=== modified file 'storage/ndb/src/ndbapi/Ndb.cpp'
--- a/storage/ndb/src/ndbapi/Ndb.cpp 2009-09-30 07:59:42 +0000
+++ b/storage/ndb/src/ndbapi/Ndb.cpp 2009-12-03 18:19:36 +0000
@@ -2206,6 +2206,154 @@ Ndb::printState(const char* fmt, ...)
theCompletedTransactionsArray[i]->printState();
NdbMutex_Unlock(ndb_print_state_mutex);
}
+
#endif
+const char*
+Ndb::getNdbErrorDetail(const NdbError& err, char* buff, Uint32 buffLen) const
+{
+ DBUG_ENTER("Ndb::getNdbErrorDetail");
+ /* If err has non-null details member, prepare a string containing
+ * those details
+ */
+ if (!buff)
+ DBUG_RETURN(NULL);
+
+ if (err.details != NULL)
+ {
+ DBUG_PRINT("info", ("err.code is %u", err.code));
+ switch (err.code) {
+ case 893: /* Unique constraint violation */
+ {
+ /* err.details contains the violated Index's object id
+ * We'll map it to a name, then map the name to a
+ * base table, schema and database, and put that in
+ * string form into the caller's buffer
+ */
+ UintPtr uip = (UintPtr) err.details;
+ Uint32 indexObjectId = (Uint32) (uip - (UintPtr(0)));
+ Uint32 primTableObjectId = ~ (Uint32) 0;
+ BaseString indexName;
+
+ {
+ DBUG_PRINT("info", ("Index object id is %u", indexObjectId));
+ NdbDictionary::Dictionary::List allIndices;
+ int rc = theDictionary->listObjects(allIndices,
+ NdbDictionary::Object::UniqueHashIndex,
+ false); // FullyQualified names
+ if (rc)
+ {
+ DBUG_PRINT("info", ("listObjects call 1 failed with rc %u", rc));
+ DBUG_RETURN(NULL);
+ }
+
+ DBUG_PRINT("info", ("Retrieved details for %u indices", allIndices.count));
+
+ for (unsigned i = 0; i < allIndices.count; i++)
+ {
+ if (allIndices.elements[i].id == indexObjectId)
+ {
+ /* Found the index in question
+ * Expect fully qualified name to be in the form :
+ * <db>/<schema>/<primTabId>/<IndexName>
+ */
+ Vector<BaseString> idxNameComponents;
+ BaseString idxName(allIndices.elements[i].name);
+
+ Uint32 components = idxName.split(idxNameComponents,
+ &table_name_separator);
+
+ assert(components == 4);
+
+ primTableObjectId = atoi(idxNameComponents[2].c_str());
+ indexName = idxNameComponents[3];
+
+ DBUG_PRINT("info", ("Found index name : %s, primary table id : %u",
+ indexName.c_str(), primTableObjectId));
+
+ break;
+ }
+ }
+ }
+
+ if (primTableObjectId != (~(Uint32) 0))
+ {
+ NdbDictionary::Dictionary::List allTables;
+ int rc = theDictionary->listObjects(allTables,
+ NdbDictionary::Object::UserTable,
+ false); // FullyQualified names
+
+ if (rc)
+ {
+ DBUG_PRINT("info", ("listObjects call 2 failed with rc %u", rc));
+ DBUG_RETURN(NULL);
+ }
+
+ DBUG_PRINT("info", ("Retrieved details for %u tables", allTables.count));
+
+ for (Uint32 t = 0; t < allTables.count; t++)
+ {
+
+ if (allTables.elements[t].id == primTableObjectId)
+ {
+ /* Found table, name should be in format :
+ * <db>/<schema>/<tablename>
+ */
+ Vector<BaseString> tabNameComponents;
+ BaseString tabName(allTables.elements[t].name);
+
+ Uint32 components = tabName.split(tabNameComponents,
+ &table_name_separator);
+ assert (components == 3);
+
+ /* Now we generate a string of the format
+ * <dbname>/<schemaname>/<tabname>/<idxname>
+ * which should be usable by end users
+ */
+ BaseString result;
+ result.assfmt("%s/%s/%s/%s",
+ tabNameComponents[0].c_str(),
+ tabNameComponents[1].c_str(),
+ tabNameComponents[2].c_str(),
+ indexName.c_str());
+
+ DBUG_PRINT("info", ("Found full index details : %s",
+ result.c_str()));
+
+ memcpy(buff, result.c_str(),
+ MIN(buffLen,
+ (result.length() + 1)));
+ buff[buffLen] = 0;
+
+ DBUG_RETURN(buff);
+ }
+ }
+
+ /* Primary table not found!
+ * Strange - perhaps it's been dropped?
+ */
+ DBUG_PRINT("info", ("Table id %u not found", primTableObjectId));
+ DBUG_RETURN(NULL);
+ }
+ else
+ {
+ /* Index not found from id - strange.
+ * Perhaps it has been dropped?
+ */
+ DBUG_PRINT("info", ("Index id %u not found", indexObjectId));
+ DBUG_RETURN(NULL);
+ }
+ }
+ default:
+ {
+ /* Unhandled details type */
+ }
+ }
+ }
+
+ DBUG_PRINT("info", ("No details string for this error"));
+ DBUG_RETURN(NULL);
+}
+
+
=== modified file 'storage/ndb/src/ndbapi/NdbDictionary.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionary.cpp 2009-10-07 02:56:19 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp 2009-12-03 10:19:24 +0000
@@ -582,6 +582,11 @@ NdbDictionary::Table::getNoOfColumns() c
}
int
+NdbDictionary::Table::getNoOfAutoIncrementColumns() const {
+ return m_impl.m_noOfAutoIncColumns;
+}
+
+int
NdbDictionary::Table::getNoOfPrimaryKeys() const {
return m_impl.m_noOfKeys;
}
@@ -2539,7 +2544,17 @@ NdbDictionary::Dictionary::listObjects(L
int
NdbDictionary::Dictionary::listObjects(List& list, Object::Type type) const
{
- return m_impl.listObjects(list, type);
+ // delegate to variant with FQ names param
+ return listObjects(list, type,
+ m_impl.m_ndb.usingFullyQualifiedNames());
+}
+
+int
+NdbDictionary::Dictionary::listObjects(List& list, Object::Type type,
+ bool fullyQualified) const
+{
+ return m_impl.listObjects(list, type,
+ fullyQualified);
}
int
=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2009-09-04 11:33:38 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2009-12-03 10:19:24 +0000
@@ -591,6 +591,7 @@ NdbTableImpl::init(){
m_noOfDistributionKeys= 0;
m_noOfBlobs= 0;
m_replicaCount= 0;
+ m_noOfAutoIncColumns = 0;
m_ndbrecord= 0;
m_pkMask= 0;
m_min_rows = 0;
@@ -872,6 +873,8 @@ NdbTableImpl::assign(const NdbTableImpl&
m_noOfBlobs = org.m_noOfBlobs;
m_replicaCount = org.m_replicaCount;
+ m_noOfAutoIncColumns = org.m_noOfAutoIncColumns;
+
m_id = org.m_id;
m_version = org.m_version;
m_status = org.m_status;
@@ -921,6 +924,9 @@ NdbTableImpl::computeAggregates()
m_noOfDiskColumns++;
col->m_keyInfoPos = ~0;
+
+ if (col->m_autoIncrement)
+ m_noOfAutoIncColumns++;
}
if (m_noOfDistributionKeys == m_noOfKeys) {
// all is none!
@@ -2432,7 +2438,17 @@ NdbDictInterface::execGET_TABINFO_REF(Nd
const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef,
signal->getDataPtr());
- m_error.code= ref->errorCode;
+ if (likely(signal->getLength() == GetTabInfoRef::SignalLength))
+ {
+ m_error.code= ref->errorCode;
+ }
+ else
+ {
+ /* 6.3 <-> 7.0 upgrade only */
+ assert (signal->getLength() == GetTabInfoRef::OriginalSignalLength);
+ m_error.code = (*(signal->getDataPtr() +
+ GetTabInfoRef::OriginalErrorOffset));
+ }
m_waiter.signal(NO_WAIT);
}
@@ -4713,7 +4729,18 @@ NdbDictInterface::execSUB_START_CONF(Ndb
}
}
- m_sub_start_conf.m_buckets = subStartConf->bucketCount;
+ if (signal->getLength() == SubStartConf::SignalLength)
+ {
+ m_sub_start_conf.m_buckets = subStartConf->bucketCount;
+ }
+ else
+ {
+ /* 6.3 <-> 7.0 upgrade
+ * 6.3 doesn't send required bucketCount.
+ * ~0 indicates no bucketCount received
+ */
+ m_sub_start_conf.m_buckets = ~0;
+ }
DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
subscriptionId,subscriptionKey,subscriberData));
m_waiter.signal(NO_WAIT);
@@ -5071,7 +5098,9 @@ NdbDictionaryImpl::listEvents(List& list
* List objects or indexes
*/
int
-NdbDictionaryImpl::listObjects(List& list, NdbDictionary::Object::Type type)
+NdbDictionaryImpl::listObjects(List& list,
+ NdbDictionary::Object::Type type,
+ bool fullyQualified)
{
int ret;
List list1, list2;
@@ -5091,8 +5120,8 @@ NdbDictionaryImpl::listObjects(List& lis
req.setTableType(getKernelConstant(type, objectTypeMapping, 0));
req.setListNames(true);
if (!list2.count)
- return m_receiver.listObjects(list, req, m_ndb.usingFullyQualifiedNames());
- ret = m_receiver.listObjects(list1, req, m_ndb.usingFullyQualifiedNames());
+ return m_receiver.listObjects(list, req, fullyQualified);
+ ret = m_receiver.listObjects(list1, req, fullyQualified);
if (ret)
return ret;
list.count = list1.count + list2.count;
@@ -7758,6 +7787,13 @@ NdbDictionaryImpl::beginSchemaTrans()
m_error.code = 4410;
DBUG_RETURN(-1);
}
+ if (!m_receiver.checkAllNodeVersionsMin(NDBD_SCHEMA_TRANS_VERSION))
+ {
+ /* Upgrade 6.3 -> 7.0 path */
+ /* Schema transaction not possible until upgrade complete */
+ m_error.code = 4411;
+ DBUG_RETURN(-1);
+ }
// TODO real transId
m_tx.m_transId = rand();
m_tx.m_state = NdbDictInterface::Tx::Started;
@@ -7839,6 +7875,27 @@ committed:
DBUG_RETURN(0);
}
+bool
+NdbDictInterface::checkAllNodeVersionsMin(Uint32 minNdbVersion) const
+{
+ for (Uint32 nodeId = 1; nodeId < MAX_NODES; nodeId++)
+ {
+ if (m_transporter->getIsDbNode(nodeId) &&
+ m_transporter->getIsNodeSendable(nodeId) &&
+ (m_transporter->getNodeNdbVersion(nodeId) <
+ minNdbVersion))
+ {
+ /* At least 1 sendable data node has lower-than-min
+ * version
+ */
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
int
NdbDictInterface::beginSchemaTrans()
{
=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2009-09-04 11:33:38 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2009-12-03 10:19:24 +0000
@@ -201,6 +201,7 @@ public:
if iterating over columns.
*/
Vector<NdbColumnImpl *> m_columns;
+ Uint32 m_noOfAutoIncColumns;
void computeAggregates();
int buildColumnHash();
@@ -689,6 +690,8 @@ public:
int endSchemaTrans(Uint32 flags);
Tx & m_tx; // shared with NdbDictionaryImpl
+ bool checkAllNodeVersionsMin(Uint32 minNdbVersion) const;
+
const NdbError &getNdbError() const;
NdbError & m_error;
private:
@@ -824,7 +827,8 @@ public:
int forceGCPWait();
- int listObjects(List& list, NdbDictionary::Object::Type type);
+ int listObjects(List& list, NdbDictionary::Object::Type type,
+ bool fullyQualified);
int listIndexes(List& list, Uint32 indexId);
NdbTableImpl * getTableGlobal(const char * tableName);
=== modified file 'storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp 2009-08-06 13:51:18 +0000
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp 2009-11-18 13:13:34 +0000
@@ -616,6 +616,12 @@ NdbEventOperationImpl::execute_nolock()
buckets);
if (r == 0)
{
+ /* Pre-7.0 kernel nodes do not return the number of buckets
+ * Assume it's == theNoOfDBnodes as was the case in 6.3
+ */
+ if (buckets == ~ (Uint32)0)
+ buckets = m_ndb->theImpl->theNoOfDBnodes;
+
m_ndb->theEventBuffer->set_total_buckets(buckets);
if (theMainOp == NULL) {
=== modified file 'storage/ndb/src/ndbapi/NdbImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbImpl.hpp 2009-10-21 12:51:50 +0000
+++ b/storage/ndb/src/ndbapi/NdbImpl.hpp 2009-12-06 17:12:40 +0000
@@ -27,9 +27,9 @@
#include <NdbReceiver.hpp>
#include <NdbOperation.hpp>
#include <kernel/ndb_limits.h>
-#include <NdbQueryOperationImpl.hpp>
#include <NdbTick.h>
+#include "NdbQueryOperationImpl.hpp"
#include "ndb_cluster_connection_impl.hpp"
#include "NdbDictionaryImpl.hpp"
#include "ObjectMap.hpp"
@@ -110,6 +110,14 @@ public:
return;
}
+ bool forceShortRequests;
+
+ static inline void setForceShortRequests(Ndb* ndb, bool val)
+ {
+ ndb->theImpl->forceShortRequests = val;
+ }
+
+
BaseString m_systemPrefix; // Buffer for preformatted for <sys>/<def>/
/**
=== modified file 'storage/ndb/src/ndbapi/NdbOperationDefine.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp 2009-06-12 14:12:30 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp 2009-12-06 17:12:40 +0000
@@ -699,6 +699,26 @@ NdbOperation::getBlobHandle(NdbTransacti
return NULL;
}
+ /* Check key fully defined for key operations */
+ switch (theStatus)
+ {
+ case TupleKeyDefined:
+ case GetValue:
+ case SetValue:
+ case FinalGetValue:
+ case ExecInterpretedValue:
+ case SetValueInterpreted:
+ /* All ok states to create a Blob Handle in */
+ break;
+ default:
+ {
+ /* Unexpected state to be obtaining Blob handle */
+ /* Invalid usage of blob attribute */
+ setErrorCodeAbort(4264);
+ return NULL;
+ }
+ }
+
tBlob = theNdb->getNdbBlob();
if (tBlob == NULL)
return NULL;
=== modified file 'storage/ndb/src/ndbapi/NdbOperationExec.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp 2009-10-26 13:55:01 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp 2009-12-06 17:12:40 +0000
@@ -130,6 +130,128 @@ NdbOperation::setLastFlag(NdbApiSignal*
TcKeyReq::setExecuteFlag(req->requestInfo, lastFlag);
}
+int
+NdbOperation::doSendKeyReq(int aNodeId,
+ GenericSectionPtr* secs,
+ Uint32 numSecs)
+{
+ /* Send a KeyRequest - could be TCKEYREQ or TCINDXREQ
+ *
+ * Normally we send a single long signal with 1 or 2
+ * sections containing KeyInfo and AttrInfo.
+ * For backwards compatibility and testing purposes
+ * we can send signal trains instead.
+ */
+ NdbApiSignal* request = theTCREQ;
+ TransporterFacade *tp = theNdb->theImpl->m_transporter_facade;
+ Uint32 tcNodeVersion = tp->getNodeNdbVersion(aNodeId);
+ bool forceShort = false;
+ forceShort = theNdb->theImpl->forceShortRequests;
+ bool sendLong = ( tcNodeVersion >= NDBD_LONG_TCKEYREQ ) &&
+ ! forceShort;
+
+ if (sendLong)
+ {
+ return tp->sendSignal(request, aNodeId, secs, numSecs);
+ }
+ else
+ {
+ /* Send signal as short request - either for backwards
+ * compatibility or testing
+ */
+ Uint32 sigCount = 1;
+ Uint32 keyInfoLen = secs[0].sz;
+ Uint32 attrInfoLen = (numSecs == 2)?
+ secs[1].sz :
+ 0;
+
+ Uint32 keyInfoInReq = MIN(keyInfoLen, TcKeyReq::MaxKeyInfo);
+ Uint32 attrInfoInReq = MIN(attrInfoLen, TcKeyReq::MaxAttrInfo);
+ TcKeyReq* tcKeyReq = (TcKeyReq*) request->getDataPtrSend();
+ Uint32 connectPtr = tcKeyReq->apiConnectPtr;
+ Uint32 transId1 = tcKeyReq->transId1;
+ Uint32 transId2 = tcKeyReq->transId2;
+ bool indexReq = (request->theVerId_signalNumber == GSN_TCINDXREQ);
+
+ Uint32 reqLen = request->theLength;
+
+ /* Set TCKEYREQ flags */
+ TcKeyReq::setKeyLength(tcKeyReq->requestInfo, keyInfoLen);
+ TcKeyReq::setAIInTcKeyReq(tcKeyReq->requestInfo , attrInfoInReq);
+ TcKeyReq::setAttrinfoLen(tcKeyReq->attrLen, attrInfoLen);
+
+ Uint32* writePtr = request->getDataPtrSend() + reqLen;
+
+ GSIReader keyInfoReader(secs[0].sectionIter);
+ GSIReader attrInfoReader(secs[1].sectionIter);
+
+ keyInfoReader.copyNWords(writePtr, keyInfoInReq);
+ writePtr += keyInfoInReq;
+ attrInfoReader.copyNWords(writePtr, attrInfoInReq);
+
+ reqLen += keyInfoInReq + attrInfoInReq;
+ assert( reqLen <= TcKeyReq::SignalLength );
+
+ request->setLength(reqLen);
+
+ if (tp->sendSignal(request, aNodeId) == -1)
+ return -1;
+
+ keyInfoLen -= keyInfoInReq;
+ attrInfoLen -= attrInfoInReq;
+
+ if (keyInfoLen)
+ {
+ request->theVerId_signalNumber = indexReq ?
+ GSN_INDXKEYINFO : GSN_KEYINFO;
+ KeyInfo* keyInfo = (KeyInfo*) request->getDataPtrSend();
+ keyInfo->connectPtr = connectPtr;
+ keyInfo->transId[0] = transId1;
+ keyInfo->transId[1] = transId2;
+
+ while(keyInfoLen)
+ {
+ Uint32 dataWords = MIN(keyInfoLen, KeyInfo::DataLength);
+
+ keyInfoReader.copyNWords(&keyInfo->keyData[0], dataWords);
+ request->setLength(KeyInfo::HeaderLength + dataWords);
+
+ if (tp->sendSignal(request, aNodeId) == -1)
+ return -1;
+
+ keyInfoLen-= dataWords;
+ sigCount++;
+ }
+ }
+
+ if (attrInfoLen)
+ {
+ request->theVerId_signalNumber = indexReq ?
+ GSN_INDXATTRINFO : GSN_ATTRINFO;
+ AttrInfo* attrInfo = (AttrInfo*) request->getDataPtrSend();
+ attrInfo->connectPtr = connectPtr;
+ attrInfo->transId[0] = transId1;
+ attrInfo->transId[1] = transId2;
+
+ while(attrInfoLen)
+ {
+ Uint32 dataWords = MIN(attrInfoLen, AttrInfo::DataLength);
+
+ attrInfoReader.copyNWords(&attrInfo->attrData[0], dataWords);
+ request->setLength(AttrInfo::HeaderLength + dataWords);
+
+ if (tp->sendSignal(request, aNodeId) == -1)
+ return -1;
+
+ attrInfoLen-= dataWords;
+ sigCount++;
+ }
+ }
+
+ return sigCount;
+ }
+}
+
/******************************************************************************
int doSend()
@@ -144,17 +266,40 @@ NdbOperation::doSend(int aNodeId, Uint32
{
assert(theTCREQ != NULL);
setLastFlag(theTCREQ, lastFlag);
+ Uint32 numSecs= 1;
+ GenericSectionPtr secs[2];
if (m_attribute_record != NULL)
{
- /* NdbRecord send - single long signal */
- if (doSendNdbRecord(aNodeId) == -1 )
+ /*
+ * NdbRecord signal building code puts all KeyInfo and
+ * AttrInfo into the KeyInfo and AttrInfo signal lists.
+ */
+ SignalSectionIterator keyInfoIter(theTCREQ->next());
+ SignalSectionIterator attrInfoIter(theFirstATTRINFO);
+
+ /* KeyInfo - always present for TCKEY/INDXREQ*/
+ secs[0].sz= theTupKeyLen;
+ secs[0].sectionIter= &keyInfoIter;
+
+ /* AttrInfo - not always needed (e.g. Delete) */
+ if (theTotalCurrAI_Len != 0)
+ {
+ secs[1].sz= theTotalCurrAI_Len;
+ secs[1].sectionIter= &attrInfoIter;
+ numSecs++;
+ }
+
+ if (doSendKeyReq(aNodeId, &secs[0], numSecs) == -1)
return -1;
}
else
{
- /* Old Api send - transform signal train to long sections */
- TransporterFacade *tp = theNdb->theImpl->m_transporter_facade;
+ /*
+ * Old Api signal building code puts first words of KeyInfo
+ * and AttrInfo into the initial request signal
+ * We use special iterators to extract this
+ */
TcKeyReq* tcKeyReq= (TcKeyReq*) theTCREQ->getDataPtrSend();
const Uint32 inlineKIOffset= Uint32(tcKeyReq->keyInfo - (Uint32*)tcKeyReq);
@@ -164,8 +309,6 @@ NdbOperation::doSend(int aNodeId, Uint32
const Uint32 inlineAILength= MIN(TcKeyReq::MaxAttrInfo,
theTotalCurrAI_Len);
- Uint32 numSecs= 1;
- GenericSectionPtr secs[2];
/* Create iterators which use the signal train to extract
* long sections from the short signal trains
*/
@@ -190,7 +333,7 @@ NdbOperation::doSend(int aNodeId, Uint32
numSecs++;
}
- if (tp->sendSignal(theTCREQ, aNodeId, &secs[0], numSecs) == -1)
+ if (doSendKeyReq(aNodeId, &secs[0], numSecs) == -1)
return -1;
}
@@ -204,37 +347,6 @@ NdbOperation::doSend(int aNodeId, Uint32
}//NdbOperation::doSend()
-int
-NdbOperation::doSendNdbRecord(int aNodeId)
-{
- /*
- * Send a long signal to the kernel.
- * KeyInfo and AttrInfo for NdbRecord are always sent as
- * separate sections, with none in the TCKEYREQ
- */
- TransporterFacade *tp = theNdb->theImpl->m_transporter_facade;
-
- Uint32 numSecs= 1;
- GenericSectionPtr secs[2];
- SignalSectionIterator keyInfoIter(theTCREQ->next());
- SignalSectionIterator attrInfoIter(theFirstATTRINFO);
-
- /* KeyInfo - always present for TCKEY/INDXREQ*/
- secs[0].sz= theTupKeyLen;
- secs[0].sectionIter= &keyInfoIter;
-
- /* AttrInfo - not always needed (e.g. Delete) */
- if (theTotalCurrAI_Len != 0)
- {
- secs[1].sz= theTotalCurrAI_Len;
- secs[1].sectionIter= &attrInfoIter;
- numSecs++;
- }
-
- return tp->sendSignal(theTCREQ, aNodeId, &secs[0], numSecs);
-}
-
-
/***************************************************************************
int prepareSend(Uint32 aTC_ConnectPtr,
Uint64 aTransactionId)
=== modified file 'storage/ndb/src/ndbapi/NdbOperationSearch.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp 2009-11-27 14:47:24 +0000
@@ -474,7 +474,8 @@ NdbOperation::reorderKEYINFO()
{
Uint32 data[ NDB_MAX_KEYSIZE_IN_WORDS ];
Uint32 size = NDB_MAX_KEYSIZE_IN_WORDS;
- getKeyFromTCREQ(data, size);
+ int rc = getKeyFromTCREQ(data, size);
+ assert(rc == 0);
Uint32 pos = 1;
Uint32 k;
for (k = 0; k < m_accessTable->m_noOfKeys; k++) {
@@ -506,7 +507,10 @@ NdbOperation::reorderKEYINFO()
int
NdbOperation::getKeyFromTCREQ(Uint32* data, Uint32 & size)
{
- assert(size >= theTupKeyLen && theTupKeyLen > 0);
+ /* Check that we can correctly return a valid key */
+ if ((size < theTupKeyLen) || (theTupKeyLen == 0))
+ return -1;
+
size = theTupKeyLen;
unsigned pos = 0;
while (pos < 8 && pos < size) {
=== modified file 'storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp 2009-12-02 15:24:36 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryOperationImpl.hpp 2009-12-06 17:12:40 +0000
@@ -22,10 +22,10 @@
#include "NdbQueryOperation.hpp"
#include "NdbQueryBuilderImpl.hpp"
#include "NdbIndexScanOperation.hpp"
-#include "NdbError.hpp"
-#include "ndb_limits.h"
-#include "Vector.hpp"
-#include "Bitmask.hpp"
+#include <NdbError.hpp>
+#include <ndb_limits.h>
+#include <Vector.hpp>
+#include <Bitmask.hpp>
// Forward declarations
class NdbTableImpl;
=== modified file 'storage/ndb/src/ndbapi/NdbScanOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp 2009-12-02 15:24:36 +0000
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp 2009-12-06 17:12:40 +0000
@@ -2395,15 +2395,93 @@ NdbScanOperation::doSendScan(int aProces
}
TransporterFacade *tp = theNdb->theImpl->m_transporter_facade;
-
- /* Send Fragmented as SCAN_TABREQ can be large */
- if (tp->sendFragmentedSignal(theSCAN_TABREQ,
- aProcessorId,
- &secs[0],
- numSections) == -1)
+
+ Uint32 tcNodeVersion = tp->getNodeNdbVersion(aProcessorId);
+ bool forceShort = false;
+ forceShort = theNdb->theImpl->forceShortRequests;
+ bool sendLong = ( tcNodeVersion >= NDBD_LONG_SCANTABREQ) &&
+ ! forceShort;
+
+ if (sendLong)
+ {
+ /* Send Fragmented as SCAN_TABREQ can be large */
+ if (tp->sendFragmentedSignal(theSCAN_TABREQ,
+ aProcessorId,
+ &secs[0],
+ numSections) == -1)
+ {
+ setErrorCode(4002);
+ return -1;
+ }
+ }
+ else
{
- setErrorCode(4002);
- return -1;
+ /* Send a 'short' SCANTABREQ - e.g. long SCANTABREQ
+ * with signalIds as first section, followed by
+ * AttrInfo and KeyInfo trains
+ */
+ Uint32 attrInfoLen = secs[1].sz;
+ Uint32 keyInfoLen = (numSections == 3)? secs[2].sz : 0;
+
+ ScanTabReq* scanTabReq = (ScanTabReq*) theSCAN_TABREQ->getDataPtrSend();
+ Uint32 connectPtr = scanTabReq->apiConnectPtr;
+ Uint32 transId1 = scanTabReq->transId1;
+ Uint32 transId2 = scanTabReq->transId2;
+
+ /* Modify ScanTabReq to carry length of keyinfo and attrinfo */
+ scanTabReq->attrLenKeyLen = (keyInfoLen << 16) | attrInfoLen;
+
+ /* Send with receiver Ids as first and only section */
+ if (tp->sendSignal(theSCAN_TABREQ, aProcessorId, &secs[0], 1) == -1)
+ {
+ setErrorCode(4002);
+ return -1;
+ }
+
+ if (keyInfoLen)
+ {
+ GSIReader keyInfoReader(secs[2].sectionIter);
+ theSCAN_TABREQ->theVerId_signalNumber = GSN_KEYINFO;
+ KeyInfo* keyInfo = (KeyInfo*) theSCAN_TABREQ->getDataPtrSend();
+ keyInfo->connectPtr = connectPtr;
+ keyInfo->transId[0] = transId1;
+ keyInfo->transId[1] = transId2;
+
+ while(keyInfoLen)
+ {
+ Uint32 dataWords = MIN(keyInfoLen, KeyInfo::DataLength);
+ keyInfoReader.copyNWords(&keyInfo->keyData[0], dataWords);
+ theSCAN_TABREQ->setLength(KeyInfo::HeaderLength + dataWords);
+
+ if (tp->sendSignal(theSCAN_TABREQ, aProcessorId) == -1)
+ {
+ setErrorCode(4002);
+ return -1;
+ }
+ keyInfoLen -= dataWords;
+ }
+ }
+
+ GSIReader attrInfoReader(secs[1].sectionIter);
+ theSCAN_TABREQ->theVerId_signalNumber = GSN_ATTRINFO;
+ AttrInfo* attrInfo = (AttrInfo*) theSCAN_TABREQ->getDataPtrSend();
+ attrInfo->connectPtr = connectPtr;
+ attrInfo->transId[0] = transId1;
+ attrInfo->transId[1] = transId2;
+
+ while(attrInfoLen)
+ {
+ Uint32 dataWords = MIN(attrInfoLen, AttrInfo::DataLength);
+ attrInfoReader.copyNWords(&attrInfo->attrData[0], dataWords);
+ theSCAN_TABREQ->setLength(AttrInfo::HeaderLength + dataWords);
+
+ if (tp->sendSignal(theSCAN_TABREQ, aProcessorId) == -1)
+ {
+ setErrorCode(4002);
+ return -1;
+ }
+ attrInfoLen -= dataWords;
+ }
}
theStatus = WaitResponse;
=== modified file 'storage/ndb/src/ndbapi/Ndbinit.cpp'
--- a/storage/ndb/src/ndbapi/Ndbinit.cpp 2009-05-26 18:53:34 +0000
+++ b/storage/ndb/src/ndbapi/Ndbinit.cpp 2009-11-18 11:05:02 +0000
@@ -219,6 +219,11 @@ NdbImpl::NdbImpl(Ndb_cluster_connection
m_systemPrefix.assfmt("%s%c%s%c", NDB_SYSTEM_DATABASE, table_name_separator,
NDB_SYSTEM_SCHEMA, table_name_separator);
+
+ forceShortRequests = false;
+ const char* f= getenv("NDB_FORCE_SHORT_REQUESTS");
+ if (f != 0 && *f != 0 && *f != '0' && *f != 'n' && *f != 'N')
+ forceShortRequests = true;
}
NdbImpl::~NdbImpl()
=== modified file 'storage/ndb/src/ndbapi/TransporterFacade.hpp'
--- a/storage/ndb/src/ndbapi/TransporterFacade.hpp 2009-09-16 11:18:37 +0000
+++ b/storage/ndb/src/ndbapi/TransporterFacade.hpp 2009-12-06 17:12:40 +0000
@@ -95,6 +95,7 @@ public:
bool getIsNodeSendable(NodeId nodeId) const;
Uint32 getNodeGrp(NodeId nodeId) const;
Uint32 getNodeSequence(NodeId nodeId) const;
+ Uint32 getNodeNdbVersion(NodeId nodeId) const;
// Is there space in sendBuffer to send messages
bool check_send_size(Uint32 node_id, Uint32 send_size);
@@ -439,6 +440,13 @@ TransporterFacade::getNodeSequence(NodeI
inline
Uint32
+TransporterFacade::getNodeNdbVersion(NodeId n) const
+{
+ return theClusterMgr->getNodeInfo(n).m_info.m_version;
+}
+
+inline
+Uint32
TransporterFacade::get_scan_batch_size() const {
return m_scan_batch_size;
}
@@ -531,4 +539,57 @@ public :
const Uint32* getNextWords(Uint32& sz);
};
+/*
+ * GenericSectionIteratorReader
+ * Helper class to simplify reading data from
+ * GenericSectionIterator implementations
+ */
+
+class GSIReader
+{
+private :
+ GenericSectionIterator* gsi;
+ const Uint32* chunkPtr;
+ Uint32 chunkRemain;
+public :
+ GSIReader(GenericSectionIterator* _gsi)
+ {
+ gsi = _gsi;
+ chunkPtr = NULL;
+ chunkRemain = 0;
+ }
+
+ void copyNWords(Uint32* dest, Uint32 n)
+ {
+ while (n)
+ {
+ if (chunkRemain == 0)
+ {
+ /* Get next contiguous stretch of words from
+ * the iterator
+ */
+ chunkPtr = gsi->getNextWords(chunkRemain);
+ if (!chunkRemain)
+ abort(); // Must have the words the caller asks for
+ }
+ else
+ {
+ /* Have some words from the iterator, copy some/
+ * all of them
+ */
+ Uint32 wordsToCopy = MIN(chunkRemain, n);
+ memcpy(dest, chunkPtr, wordsToCopy << 2);
+ chunkPtr += wordsToCopy;
+ chunkRemain -= wordsToCopy;
+
+ dest += wordsToCopy;
+ n -= wordsToCopy;
+ }
+ }
+ }
+};
+
+
+
+
#endif // TransporterFacade_H
=== modified file 'storage/ndb/src/ndbapi/ndb_cluster_connection.cpp'
--- a/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp 2009-09-08 15:12:34 +0000
+++ b/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp 2009-11-17 16:26:09 +0000
@@ -290,7 +290,6 @@ Ndb_cluster_connection_impl(const char *
: Ndb_cluster_connection(*this),
m_main_connection(main_connection),
m_optimized_node_selection(1),
- m_name(0),
m_run_connect_thread(0),
m_latest_trans_gci(0),
m_first_ndb_object(0),
@@ -335,13 +334,6 @@ Ndb_cluster_connection_impl(const char *
("Could not initialize handle to management server: %s",
m_config_retriever->getErrorString());
printf("%s\n", get_latest_error_msg());
- delete m_config_retriever;
- m_config_retriever= 0;
- }
- if (m_name)
- {
- NdbMgmHandle h= m_config_retriever->get_mgmHandle();
- ndb_mgm_set_name(h, m_name);
}
if (!m_main_connection)
{
@@ -354,6 +346,11 @@ Ndb_cluster_connection_impl(const char *
m_globalDictCache = 0;
m_transporter_facade=
new TransporterFacade(m_main_connection->m_impl.m_globalDictCache);
+
+ // The secondary connection can't use same nodeid, clear the nodeid
+ // in ConfigRetriver to avoid asking for the same nodeid again
+ m_config_retriever->setNodeId(0);
+
}
DBUG_VOID_RETURN;
@@ -395,8 +392,6 @@ Ndb_cluster_connection_impl::~Ndb_cluste
ndb_print_state_mutex= NULL;
}
#endif
- if (m_name)
- free(m_name);
NdbMutex_Lock(g_ndb_connection_mutex);
if(--g_ndb_connection_count == 0)
@@ -483,14 +478,8 @@ Ndb_cluster_connection_impl::unlink_ndb_
void
Ndb_cluster_connection_impl::set_name(const char *name)
{
- if (m_name)
- free(m_name);
- m_name= strdup(name);
- if (m_config_retriever && m_name)
- {
- NdbMgmHandle h= m_config_retriever->get_mgmHandle();
- ndb_mgm_set_name(h, m_name);
- }
+ NdbMgmHandle h= m_config_retriever->get_mgmHandle();
+ ndb_mgm_set_name(h, name);
}
int
=== modified file 'storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp'
--- a/storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp 2009-11-17 16:15:19 +0000
@@ -89,7 +89,6 @@ private:
int (*m_connect_callback)(void);
int m_optimized_node_selection;
- char *m_name;
int m_run_connect_thread;
NdbMutex *m_event_add_drop_mutex;
Uint64 m_latest_trans_gci;
=== modified file 'storage/ndb/src/ndbapi/ndberror.c'
--- a/storage/ndb/src/ndbapi/ndberror.c 2009-12-02 15:24:36 +0000
+++ b/storage/ndb/src/ndbapi/ndberror.c 2009-12-06 17:12:40 +0000
@@ -583,6 +583,7 @@ ErrorBundle ErrorCodes[] = {
{ 4401, DMEC, AE, "Only one schema operation per schema transaction" },
{ 4402, DMEC, AE, "No schema operation defined before calling execute" },
{ 4410, DMEC, AE, "Schema transaction is already started" },
+ { 4411, DMEC, AE, "Schema transaction not possible until upgrade complete" },
{ 4501, DMEC, AE, "Insert in hash table failed when getting table information from Ndb" },
{ 4502, DMEC, AE, "GetValue not allowed in Update operation" },
=== modified file 'storage/ndb/test/include/NDBT_Test.hpp'
--- a/storage/ndb/test/include/NDBT_Test.hpp 2009-09-16 12:40:24 +0000
+++ b/storage/ndb/test/include/NDBT_Test.hpp 2009-11-18 11:05:02 +0000
@@ -380,6 +380,8 @@ public:
void setLogging(bool val);
bool getLogging() const;
+ bool getForceShort() const;
+
int createTables(Ndb_cluster_connection&) const;
int dropTables(Ndb_cluster_connection&) const;
@@ -417,6 +419,7 @@ private:
bool m_logging;
NDBT_DriverType m_driverType;
bool m_noddl;
+ bool m_forceShort;
};
=== modified file 'storage/ndb/test/ndbapi/slow_select.cpp'
--- a/storage/ndb/test/ndbapi/slow_select.cpp 2009-09-25 13:11:39 +0000
+++ b/storage/ndb/test/ndbapi/slow_select.cpp 2009-12-04 05:53:03 +0000
@@ -22,8 +22,15 @@ static S_Scan g_scans[] = {
{ "subgenrestometamap", "metaid", 0, 0, 0, 0 }
};
-#define require(x) if(!(x)) { ndbout << "LINE: " << __LINE__ << endl;abort(); }
-#define require2(o, x) if(!(x)) { ndbout << o->getNdbError() << endl; abort(); }
+#undef require
+#define require(x) require_exit_or_core_with_printer((x), 0, ndbout_printer)
+#define require2(o, x) \
+ if(!(x))\
+ {\
+ ndbout << o->getNdbError() << endl;\
+ require_exit_or_core_with_printer(0, 0, ndbout_printer);\
+ }
+
Uint32 g_affiliateid = 2;
Uint32 g_formatids[] = { 8, 31, 76 };
=== modified file 'storage/ndb/test/ndbapi/testBlobs.cpp'
--- a/storage/ndb/test/ndbapi/testBlobs.cpp 2009-10-26 20:51:04 +0000
+++ b/storage/ndb/test/ndbapi/testBlobs.cpp 2009-11-27 14:47:24 +0000
@@ -4177,6 +4177,87 @@ bugtest_27370()
return 0;
}
+static int
+bugtest_28116()
+{
+ DBG("bug test 28116 - Crash in getBlobHandle() when called without full key");
+
+ if (g_opt.m_pk2chr.m_len == 0)
+ {
+ DBG(" ... skipped, requires multi-column primary key.");
+ return 0;
+ }
+
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ int reqType = urandom(4);
+ switch(reqType) {
+ case 0:
+ {
+ DBG("Read");
+ CHK(g_opr->readTuple() == 0);
+ break;
+ }
+ case 1:
+ {
+ DBG("Insert");
+ CHK(g_opr->insertTuple() == 0);
+ break;
+ }
+ case 2:
+ {
+ DBG("Update");
+ CHK(g_opr->updateTuple() == 0);
+ break;
+ }
+ case 3:
+ default:
+ {
+ DBG("Delete");
+ CHK(g_opr->deleteTuple() == 0);
+ break;
+ }
+ }
+ switch (urandom(3)) {
+ case 0:
+ {
+ DBG(" No keys");
+ break;
+ }
+ case 1:
+ {
+ DBG(" Pk1 only");
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ break;
+ }
+ case 2:
+ default:
+ {
+ DBG(" Pk2/3 only");
+ if (g_opt.m_pk2chr.m_len != 0)
+ {
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK(g_opr->equal("PK3", tup.m_pk3) == 0);
+ }
+ break;
+ }
+ }
+ /* Deliberately no equal() on rest of primary key, to provoke error. */
+ CHK(g_opr->getBlobHandle("BL1") == 0);
+
+ /* 4264 - Invalid usage of Blob attribute */
+ CHK(g_con->getNdbError().code == 4264);
+ CHK(g_opr->getNdbError().code == 4264);
+
+ g_ndb->closeTransaction(g_con);
+ g_opr = 0;
+ g_con = 0;
+ }
+ return 0;
+}
+
static struct {
int m_bug;
int (*m_test)();
@@ -4186,7 +4267,8 @@ static struct {
{ 27370, bugtest_27370 },
{ 36756, bugtest_36756 },
{ 45768, bugtest_45768 },
- { 48040, bugtest_48040 }
+ { 48040, bugtest_48040 },
+ { 28116, bugtest_28116 }
};
NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
=== modified file 'storage/ndb/test/ndbapi/testIndex.cpp'
--- a/storage/ndb/test/ndbapi/testIndex.cpp 2009-08-07 12:02:25 +0000
+++ b/storage/ndb/test/ndbapi/testIndex.cpp 2009-12-03 16:40:09 +0000
@@ -31,6 +31,13 @@
result = NDBT_FAILED; break;\
}
+#define CHECKRET(b) if (!(b)) { \
+ g_err << "ERR: "<< step->getName() \
+ << " failed on line " << __LINE__ << endl; \
+ abort(); /* Remove */ \
+ return NDBT_FAILED; \
+}
+
struct Attrib {
bool indexCreated;
@@ -767,6 +774,298 @@ int runInsertDelete(NDBT_Context* ctx, N
return result;
}
+
+int tryAddUniqueIndex(Ndb* pNdb,
+ const NdbDictionary::Table* pTab,
+ const char* idxName,
+ HugoCalculator& calc,
+ int& chosenCol)
+{
+ for(int c = 0; c < pTab->getNoOfColumns(); c++)
+ {
+ const NdbDictionary::Column* col = pTab->getColumn(c);
+
+ if (!col->getPrimaryKey() &&
+ !calc.isUpdateCol(c) &&
+ !col->getNullable() &&
+ col->getStorageType() != NDB_STORAGETYPE_DISK)
+ {
+ chosenCol = c;
+ break;
+ }
+ }
+
+ if (chosenCol == -1)
+ {
+ return 1;
+ }
+
+
+ /* Create unique index on chosen column */
+
+ const char* colName = pTab->getColumn(chosenCol)->getName();
+ ndbout << "Creating unique index :" << idxName << " on ("
+ << colName << ")" << endl;
+
+ NdbDictionary::Index idxDef(idxName);
+ idxDef.setTable(pTab->getName());
+ idxDef.setType(NdbDictionary::Index::UniqueHashIndex);
+
+ idxDef.addIndexColumn(colName);
+ idxDef.setStoredIndex(false);
+
+ if (pNdb->getDictionary()->createIndex(idxDef) != 0)
+ {
+ ndbout << "FAILED!" << endl;
+ const NdbError err = pNdb->getDictionary()->getNdbError();
+ ERR(err);
+ return -1;
+ }
+
+ return 0;
+}
+
+int tryInsertUniqueRecord(NDBT_Step* step,
+ HugoOperations& hugoOps,
+ int& recordNum)
+{
+ Ndb* pNdb = GETNDB(step);
+ do
+ {
+ CHECKRET(hugoOps.startTransaction(pNdb) == 0);
+ CHECKRET(hugoOps.pkInsertRecord(pNdb,
+ recordNum,
+ 1, // NumRecords
+ 0) // UpdatesValue
+ == 0);
+ if (hugoOps.execute_Commit(pNdb) != 0)
+ {
+ NdbError err = hugoOps.getTransaction()->getNdbError();
+ hugoOps.closeTransaction(pNdb);
+ if (err.code == 839)
+ {
+ /* Unique constraint violation, try again with
+ * different record
+ */
+ recordNum++;
+ continue;
+ }
+ else
+ {
+ ERR(err);
+ return NDBT_FAILED;
+ }
+ }
+
+ hugoOps.closeTransaction(pNdb);
+ break;
+ } while (true);
+
+ return NDBT_OK;
+}
+
+
+int runConstraintDetails(NDBT_Context* ctx, NDBT_Step* step)
+{
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ Ndb* pNdb = GETNDB(step);
+
+ /* Steps in testcase
+ * 1) Choose a column to index - not pk or updates column
+ * 2) Insert a couple of unique rows
+ * 3) For a number of different batch sizes :
+ * i) Insert a row with a conflicting values
+ * ii) Update an existing row with a conflicting value
+ * Verify :
+ * - The correct error is received
+ * - The failing constraint is detected
+ * - The error details string is as expected.
+ */
+ HugoCalculator calc(*pTab);
+
+ /* Choose column to add unique index to */
+
+ int chosenCol = -1;
+ const char* idxName = "constraintCheck";
+
+ int rc = tryAddUniqueIndex(pNdb, pTab, idxName, calc, chosenCol);
+
+ if (rc)
+ {
+ if (rc == 1)
+ {
+ ndbout << "No suitable column in this table, skipping" << endl;
+ return NDBT_OK;
+ }
+ return NDBT_FAILED;
+ }
+
+ const NdbDictionary::Index* pIdx =
+ pNdb->getDictionary()->getIndex(idxName, pTab->getName());
+ CHECKRET(pIdx != 0);
+
+
+ /* Now insert a couple of rows */
+
+ HugoOperations hugoOps(*pTab);
+ int firstRecordNum = 0;
+ CHECKRET(tryInsertUniqueRecord(step, hugoOps, firstRecordNum) == NDBT_OK);
+ int secondRecordNum = firstRecordNum + 1;
+ CHECKRET(tryInsertUniqueRecord(step, hugoOps, secondRecordNum) == NDBT_OK);
+
+
+ /* Now we'll attempt to insert/update records
+ * in various sized batches and check the errors which
+ * are returned
+ */
+
+ int maxBatchSize = 10;
+ int recordOffset = secondRecordNum + 1;
+ char buff[NDB_MAX_TUPLE_SIZE];
+ Uint32 real_len;
+ CHECKRET(calc.calcValue(firstRecordNum, chosenCol, 0, &buff[0],
+ pTab->getColumn(chosenCol)->getSizeInBytes(),
+ &real_len) != 0);
+
+ for (int optype = 0; optype < 2; optype ++)
+ {
+ bool useInsert = (optype == 0);
+ ndbout << "Verifying constraint violation for "
+ << (useInsert?"Insert":"Update")
+ << " operations" << endl;
+
+ for (int batchSize = 1; batchSize <= maxBatchSize; batchSize++)
+ {
+ NdbTransaction* trans = pNdb->startTransaction();
+ CHECKRET(trans != 0);
+
+ for (int rows = 0; rows < batchSize; rows ++)
+ {
+ int rowId = recordOffset + rows;
+ NdbOperation* op = trans->getNdbOperation(pTab);
+ CHECKRET(op != 0);
+ if (useInsert)
+ {
+ CHECKRET(op->insertTuple() == 0);
+
+ CHECKRET(hugoOps.setValues(op, rowId, 0) == 0);
+
+ /* Now override setValue for the indexed column to cause
+ * constraint violation
+ */
+ CHECKRET(op->setValue(chosenCol, &buff[0], real_len) == 0);
+ }
+ else
+ {
+ /* Update value of 'second' row to conflict with
+ * first
+ */
+ CHECKRET(op->updateTuple() == 0);
+ CHECKRET(hugoOps.equalForRow(op, secondRecordNum) == 0);
+
+ CHECKRET(op->setValue(chosenCol, &buff[0], real_len) == 0);
+ }
+ }
+
+ CHECKRET(trans->execute(Commit) == -1);
+
+ NdbError err = trans->getNdbError();
+
+ ERR(err);
+
+ CHECKRET(err.code == 893);
+
+ /* Ugliness - current NdbApi puts index schema object id
+ * as abs. value of char* in NdbError struct
+ */
+
+ int idxObjId = (int) ((UintPtr) err.details - UintPtr(0));
+ char detailsBuff[100];
+ const char* errIdxName = NULL;
+
+ ndbout_c("Got details column val of %p and string of %s\n",
+ err.details, pNdb->getNdbErrorDetail(err,
+ &detailsBuff[0],
+ 100));
+ if (idxObjId == pIdx->getObjectId())
+ {
+ /* Insert / update failed on the constraint we added */
+ errIdxName = pIdx->getName();
+ }
+ else
+ {
+ /* We failed on a different constraint.
+ * Some NDBT tables already have constraints (e.g. I3)
+ * Check that the failing constraint contains our column
+ */
+ NdbDictionary::Dictionary::List tableIndices;
+
+ CHECKRET(pNdb->getDictionary()->listIndexes(tableIndices,
+ pTab->getName()) == 0);
+
+ bool ok = false;
+ for (unsigned ind = 0; ind < tableIndices.count; ind ++)
+ {
+ if (tableIndices.elements[ind].id == (unsigned) idxObjId)
+ {
+ const char* otherIdxName = tableIndices.elements[ind].name;
+ ndbout << "Found other violated constraint : " << otherIdxName << endl;
+ const NdbDictionary::Index* otherIndex =
+ pNdb->getDictionary()->getIndex(otherIdxName,
+ pTab->getName());
+ CHECKRET(otherIndex != NULL);
+
+ for (unsigned col = 0; col < otherIndex->getNoOfColumns(); col++)
+ {
+ if (strcmp(otherIndex->getColumn(col)->getName(),
+ pTab->getColumn(chosenCol)->getName()) == 0)
+ {
+ /* Found our column in the index */
+ ok = true;
+ errIdxName = otherIndex->getName();
+ break;
+ }
+ }
+
+ if (ok)
+ {
+ ndbout << " Constraint contains unique column " << endl;
+ break;
+ }
+ ndbout << " Constraint does not contain unique col - fail" << endl;
+ CHECKRET(false);
+ }
+ }
+
+ if (!ok)
+ {
+ ndbout << "Did not find violated constraint" << endl;
+ CHECKRET(false);
+ }
+ }
+
+ /* Finally verify the name returned is :
+ * <db>/<schema>/<table>/<index>
+ */
+ BaseString expected;
+
+ expected.assfmt("%s/%s/%s/%s",
+ pNdb->getDatabaseName(),
+ pNdb->getSchemaName(),
+ pTab->getName(),
+ errIdxName);
+
+ CHECKRET(strcmp(expected.c_str(), &detailsBuff[0]) == 0);
+
+ ndbout << " OK " << endl;
+
+ trans->close();
+ }
+ }
+
+ return NDBT_OK;
+}
+
int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
int records = ctx->getNumRecords();
@@ -2376,6 +2675,11 @@ TESTCASE("Bug46069", ""){
STEPS(runBug46069_scandel, 2);
FINALIZER(createPkIndex_Drop);
}
+TESTCASE("ConstraintDetails",
+ "Test that the details part of the returned NdbError is as "
+ "expected"){
+ INITIALIZER(runConstraintDetails);
+}
NDBT_TESTSUITE_END(testIndex);
int main(int argc, const char** argv){
=== modified file 'storage/ndb/test/ndbapi/testLcp.cpp'
--- a/storage/ndb/test/ndbapi/testLcp.cpp 2009-09-25 13:38:00 +0000
+++ b/storage/ndb/test/ndbapi/testLcp.cpp 2009-12-03 05:53:33 +0000
@@ -64,8 +64,6 @@ static int commit();
static int restart();
static int validate();
-#define require(x) { bool b = x; if(!b){g_err << __LINE__ << endl; abort();}}
-
int
main(int argc, char ** argv){
ndb_init();
=== modified file 'storage/ndb/test/ndbapi/testMgmd.cpp'
--- a/storage/ndb/test/ndbapi/testMgmd.cpp 2009-10-06 12:17:23 +0000
+++ b/storage/ndb/test/ndbapi/testMgmd.cpp 2009-11-17 18:13:29 +0000
@@ -613,6 +613,176 @@ int runTestBug42015(NDBT_Context* ctx, N
}
+int runTestNowaitNodes(NDBT_Context* ctx, NDBT_Step* step)
+{
+ MgmdProcessList mgmds;
+ NDBT_Workingdir wd("test_mgmd"); // temporary working directory
+
+ // Create config.ini
+ Properties config = ConfigFactory::create(2);
+ CHECK(ConfigFactory::write_config_ini(config,
+ path(wd.path(),
+ "config.ini",
+ NULL).c_str()));
+ // Start first ndb_mgmd
+ {
+ Mgmd* mgmd1 = new Mgmd(1);
+ CHECK(mgmd1->start_from_config_ini(wd.path(),
+ "--initial",
+ "--nowait-nodes=2",
+ NULL));
+ mgmds.push_back(mgmd1);
+
+ // Connect the ndb_mgmd
+ CHECK(mgmd1->connect(config));
+
+ // wait for confirmed config
+ CHECK(mgmd1->wait_confirmed_config());
+
+ // Check binary config file created
+ CHECK(file_exists(path(wd.path(),
+ "ndb_1_config.bin.1",
+ NULL).c_str()));
+ }
+
+ // Start second ndb_mgmd
+ {
+ Mgmd* mgmd2 = new Mgmd(2);
+ CHECK(mgmd2->start_from_config_ini(wd.path(),
+ "--initial",
+ NULL));
+ mgmds.push_back(mgmd2);
+
+ // Connect the ndb_mgmd
+ CHECK(mgmd2->connect(config));
+
+ // wait for confirmed config
+ CHECK(mgmd2->wait_confirmed_config());
+
+ // Check binary config file created
+ CHECK(file_exists(path(wd.path(),
+ "ndb_2_config.bin.1",
+ NULL).c_str()));
+
+ }
+
+ // Create new config.ini
+ g_err << "** Create config2.ini" << endl;
+ CHECK(ConfigFactory::put(config, "ndb_mgmd", 1, "ArbitrationDelay", 100));
+ CHECK(ConfigFactory::write_config_ini(config,
+ path(wd.path(),
+ "config2.ini",
+ NULL).c_str()));
+
+ g_err << "** Reload second mgmd from config2.ini" << endl;
+ {
+ Mgmd* mgmd2 = mgmds[1];
+ CHECK(mgmd2->stop());
+ // Start from config2.ini
+ CHECK(mgmd2->start_from_config_ini(wd.path(),
+ "-f config2.ini",
+ "--reload", NULL));
+ CHECK(mgmd2->connect(config));
+ CHECK(mgmd2->wait_confirmed_config());
+
+ CHECK(file_exists(path(wd.path(),
+ "ndb_1_config.bin.1",
+ NULL).c_str()));
+ CHECK(file_exists(path(wd.path(),
+ "ndb_2_config.bin.1",
+ NULL).c_str()));
+
+ // Both ndb_mgmd(s) should have reloaded and new binary config exist
+ CHECK(file_exists(path(wd.path(),
+ "ndb_1_config.bin.2",
+ NULL).c_str()));
+ CHECK(file_exists(path(wd.path(),
+ "ndb_2_config.bin.2",
+ NULL).c_str()));
+ }
+
+ // Stop the ndb_mgmd(s)
+ for (unsigned i = 0; i < mgmds.size(); i++)
+ CHECK(mgmds[i]->stop());
+
+ return NDBT_OK;
+}
+
+
+int runTestNowaitNodes2(NDBT_Context* ctx, NDBT_Step* step)
+{
+ int ret;
+ NDBT_Workingdir wd("test_mgmd"); // temporary working directory
+
+ // Create config.ini
+ Properties config = ConfigFactory::create(2);
+ CHECK(ConfigFactory::write_config_ini(config,
+ path(wd.path(),
+ "config.ini",
+ NULL).c_str()));
+
+ g_err << "** Start mgmd1 from config.ini" << endl;
+ Mgmd* mgmd1 = new Mgmd(1);
+ CHECK(mgmd1->start_from_config_ini(wd.path(),
+ "--initial",
+ "--nowait-nodes=1-255",
+ NULL));
+ CHECK(mgmd1->connect(config));
+ CHECK(mgmd1->wait_confirmed_config());
+
+ // check config files exist
+ CHECK(file_exists(path(wd.path(),
+ "ndb_1_config.bin.1",
+ NULL).c_str()));
+
+ g_err << "** Create config2.ini" << endl;
+ CHECK(ConfigFactory::put(config, "ndb_mgmd", 1, "ArbitrationDelay", 100));
+ CHECK(ConfigFactory::write_config_ini(config,
+ path(wd.path(),
+ "config2.ini",
+ NULL).c_str()));
+
+ g_err << "** Start mgmd2 from config2.ini" << endl;
+ Mgmd* mgmd2 = new Mgmd(2);
+ CHECK(mgmd2->start_from_config_ini(wd.path(),
+ "-f config2.ini",
+ "--initial",
+ "--nowait-nodes=1-255",
+ NULL));
+ CHECK(mgmd2->wait(ret));
+ CHECK(ret == 1);
+
+ CHECK(mgmd1->stop());
+
+ g_err << "** Start mgmd2 again from config2.ini" << endl;
+ CHECK(mgmd2->start_from_config_ini(wd.path(),
+ "-f config2.ini",
+ "--initial",
+ "--nowait-nodes=1-255",
+ NULL));
+
+
+ CHECK(mgmd2->connect(config));
+ CHECK(mgmd2->wait_confirmed_config());
+
+ // check config files exist
+ CHECK(file_exists(path(wd.path(),
+ "ndb_2_config.bin.1",
+ NULL).c_str()));
+
+ g_err << "** Start mgmd1 from config.ini, mgmd2 should shutdown" << endl;
+ CHECK(mgmd1->start_from_config_ini(wd.path(),
+ "--initial",
+ "--nowait-nodes=1-255",
+ NULL));
+ CHECK(mgmd2->wait(ret));
+ CHECK(ret == 1);
+
+ CHECK(mgmd1->stop());
+
+ return NDBT_OK;
+}
+
NDBT_TESTSUITE(testMgmd);
DRIVER(DummyDriver); /* turn off use of NdbApi */
@@ -633,6 +803,19 @@ TESTCASE("Bug42015",
{
INITIALIZER(runTestBug42015);
}
+TESTCASE("NowaitNodes",
+ "Test that one mgmd(of 2) can start alone with usage "
+ "of --nowait-nodes, then start the second mgmd and it should join")
+{
+ INITIALIZER(runTestNowaitNodes);
+}
+TESTCASE("NowaitNodes2",
+ "Test that one mgmd(of 2) can start alone with usage "
+ "of --nowait-nodes, then start the second mgmd from different "
+ "configuration and the one with lowest nodeid should shutdown")
+{
+ INITIALIZER(runTestNowaitNodes2);
+}
NDBT_TESTSUITE_END(testMgmd);
=== modified file 'storage/ndb/test/ndbapi/testNdbinfo.cpp'
--- a/storage/ndb/test/ndbapi/testNdbinfo.cpp 2009-11-08 12:52:27 +0000
+++ b/storage/ndb/test/ndbapi/testNdbinfo.cpp 2009-11-17 16:55:50 +0000
@@ -20,6 +20,7 @@
#include <NDBT_Test.hpp>
#include "../../src/ndbapi/NdbInfo.hpp"
+#include <NdbRestarter.hpp>
int runTestNdbInfo(NDBT_Context* ctx, NDBT_Step* step)
{
@@ -121,10 +122,10 @@ int runScanAll(NDBT_Context* ctx, NDBT_S
columnId++;
// At least one column
assert(columnId >= 1);
-
- if(scanOp->execute() != 0)
+ int ret;
+ if((ret = scanOp->execute()) != 0)
{
- g_err << "scanOp->execute failed" << endl;
+ g_err << "scanOp->execute failed, ret: " << ret << endl;
return NDBT_FAILED;
}
@@ -143,6 +144,20 @@ int runScanAll(NDBT_Context* ctx, NDBT_S
return NDBT_FAILED;
}
+
+int runScanAllUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
+ int i = 0;
+ while (ctx->isTestStopped() == false) {
+ g_info << i << ": ";
+ if (runScanAll(ctx, step) != NDBT_OK){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+
int runScanStop(NDBT_Context* ctx, NDBT_Step* step)
{
NdbInfo ndbinfo(&ctx->m_cluster_connection, "ndbinfo/");
@@ -372,6 +387,84 @@ int runTestTable(NDBT_Context* ctx, NDBT
return NDBT_OK;
}
+int runRestarter(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int sync_threads = ctx->getProperty("SyncThreads", (unsigned)0);
+ int sleep0 = ctx->getProperty("Sleep0", (unsigned)0);
+ int sleep1 = ctx->getProperty("Sleep1", (unsigned)0);
+ int randnode = ctx->getProperty("RandNode", (unsigned)0);
+ NdbRestarter restarter;
+ int i = 0;
+ int lastId = 0;
+
+ if (restarter.getNumDbNodes() < 2){
+ ctx->stopTest();
+ return NDBT_OK;
+ }
+
+ if(restarter.waitClusterStarted() != 0){
+ g_err << "Cluster failed to start" << endl;
+ return NDBT_FAILED;
+ }
+
+ loops *= (restarter.getNumDbNodes() > 2 ? 2 : restarter.getNumDbNodes());
+ if (loops < restarter.getNumDbNodes())
+ loops = restarter.getNumDbNodes();
+
+ while(i<loops && result != NDBT_FAILED && !ctx->isTestStopped()){
+
+ int id = lastId % restarter.getNumDbNodes();
+ if (randnode == 1)
+ {
+ id = rand() % restarter.getNumDbNodes();
+ }
+ int nodeId = restarter.getDbNodeId(id);
+ ndbout << "Restart node " << nodeId << endl;
+ if(restarter.restartOneDbNode(nodeId, false, true, true) != 0){
+ g_err << "Failed to restartNextDbNode" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+
+ if (restarter.waitNodesNoStart(&nodeId, 1))
+ {
+ g_err << "Failed to waitNodesNoStart" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+
+ if (sleep1)
+ NdbSleep_MilliSleep(sleep1);
+
+ if (restarter.startNodes(&nodeId, 1))
+ {
+ g_err << "Failed to start node" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+
+ if(restarter.waitClusterStarted() != 0){
+ g_err << "Cluster failed to start" << endl;
+ result = NDBT_FAILED;
+ break;
+ }
+
+ if (sleep0)
+ NdbSleep_MilliSleep(sleep0);
+
+ ctx->sync_up_and_wait("PauseThreads", sync_threads);
+
+ lastId++;
+ i++;
+ }
+
+ ctx->stopTest();
+
+ return result;
+}
+
+
NDBT_TESTSUITE(testNdbinfo);
TESTCASE("Ndbinfo",
@@ -399,6 +492,13 @@ TESTCASE("TestTable",
"of rows which will depend on how many TUP blocks are configured"){
STEP(runTestTable);
}
+#if 0
+TESTCASE("NodeRestart", "Scan NdbInfo tables while restarting nodes"){
+ TC_PROPERTY("Sleep0", 29000); // Between restarts
+ STEP(runRestarter);
+ STEPS(runScanAllUntilStopped, 1);
+}
+#endif
NDBT_TESTSUITE_END(testNdbinfo);
=== modified file 'storage/ndb/test/ndbapi/testPartitioning.cpp'
--- a/storage/ndb/test/ndbapi/testPartitioning.cpp 2009-05-27 15:21:45 +0000
+++ b/storage/ndb/test/ndbapi/testPartitioning.cpp 2009-11-17 13:10:09 +0000
@@ -814,7 +814,20 @@ load_dist_table(Ndb* pNdb, int records,
CHECKNOTNULL(trans->insertTuple(distRecord, buf,
NULL, &opts, sizeof(opts)), trans);
- CHECK(trans->execute(NdbTransaction::Commit), trans);
+ if (trans->execute(NdbTransaction::Commit) != 0)
+ {
+ NdbError err = trans->getNdbError();
+ if (err.status == NdbError::TemporaryError)
+ {
+ ndbout << err << endl;
+ NdbSleep_MilliSleep(50);
+ r--; // just retry
+ }
+ else
+ {
+ CHECK(-1, trans);
+ }
+ }
trans->close();
}
=== modified file 'storage/ndb/test/run-test/CMakeLists.txt'
--- a/storage/ndb/test/run-test/CMakeLists.txt 2009-11-13 04:50:47 +0000
+++ b/storage/ndb/test/run-test/CMakeLists.txt 2009-11-16 05:21:53 +0000
@@ -36,6 +36,7 @@ ADD_EXECUTABLE(atrt main.cpp setup.cpp f
INSTALL(TARGETS atrt DESTINATION bin)
INSTALL(FILES
+ atrt-testBackup
atrt-analyze-result.sh
atrt-backtrace.sh
atrt-gather-result.sh
=== modified file 'storage/ndb/test/run-test/atrt.hpp'
--- a/storage/ndb/test/run-test/atrt.hpp 2009-11-13 04:55:46 +0000
+++ b/storage/ndb/test/run-test/atrt.hpp 2009-12-03 05:53:33 +0000
@@ -125,7 +125,6 @@ struct atrt_testcase
extern Logger g_logger;
-void require(bool x);
bool parse_args(int argc, char** argv);
bool setup_config(atrt_config&, const char * mysqld);
bool configure(atrt_config&, int setup);
=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt 2009-11-02 17:15:29 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt 2009-12-03 10:19:24 +0000
@@ -274,6 +274,10 @@ max-time: 2500
cmd: testIndex
args: -n BuildDuring T6
+max-time: 2500
+cmd: testIndex
+args: -n BuildDuring_O T6
+
max-time: 600
cmd: testIndex
args: -n Bug46069 T1
@@ -1469,6 +1473,32 @@ cmd: testBasic
args: -n DDInsertFailUpdateBatch
max-time: 300
+cmd: testBlobs
+args: -skip hp -bug 28116
+
+max-time: 300
cmd: testNdbApi
args: -n FragmentedApiFailure T1
+# Series of short (signal train) request generation/handling tests
+# Start
+max-time: 500
+cmd: testBasic
+args: --forceshortreqs -n PkUpdate
+
+max-time: 300
+cmd: testIndex
+args: --forceshortreqs -n InsertDelete T2
+
+max-time: 2500
+cmd: testPartitioning
+args: --forceshortreqs
+
+# End of short (signal train) handling tests
+
+max-time: 300
+cmd: testIndex
+args: -n ConstraintDetails
+
+
+
=== modified file 'storage/ndb/test/run-test/daily-devel-tests.txt'
--- a/storage/ndb/test/run-test/daily-devel-tests.txt 2009-09-15 10:13:15 +0000
+++ b/storage/ndb/test/run-test/daily-devel-tests.txt 2009-11-30 10:45:52 +0000
@@ -112,10 +112,6 @@ args: -n NFNR3_O T6 T13
max-time: 2500
cmd: testIndex
-args: -n BuildDuring_O T6
-
-max-time: 2500
-cmd: testIndex
args: -l 2 -n SR1_O T6 T13
# dict trans
=== modified file 'storage/ndb/test/run-test/main.cpp'
--- a/storage/ndb/test/run-test/main.cpp 2009-11-13 04:54:50 +0000
+++ b/storage/ndb/test/run-test/main.cpp 2009-12-03 05:53:33 +0000
@@ -1404,13 +1404,6 @@ started:
return true;
}
-void
-require(bool x)
-{
- if (!x)
- abort();
-}
-
bool
reset_config(atrt_config & config)
{
=== modified file 'storage/ndb/test/src/CMakeLists.txt'
--- a/storage/ndb/test/src/CMakeLists.txt 2009-10-07 06:35:51 +0000
+++ b/storage/ndb/test/src/CMakeLists.txt 2009-11-18 11:05:02 +0000
@@ -17,7 +17,8 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/
${CMAKE_SOURCE_DIR}/storage/ndb/src/common/mgmcommon
${CMAKE_SOURCE_DIR}/storage/ndb/include/mgmcommon
${CMAKE_SOURCE_DIR}/storage/ndb/include/kernel
- ${CMAKE_SOURCE_DIR}/storage/ndb/src/mgmapi)
+ ${CMAKE_SOURCE_DIR}/storage/ndb/src/mgmapi
+ ${CMAKE_SOURCE_DIR}/storage/ndb/include/debugger)
INCLUDE(${CMAKE_SOURCE_DIR}/storage/ndb/config/type_ndbapitest.cmake)
ADD_LIBRARY(ndbNDBT STATIC
=== modified file 'storage/ndb/test/src/Makefile.am'
--- a/storage/ndb/test/src/Makefile.am 2009-09-16 12:53:49 +0000
+++ b/storage/ndb/test/src/Makefile.am 2009-11-18 11:05:02 +0000
@@ -30,7 +30,7 @@ libNDBT_a_SOURCES = \
CpcClient.cpp NdbMixRestarter.cpp NDBT_Thread.cpp DbUtil.cpp \
SocketInputStream2.cpp NDBT_Find.cpp
-INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/common/mgmcommon -I$(top_srcdir)/storage/ndb/include/mgmcommon -I$(top_srcdir)/storage/ndb/include/kernel -I$(top_srcdir)/storage/ndb/src/mgmapi -I$(top_srcdir)/include
+INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/common/mgmcommon -I$(top_srcdir)/storage/ndb/include/mgmcommon -I$(top_srcdir)/storage/ndb/include/kernel -I$(top_srcdir)/storage/ndb/src/mgmapi -I$(top_srcdir)/include -I$(top_srcdir)/storage/ndb/include/debugger
include $(top_srcdir)/storage/ndb/config/common.mk.am
include $(top_srcdir)/storage/ndb/config/type_ndbapitest.mk.am
=== modified file 'storage/ndb/test/src/NDBT_Test.cpp'
--- a/storage/ndb/test/src/NDBT_Test.cpp 2009-11-11 18:04:01 +0000
+++ b/storage/ndb/test/src/NDBT_Test.cpp 2009-11-18 23:14:19 +0000
@@ -268,6 +268,7 @@ NDBT_Step::NDBT_Step(NDBT_TestCase* ptes
{
}
+#include <../../src/ndbapi/NdbImpl.hpp>
int
NDBT_Step::setUp(Ndb_cluster_connection& con){
@@ -282,6 +283,9 @@ NDBT_Step::setUp(Ndb_cluster_connection&
m_ndb = new Ndb(&con, "TEST_DB" );
m_ndb->init(1024);
+ NdbImpl::setForceShortRequests(m_ndb,
+ m_ctx->suite->getForceShort());
+
int result = m_ndb->waitUntilReady(300); // 5 minutes
if (result != 0){
g_err << "Ndb was not ready" << endl;
@@ -792,6 +796,7 @@ NDBT_TestSuite::NDBT_TestSuite(const cha
temporaryTables = false;
runonce = false;
m_noddl = false;
+ m_forceShort = false;
}
@@ -833,6 +838,10 @@ bool NDBT_TestSuite::getLogging() const
return m_logging;
}
+bool NDBT_TestSuite::getForceShort() const {
+ return m_forceShort;
+}
+
bool NDBT_TestSuite::timerIsOn(){
return (timer != 0);
}
@@ -927,6 +936,8 @@ NDBT_TestSuite::executeOneCtx(Ndb_cluste
Ndb ndb(&con, "TEST_DB");
ndb.init(1024);
+ NdbImpl::setForceShortRequests(&ndb, m_forceShort);
+
int result = ndb.waitUntilReady(300); // 5 minutes
if (result != 0){
g_err << name <<": Ndb was not ready" << endl;
@@ -1276,6 +1287,7 @@ static int opt_seed = 0;
static int opt_nologging = 0;
static int opt_temporary = 0;
static int opt_noddl = 0;
+static int opt_forceShort = 0;
static struct my_option my_long_options[] =
{
@@ -1316,6 +1328,9 @@ static struct my_option my_long_options[
{ "noddl", 0, "Don't create/drop tables as part of running tests",
(uchar**) &opt_noddl, (uchar**) &opt_noddl, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "forceshortreqs", 0, "Use short signals for NdbApi requests",
+ (uchar**) &opt_forceShort, (uchar**) &opt_forceShort, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -1386,6 +1401,7 @@ int NDBT_TestSuite::execute(int argc, co
setLogging(false);
temporaryTables = opt_temporary;
m_noddl = opt_noddl;
+ m_forceShort = opt_forceShort;
if (opt_seed == 0)
{
=== modified file 'storage/ndb/tools/ndbinfo_sql.cpp'
--- a/storage/ndb/tools/ndbinfo_sql.cpp 2009-11-12 21:25:49 +0000
+++ b/storage/ndb/tools/ndbinfo_sql.cpp 2009-11-13 13:43:02 +0000
@@ -98,8 +98,8 @@ struct view {
" WHEN 5 THEN \"FILE_BUFFERS\""
" WHEN 6 THEN \"TRANSPORTER_BUFFERS\""
" ELSE \"<unknown>\" "
- " END AS resource_id, "
- "reserved, used, max, high "
+ " END AS resource_name, "
+ "reserved, used, max "
"FROM <NDBINFO_DB>.<TABLE_PREFIX>resources"
},
{ "counters",
@@ -142,15 +142,15 @@ struct view {
"FROM <NDBINFO_DB>.<TABLE_PREFIX>nodes"
},
{ "memoryusage",
- "SELECT node_id, \"DATA_MEMORY\" "
- "used, max, high "
+ "SELECT node_id, \"DATA_MEMORY\", "
+ "used, max "
"FROM <NDBINFO_DB>.<TABLE_PREFIX>resources "
- "WHERE resource_id = \"DATA_MEMORY|\" "
+ "WHERE resource_id = 3 "
"UNION "
- "SELECT node_id, \"INDEX_MEMORY\" "
- "used, total, high "
+ "SELECT node_id, \"INDEX_MEMORY\", "
+ "used, total "
"FROM <NDBINFO_DB>.<TABLE_PREFIX>pools "
- "WHERE pool_name = \"Index memory|\" "
+ "WHERE block_number = 248 AND pool_name = \"Index memory\" "
}
};
=== modified file 'storage/ndb/tools/restore/Restore.cpp'
--- a/storage/ndb/tools/restore/Restore.cpp 2009-09-08 12:10:53 +0000
+++ b/storage/ndb/tools/restore/Restore.cpp 2009-12-02 15:01:19 +0000
@@ -501,8 +501,12 @@ RestoreMetaData::markSysTables()
strcmp(tableName, OLD_NDB_REP_DB "/def/" OLD_NDB_SCHEMA_TABLE) == 0 ||
strcmp(tableName, NDB_REP_DB "/def/" NDB_APPLY_TABLE) == 0 ||
strcmp(tableName, NDB_REP_DB "/def/" NDB_SCHEMA_TABLE)== 0 )
-
- table->isSysTable = true;
+ {
+ table->m_isSysTable = true;
+ if (strcmp(tableName, "SYSTAB_0") == 0 ||
+ strcmp(tableName, "sys/def/SYSTAB_0") == 0)
+ table->m_isSYSTAB_0 = true;
+ }
}
for (i = 0; i < getNoOfTables(); i++) {
TableS* blobTable = allTables[i];
@@ -517,8 +521,8 @@ RestoreMetaData::markSysTables()
for (j = 0; j < getNoOfTables(); j++) {
TableS* table = allTables[j];
if (table->getTableId() == (Uint32) id1) {
- if (table->isSysTable)
- blobTable->isSysTable = true;
+ if (table->m_isSysTable)
+ blobTable->m_isSysTable = true;
blobTable->m_main_table = table;
blobTable->m_main_column_id = id2;
break;
@@ -565,7 +569,16 @@ RestoreMetaData::fixBlobs()
break;
}
}
- assert(blobTable != NULL);
+ if (blobTable == NULL)
+ {
+ /* Corrupt backup, has main table, but no blob table */
+ err << "Table " << table->m_dictTable->getName()
+ << " has blob column " << j << " ("
+ << c->m_name.c_str()
+ << ") with missing parts table in backup."
+ << endl;
+ return false;
+ }
assert(blobTable->m_dictTable != NULL);
NdbTableImpl& bt = NdbTableImpl::getImpl(*blobTable->m_dictTable);
const char* colName = c->m_blobVersion == 1 ? "DATA" : "NDB$DATA";
@@ -662,7 +675,8 @@ TableS::TableS(Uint32 version, NdbTableI
m_max_auto_val= 0;
m_noOfRecords= 0;
backupVersion = version;
- isSysTable = false;
+ m_isSysTable = false;
+ m_isSYSTAB_0 = false;
m_main_table = NULL;
m_main_column_id = ~(Uint32)0;
@@ -1742,6 +1756,35 @@ void TableS::createAttr(NdbDictionary::C
m_variableAttribs.push_back(d);
} // TableS::createAttr
+bool
+TableS::get_auto_data(const TupleS & tuple, Uint32 * syskey, Uint64 * nextid) const
+{
+ /*
+ Read current (highest) auto_increment value for
+ a table. Currently there can only be one per table.
+ The values are stored in sustable SYSTAB_0 as
+ {SYSKEY,NEXTID} values where SYSKEY (32-bit) is
+ the table_id and NEXTID (64-bit) is the next auto_increment
+ value in the sequence (note though that sequences of
+ values can have been fetched and that are cached in NdbAPI).
+ SYSTAB_0 can contain other data so we need to check that
+ the found SYSKEY value is a valid table_id (< 0x10000000).
+ */
+ AttributeData * attr_data = tuple.getData(0);
+ const AttributeDesc * attr_desc = tuple.getDesc(0);
+ const AttributeS attr1 = {attr_desc, *attr_data};
+ memcpy(syskey ,attr1.Data.u_int32_value, sizeof(Uint32));
+ attr_data = tuple.getData(1);
+ attr_desc = tuple.getDesc(1);
+ const AttributeS attr2 = {attr_desc, *attr_data};
+ memcpy(nextid, attr2.Data.u_int64_value, sizeof(Uint64));
+ if (*syskey < 0x10000000)
+ {
+ return true;
+ }
+ return false;
+};
+
Uint16 Twiddle16(Uint16 in)
{
Uint16 retVal = 0;
=== modified file 'storage/ndb/tools/restore/Restore.hpp'
--- a/storage/ndb/tools/restore/Restore.hpp 2009-08-18 13:21:50 +0000
+++ b/storage/ndb/tools/restore/Restore.hpp 2009-12-01 10:15:25 +0000
@@ -168,7 +168,9 @@ class TableS {
AttributeDesc * m_auto_val_attrib;
Uint64 m_max_auto_val;
- bool isSysTable;
+ bool m_isSysTable;
+ bool m_isSYSTAB_0;
+
TableS *m_main_table;
Uint32 m_main_column_id;
Uint32 m_local_id;
@@ -264,6 +266,9 @@ public:
if(v > m_max_auto_val)
m_max_auto_val= v;
};
+
+ bool get_auto_data(const TupleS & tuple, Uint32 * syskey, Uint64 * nextid) const;
+
/**
* Get attribute descriptor
*/
@@ -276,14 +281,19 @@ public:
}
bool getSysTable() const {
- return isSysTable;
+ return m_isSysTable;
}
const TableS *getMainTable() const {
return m_main_table;
}
- TableS& operator=(TableS& org) ;
+ TableS& operator=(TableS& org) ;
+
+ inline
+ const bool isSYSTAB_0() const {
+ return m_isSYSTAB_0;
+ }
}; // TableS;
class RestoreLogIterator;
@@ -496,6 +506,8 @@ NdbOut& operator<<(NdbOut& ndbout, const
NdbOut& operator<<(NdbOut& ndbout, const LogEntry&);
NdbOut& operator<<(NdbOut& ndbout, const RestoreMetaData&);
+bool readSYSTAB_0(const TupleS & tup, Uint32 * syskey, Uint64 * nextid);
+
#endif
=== modified file 'storage/ndb/tools/restore/consumer_printer.cpp'
--- a/storage/ndb/tools/restore/consumer_printer.cpp 2009-05-26 18:53:34 +0000
+++ b/storage/ndb/tools/restore/consumer_printer.cpp 2009-11-25 12:37:14 +0000
@@ -18,6 +18,7 @@
#include "consumer_printer.hpp"
extern FilteredNdbOut info;
+extern bool ga_dont_ignore_systab_0;
extern NdbRecordPrintFormat g_ndbrecord_print_format;
extern const char *tab_path;
@@ -44,6 +45,9 @@ BackupPrinter::tuple(const TupleS & tup,
info.setLevel(254);
info << tup.getTable()->getTableName() << "; ";
}
+ const TableS * table = tup.getTable();
+ if ((!ga_dont_ignore_systab_0) && table->isSYSTAB_0())
+ return;
m_ndbout << tup << g_ndbrecord_print_format.lines_terminated_by;
}
}
=== modified file 'storage/ndb/tools/restore/consumer_restore.cpp'
--- a/storage/ndb/tools/restore/consumer_restore.cpp 2009-08-18 13:21:50 +0000
+++ b/storage/ndb/tools/restore/consumer_restore.cpp 2009-12-01 10:15:25 +0000
@@ -176,8 +176,15 @@ BackupRestore::get_table(const NdbDictio
int cnt, id1, id2;
char db[256], schema[256];
- if((cnt = sscanf(tab->getName(), "%[^/]/%[^/]/NDB$BLOB_%d_%d",
- db, schema, &id1, &id2)) == 4){
+ if (strcmp(tab->getName(), "SYSTAB_0") == 0 ||
+ strcmp(tab->getName(), "sys/def/SYSTAB_0") == 0) {
+ /*
+ Restore SYSTAB_0 to itself
+ */
+ m_cache.m_new_table = tab;
+ }
+ else if((cnt = sscanf(tab->getName(), "%[^/]/%[^/]/NDB$BLOB_%d_%d",
+ db, schema, &id1, &id2)) == 4){
m_ndb->setDatabaseName(db);
m_ndb->setSchemaName(schema);
@@ -1442,6 +1449,8 @@ BackupRestore::endOfTables(){
void BackupRestore::tuple(const TupleS & tup, Uint32 fragmentId)
{
+ const TableS * tab = tup.getTable();
+
if (!m_restore)
return;
@@ -1458,12 +1467,19 @@ void BackupRestore::tuple(const TupleS &
if (cb == 0)
assert(false);
- m_free_callback = cb->next;
cb->retries = 0;
cb->fragId = fragmentId;
cb->tup = tup; // must do copy!
- tuple_a(cb);
+ if (tab->isSYSTAB_0())
+ {
+ tuple_SYSTAB_0(cb, *tab);
+ return;
+ }
+
+ m_free_callback = cb->next;
+
+ tuple_a(cb);
}
void BackupRestore::tuple_a(restore_callback_t *cb)
@@ -1637,6 +1653,59 @@ void BackupRestore::tuple_a(restore_call
exitHandler();
}
+void BackupRestore::tuple_SYSTAB_0(restore_callback_t *cb,
+ const TableS & tab)
+{
+ const TupleS & tup = cb->tup;
+ Uint32 syskey;
+ Uint64 nextid;
+
+ if (tab.get_auto_data(tup, &syskey, &nextid))
+ {
+ /*
+ We found a valid auto_increment value in SYSTAB_0
+ where syskey is a table_id and nextid is next auto_increment
+ value.
+ */
+ if (restoreAutoIncrement(cb, syskey, nextid) == -1)
+ exitHandler();
+ }
+}
+
+int BackupRestore::restoreAutoIncrement(restore_callback_t *cb,
+ Uint32 tableId, Uint64 value)
+{
+ /*
+ Restore the auto_increment value found in SYSTAB_0 from
+ backup. First map the old table id to the new table while
+ also checking that it is an actual table will some auto_increment
+ column. Note that the SYSTAB_0 table in the backup can contain
+ stale information from dropped tables.
+ */
+ int result = 0;
+ const NdbDictionary::Table* tab = (tableId < m_new_tables.size())? m_new_tables[tableId] : NULL;
+ if (tab && tab->getNoOfAutoIncrementColumns() > 0)
+ {
+ /*
+ Write the auto_increment value back into SYSTAB_0.
+ This is done in a separate transaction and could possibly
+ fail, so we retry if a temporary error is received.
+ */
+ while (cb->retries < 10)
+ {
+ if ((result = m_ndb->setAutoIncrementValue(tab, value, false) == -1))
+ {
+ if (errorHandler(cb))
+ {
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ return result;
+}
+
void BackupRestore::cback(int result, restore_callback_t *cb)
{
m_transactions--;
=== modified file 'storage/ndb/tools/restore/consumer_restore.hpp'
--- a/storage/ndb/tools/restore/consumer_restore.hpp 2009-08-18 13:21:50 +0000
+++ b/storage/ndb/tools/restore/consumer_restore.hpp 2009-12-01 10:15:25 +0000
@@ -89,6 +89,9 @@ public:
virtual void tuple(const TupleS &, Uint32 fragId);
virtual void tuple_free();
virtual void tuple_a(restore_callback_t *cb);
+ virtual void tuple_SYSTAB_0(restore_callback_t *cb, const TableS &);
+ virtual int restoreAutoIncrement(restore_callback_t *cb,
+ Uint32 tableId, Uint64 value);
virtual void cback(int result, restore_callback_t *cb);
virtual bool errorHandler(restore_callback_t *cb);
virtual void exitHandler();
=== modified file 'storage/ndb/tools/restore/restore_main.cpp'
--- a/storage/ndb/tools/restore/restore_main.cpp 2009-08-18 13:21:50 +0000
+++ b/storage/ndb/tools/restore/restore_main.cpp 2009-12-02 13:54:07 +0000
@@ -37,7 +37,7 @@ static Uint32 g_tableCompabilityMask = 0
static int ga_nodeId = 0;
static int ga_nParallelism = 128;
static int ga_backupId = 0;
-static bool ga_dont_ignore_systab_0 = false;
+bool ga_dont_ignore_systab_0 = false;
static bool ga_no_upgrade = false;
static bool ga_promote_attributes = false;
static Vector<class BackupConsumer *> g_consumers;
@@ -64,6 +64,17 @@ Vector<BaseString> g_include_databases,
NdbRecordPrintFormat g_ndbrecord_print_format;
unsigned int opt_no_binlog;
+class RestoreOption
+{
+public:
+ virtual ~RestoreOption() { }
+ int optid;
+ BaseString argument;
+};
+
+Vector<class RestoreOption *> g_include_exclude;
+static void save_include_exclude(int optid, char * argument);
+
/**
* print and restore flags
*/
@@ -183,7 +194,7 @@ static struct my_option my_long_options[
(uchar**) &ga_backupPath, (uchar**) &ga_backupPath, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ "dont_ignore_systab_0", 'f',
- "Experimental. Do not ignore system table during restore.",
+ "Do not ignore system table during --print-data.",
(uchar**) &ga_dont_ignore_systab_0, (uchar**) &ga_dont_ignore_systab_0, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ "ndb-nodegroup-map", OPT_NDB_NODEGROUP_MAP,
@@ -419,6 +430,12 @@ get_one_option(int optid, const struct m
exit(NDBT_ProgramExit(NDBT_WRONGARGS));
}
break;
+ case OPT_INCLUDE_DATABASES:
+ case OPT_EXCLUDE_DATABASES:
+ case OPT_INCLUDE_TABLES:
+ case OPT_EXCLUDE_TABLES:
+ save_include_exclude(optid, argument);
+ break;
}
return 0;
}
@@ -733,7 +750,7 @@ clearConsumers()
static inline bool
checkSysTable(const TableS* table)
{
- return ga_dont_ignore_systab_0 || ! table->getSysTable();
+ return ! table->getSysTable();
}
static inline bool
@@ -757,8 +774,13 @@ isIndex(const TableS* table)
}
static inline bool
-isInList(BaseString &needle, Vector<BaseString> &lst)
+isSYSTAB_0(const TableS* table)
{
+ return table->isSYSTAB_0();
+}
+
+static inline bool
+isInList(BaseString &needle, Vector<BaseString> &lst){
unsigned int i= 0;
for (i= 0; i < lst.size(); i++)
{
@@ -783,6 +805,100 @@ getTableName(const TableS* table)
return table_name;
}
+static void save_include_exclude(int optid, char * argument)
+{
+ BaseString arg = argument;
+ Vector<BaseString> args;
+ arg.split(args, ",");
+ for (uint i = 0; i < args.size(); i++)
+ {
+ RestoreOption * option = new RestoreOption();
+ BaseString arg;
+
+ option->optid = optid;
+ switch (optid) {
+ case OPT_INCLUDE_TABLES:
+ case OPT_EXCLUDE_TABLES:
+ if (makeInternalTableName(args[i], arg))
+ {
+ info << "`" << args[i] << "` is not a valid tablename!" << endl;
+ exit(NDBT_ProgramExit(NDBT_WRONGARGS));
+ }
+ break;
+ default:
+ arg = args[i];
+ break;
+ }
+ option->argument = arg;
+ g_include_exclude.push_back(option);
+ }
+}
+static bool check_include_exclude(BaseString database, BaseString table)
+{
+ const char * db = database.c_str();
+ const char * tbl = table.c_str();
+ bool do_include = true;
+
+ if (g_include_databases.size() != 0 ||
+ g_include_tables.size() != 0)
+ {
+ /*
+ User has explicitly specified what databases
+ and/or tables should be restored. If no match is
+ found then DON'T restore table.
+ */
+ do_include = false;
+ }
+ if (do_include &&
+ (g_exclude_databases.size() != 0 ||
+ g_exclude_tables.size() != 0))
+ {
+ /*
+ User has not explicitly specified what databases
+ and/or tables should be restored.
+ User has explicitly specified what databases
+ and/or tables should NOT be restored. If no match is
+ found then DO restore table.
+ */
+ do_include = true;
+ }
+
+ if (g_include_exclude.size() != 0)
+ {
+ /*
+ Scan include exclude arguments in reverse.
+ First matching include causes table to be restored.
+ first matching exclude causes table NOT to be restored.
+ */
+ for(uint i = g_include_exclude.size(); i > 0; i--)
+ {
+ RestoreOption *option = g_include_exclude[i-1];
+ switch (option->optid) {
+ case OPT_INCLUDE_TABLES:
+ if (strcmp(tbl, option->argument.c_str()) == 0)
+ return true; // do include
+ break;
+ case OPT_EXCLUDE_TABLES:
+ if (strcmp(tbl, option->argument.c_str()) == 0)
+ return false; // don't include
+ break;
+ case OPT_INCLUDE_DATABASES:
+ if (strcmp(db, option->argument.c_str()) == 0)
+ return true; // do include
+ break;
+ case OPT_EXCLUDE_DATABASES:
+ if (strcmp(db, option->argument.c_str()) == 0)
+ return false; // don't include
+ break;
+ default:
+ continue;
+ }
+ }
+ }
+
+ return do_include;
+}
+
static inline bool
checkDoRestore(const TableS* table)
{
@@ -794,32 +910,16 @@ checkDoRestore(const TableS* table)
idx = tbl.indexOf('/');
db = tbl.substr(0, idx);
- /* Included tables overrides
- * Excluded tables which overrides
- * Included databases which overrides
- * Excluded databases.
- * If any databases are included, then only
- * included databases are restored.
- * If any tables are included, then only
- * included tables are restored.
+ /*
+ Include/exclude flags are evaluated right
+ to left, and first match overrides any other
+ matches. Non-overlapping arguments are accumulative.
+ If no include flags are specified this means all databases/tables
+ except any excluded are restored.
+ If include flags are specified than only those databases
+ or tables specified are restored.
*/
-
- if (g_exclude_databases.size() != 0) {
- if (isInList(db, g_exclude_databases))
- ret = false;
- }
- if (g_include_databases.size() != 0) {
- ret= isInList(db, g_include_databases);
- }
-
- if (g_exclude_tables.size() != 0) {
- if (isInList(tbl, g_exclude_tables))
- ret = false;
- }
- if (g_include_tables.size() != 0) {
- ret= isInList(tbl, g_include_tables);
- }
-
+ ret = check_include_exclude(db, tbl);
return ret;
}
@@ -1075,6 +1175,10 @@ main(int argc, char** argv)
table_output.push_back(NULL);
if (!checkDbAndTableName(table))
continue;
+ if (isSYSTAB_0(table))
+ {
+ table_output[i]= ndbout.m_out;
+ }
if (checkSysTable(table))
{
if (!tab_path || isBlobTable(table) || isIndex(table))
@@ -1345,3 +1449,4 @@ main(int argc, char** argv)
template class Vector<BackupConsumer*>;
template class Vector<OutputStream*>;
+template class Vector<RestoreOption *>;
Attachment: [text/bzr-bundle] bzr/jonas@mysql.com-20091206171240-t8a8bke0gcxxvdun.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-telco-7.0-spj branch (jonas:3014) | Jonas Oreland | 6 Dec |