summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <tomas@whalegate.ndb.mysql.com>2007-03-23 21:50:57 +0100
committerunknown <tomas@whalegate.ndb.mysql.com>2007-03-23 21:50:57 +0100
commit4d3291e62c2b0e6b52f8bfa5782fc96458441277 (patch)
tree04d05ee60b5e3616bdd241f57aec499218fde184
parent65401f91974a5677d735c26f669332e466f62826 (diff)
parent27fc5de41aa6005d61c520e050ec0b8795b366eb (diff)
downloadmariadb-git-4d3291e62c2b0e6b52f8bfa5782fc96458441277.tar.gz
Merge tulin@bk-internal.mysql.com:/home/bk/mysql-5.1-new-ndb
into whalegate.ndb.mysql.com:/home/tomas/mysql-5.1-single-user storage/ndb/include/util/OutputStream.hpp: Auto merged
-rw-r--r--mysql-test/include/ndb_backup_print.inc6
-rw-r--r--mysql-test/r/ndb_partition_key.result1
-rw-r--r--mysql-test/r/ndb_restore_compat.result8
-rw-r--r--mysql-test/r/ndb_restore_print.result321
-rw-r--r--mysql-test/r/ndb_single_user.result28
-rw-r--r--mysql-test/r/rpl_ndb_log.result8
-rw-r--r--mysql-test/r/rpl_ndb_sync.result2
-rw-r--r--mysql-test/r/rpl_truncate_7ndb.result52
-rw-r--r--mysql-test/t/disabled.def1
-rw-r--r--mysql-test/t/ndb_restore_print.test189
-rw-r--r--mysql-test/t/ndb_single_user.test53
-rw-r--r--sql/ha_ndbcluster.cc25
-rw-r--r--sql/ha_ndbcluster_binlog.cc6
-rw-r--r--storage/ndb/include/kernel/signaldata/DictTabInfo.hpp4
-rw-r--r--storage/ndb/include/ndb_constants.h7
-rw-r--r--storage/ndb/include/ndbapi/NdbDictionary.hpp16
-rw-r--r--storage/ndb/include/ndbapi/NdbRecAttr.hpp50
-rw-r--r--storage/ndb/include/util/OutputStream.hpp1
-rw-r--r--storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp3
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp7
-rw-r--r--storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp5
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp31
-rw-r--r--storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp212
-rw-r--r--storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp1
-rw-r--r--storage/ndb/src/ndbapi/ClusterMgr.cpp2
-rw-r--r--storage/ndb/src/ndbapi/Ndb.cpp11
-rw-r--r--storage/ndb/src/ndbapi/NdbDictionary.cpp12
-rw-r--r--storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp16
-rw-r--r--storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp1
-rw-r--r--storage/ndb/src/ndbapi/NdbRecAttr.cpp144
-rw-r--r--storage/ndb/src/ndbapi/TransporterFacade.hpp16
-rw-r--r--storage/ndb/test/src/NDBT_Table.cpp2
-rw-r--r--storage/ndb/tools/restore/Restore.cpp18
-rw-r--r--storage/ndb/tools/restore/Restore.hpp11
-rw-r--r--storage/ndb/tools/restore/consumer_printer.cpp22
-rw-r--r--storage/ndb/tools/restore/consumer_restore.cpp35
-rw-r--r--storage/ndb/tools/restore/restore_main.cpp337
37 files changed, 1443 insertions, 221 deletions
diff --git a/mysql-test/include/ndb_backup_print.inc b/mysql-test/include/ndb_backup_print.inc
new file mode 100644
index 00000000000..57fb279491c
--- /dev/null
+++ b/mysql-test/include/ndb_backup_print.inc
@@ -0,0 +1,6 @@
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults $ndb_restore_opts -b $the_backup_id -n 1 $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id $ndb_restore_filter > $MYSQLTEST_VARDIR/tmp/tmp.dat
+--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults $ndb_restore_opts -b $the_backup_id -n 2 $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id $ndb_restore_filter >> $MYSQLTEST_VARDIR/tmp/tmp.dat
+--exec sort $MYSQLTEST_VARDIR/tmp/tmp.dat
+--exec rm -f $MYSQLTEST_VARDIR/tmp/tmp.dat
+--let ndb_restore_opts=
+--let ndb_restore_filter=
diff --git a/mysql-test/r/ndb_partition_key.result b/mysql-test/r/ndb_partition_key.result
index e294807b40d..685137b7710 100644
--- a/mysql-test/r/ndb_partition_key.result
+++ b/mysql-test/r/ndb_partition_key.result
@@ -57,6 +57,7 @@ Number of primary keys: 3
Length of frm data: #
Row Checksum: 1
Row GCI: 1
+SingleUserMode: 0
TableStatus: Retrieved
-- Attributes --
a Int PRIMARY KEY AT=FIXED ST=MEMORY
diff --git a/mysql-test/r/ndb_restore_compat.result b/mysql-test/r/ndb_restore_compat.result
index f580f680687..d495aa28135 100644
--- a/mysql-test/r/ndb_restore_compat.result
+++ b/mysql-test/r/ndb_restore_compat.result
@@ -45,8 +45,8 @@ SYSTEM_VALUES_ID VALUE
0 2039
1 3
SELECT * FROM mysql.ndb_apply_status WHERE server_id=0;
-server_id epoch
-0 151
+server_id epoch log_name start_pos end_pos
+0 151 0 0
TRUNCATE GL;
TRUNCATE ACCOUNT;
TRUNCATE TRANSACTION;
@@ -99,6 +99,6 @@ SYSTEM_VALUES_ID VALUE
0 2297
1 5
SELECT * FROM mysql.ndb_apply_status WHERE server_id=0;
-server_id epoch
-0 331
+server_id epoch log_name start_pos end_pos
+0 331 0 0
DROP DATABASE BANK;
diff --git a/mysql-test/r/ndb_restore_print.result b/mysql-test/r/ndb_restore_print.result
new file mode 100644
index 00000000000..e05f8e43d1a
--- /dev/null
+++ b/mysql-test/r/ndb_restore_print.result
@@ -0,0 +1,321 @@
+use test;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
+create table t1
+(pk int key
+,a1 BIT(1), a2 BIT(5), a3 BIT(33), a4 BIT(63), a5 BIT(64)
+,b1 TINYINT, b2 TINYINT UNSIGNED
+,c1 SMALLINT, c2 SMALLINT UNSIGNED
+,d1 INT, d2 INT UNSIGNED
+,e1 BIGINT, e2 BIGINT UNSIGNED
+,f1 CHAR(1) BINARY, f2 CHAR(32) BINARY, f3 CHAR(255) BINARY
+,g1 VARCHAR(32) BINARY, g2 VARCHAR(255) BINARY, g3 VARCHAR(1000) BINARY
+,h1 BINARY(1), h2 BINARY(8), h3 BINARY(255)
+,i1 VARBINARY(32), i2 VARBINARY(255), i3 VARBINARY(1000)
+) engine myisam;
+insert into t1 values
+(1
+,0x1, 0x17, 0x789a, 0x789abcde, 0xfedc0001
+,127, 255
+,32767, 65535
+,2147483647, 4294967295
+,9223372036854775807, 18446744073709551615
+,'1','12345678901234567890123456789012','123456789'
+ ,'1','12345678901234567890123456789012','123456789'
+ ,0x12,0x123456789abcdef0, 0x012345
+,0x12,0x123456789abcdef0, 0x00123450
+);
+insert into t1 values
+(2
+,0, 0, 0, 0, 0
+,-128, 0
+,-32768, 0
+,-2147483648, 0
+,-9223372036854775808, 0
+,'','',''
+ ,'','',''
+ ,0x0,0x0,0x0
+,0x0,0x0,0x0
+);
+insert into t1 values
+(3
+,NULL,NULL,NULL,NULL,NULL
+,NULL,NULL
+,NULL,NULL
+,NULL,NULL
+,NULL,NULL
+,NULL,NULL,NULL
+,NULL,NULL,NULL
+,NULL,NULL,NULL
+,NULL,NULL,NULL
+);
+select pk
+,hex(a1), hex(a2), hex(a3), hex(a4), hex(a5)
+,b1, b2
+,c1 , c2
+,d1 , d2
+,e1 , e2
+,f1 , f2, f3
+,g1 , g2, g3
+,hex(h1), hex(h2), hex(h3)
+,hex(i1), hex(i2), hex(i3)
+from t1 order by pk;
+pk 1
+hex(a1) 1
+hex(a2) 17
+hex(a3) 789A
+hex(a4) 789ABCDE
+hex(a5) FEDC0001
+b1 127
+b2 255
+c1 32767
+c2 65535
+d1 2147483647
+d2 4294967295
+e1 9223372036854775807
+e2 18446744073709551615
+f1 1
+f2 12345678901234567890123456789012
+f3 123456789
+g1 1
+g2 12345678901234567890123456789012
+g3 123456789
+hex(h1) 12
+hex(h2) 123456789ABCDEF0
+hex(h3) 012345000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+hex(i1) 12
+hex(i2) 123456789ABCDEF0
+hex(i3) 00123450
+pk 2
+hex(a1) 0
+hex(a2) 0
+hex(a3) 0
+hex(a4) 0
+hex(a5) 0
+b1 -128
+b2 0
+c1 -32768
+c2 0
+d1 -2147483648
+d2 0
+e1 -9223372036854775808
+e2 0
+f1
+f2
+f3
+g1
+g2
+g3
+hex(h1) 00
+hex(h2) 0000000000000000
+hex(h3) 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+hex(i1) 00
+hex(i2) 00
+hex(i3) 00
+pk 3
+hex(a1) NULL
+hex(a2) NULL
+hex(a3) NULL
+hex(a4) NULL
+hex(a5) NULL
+b1 NULL
+b2 NULL
+c1 NULL
+c2 NULL
+d1 NULL
+d2 NULL
+e1 NULL
+e2 NULL
+f1 NULL
+f2 NULL
+f3 NULL
+g1 NULL
+g2 NULL
+g3 NULL
+hex(h1) NULL
+hex(h2) NULL
+hex(h3) NULL
+hex(i1) NULL
+hex(i2) NULL
+hex(i3) NULL
+alter table t1 engine ndb;
+select pk
+,hex(a1), hex(a2), hex(a3), hex(a4), hex(a5)
+,b1, b2
+,c1 , c2
+,d1 , d2
+,e1 , e2
+,f1 , f2, f3
+,g1 , g2, g3
+,hex(h1), hex(h2), hex(h3)
+,hex(i1), hex(i2), hex(i3)
+from t1 order by pk;
+pk 1
+hex(a1) 1
+hex(a2) 17
+hex(a3) 789A
+hex(a4) 789ABCDE
+hex(a5) FEDC0001
+b1 127
+b2 255
+c1 32767
+c2 65535
+d1 2147483647
+d2 4294967295
+e1 9223372036854775807
+e2 18446744073709551615
+f1 1
+f2 12345678901234567890123456789012
+f3 123456789
+g1 1
+g2 12345678901234567890123456789012
+g3 123456789
+hex(h1) 12
+hex(h2) 123456789ABCDEF0
+hex(h3) 012345000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+hex(i1) 12
+hex(i2) 123456789ABCDEF0
+hex(i3) 00123450
+pk 2
+hex(a1) 0
+hex(a2) 0
+hex(a3) 0
+hex(a4) 0
+hex(a5) 0
+b1 -128
+b2 0
+c1 -32768
+c2 0
+d1 -2147483648
+d2 0
+e1 -9223372036854775808
+e2 0
+f1
+f2
+f3
+g1
+g2
+g3
+hex(h1) 00
+hex(h2) 0000000000000000
+hex(h3) 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+hex(i1) 00
+hex(i2) 00
+hex(i3) 00
+pk 3
+hex(a1) NULL
+hex(a2) NULL
+hex(a3) NULL
+hex(a4) NULL
+hex(a5) NULL
+b1 NULL
+b2 NULL
+c1 NULL
+c2 NULL
+d1 NULL
+d2 NULL
+e1 NULL
+e2 NULL
+f1 NULL
+f2 NULL
+f3 NULL
+g1 NULL
+g2 NULL
+g3 NULL
+hex(h1) NULL
+hex(h2) NULL
+hex(h3) NULL
+hex(i1) NULL
+hex(i2) NULL
+hex(i3) NULL
+CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP;
+DELETE FROM test.backup_info;
+LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ',';
+SELECT @the_backup_id:=backup_id FROM test.backup_info;
+@the_backup_id:=backup_id
+<the_backup_id>
+DROP TABLE test.backup_info;
+1;0x1;0x17;0x789A;0x789ABCDE;0xFEDC0001;127;255;32767;65535;2147483647;4294967295;9223372036854775807;18446744073709551615;1;12345678901234567890123456789012;123456789;1;12345678901234567890123456789012;123456789;0x12;0x123456789ABCDEF0;0x012345;0x12;0x123456789ABCDEF0;0x00123450
+2;0x0;0x0;0x0;0x0;0x0;-128;0;-32768;0;-2147483648;0;-9223372036854775808;0;;;;;;;0x0;0x0;0x0;0x0;0x0;0x0
+3;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N
+1,0x1,0x17,0x789A,0x789ABCDE,0xFEDC0001,127,255,32767,65535,2147483647,4294967295,9223372036854775807,18446744073709551615,'1','12345678901234567890123456789012','123456789','1','12345678901234567890123456789012','123456789',0x12,0x123456789ABCDEF0,0x012345,0x12,0x123456789ABCDEF0,0x00123450
+2,0x0,0x0,0x0,0x0,0x0,-128,0,-32768,0,-2147483648,0,-9223372036854775808,0,'','','','','','',0x0,0x0,0x0,0x0,0x0,0x0
+3,,,,,,,,,,,,,,,,,,,,,,,,,
+drop table t1;
+create table t1
+(pk int key
+,f1 CHAR(1) BINARY, f2 CHAR(32) BINARY, f3 CHAR(255) BINARY
+,g1 VARCHAR(32) BINARY, g2 VARCHAR(255) BINARY, g3 VARCHAR(1000) BINARY
+,h1 BINARY(1), h2 BINARY(9), h3 BINARY(255)
+,i1 VARBINARY(32), i2 VARBINARY(255), i3 VARBINARY(1000)
+) engine ndb;
+insert into t1 values
+(1
+,'1','12345678901234567890123456789012','123456789 '
+ ,'1 ','12345678901234567890123456789012 ','123456789 '
+ ,0x20,0x123456789abcdef020, 0x012345000020
+,0x1200000020,0x123456789abcdef000000020, 0x00123450000020
+);
+create table t2 (pk int key, a int) engine ndb;
+create table t3 (pk int key, a int) engine ndb;
+create table t4 (pk int key, a int) engine ndb;
+insert into t2 values (1,11),(2,12),(3,13),(4,14),(5,15);
+insert into t3 values (1,21),(2,22),(3,23),(4,24),(5,25);
+insert into t4 values (1,31),(2,32),(3,33),(4,34),(5,35);
+CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP;
+DELETE FROM test.backup_info;
+LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ',';
+SELECT @the_backup_id:=backup_id FROM test.backup_info;
+@the_backup_id:=backup_id
+<the_backup_id>
+DROP TABLE test.backup_info;
+'1' '1' '12345678901234567890123456789012' '123456789' '1' '12345678901234567890123456789012' '123456789' '0x20' '0x123456789ABCDEF020' '0x012345000020' '0x1200000020' '0x123456789ABCDEF000000020' '0x00123450000020'
+
+t1
+--
+1 1 12345678901234567890123456789012 123456789 1 12345678901234567890123456789012 123456789 0x20 0x123456789ABCDEF020 0x012345000020 0x1200000020 0x123456789ABCDEF000000020 0x00123450000020
+
+t2
+--
+1 11
+2 12
+3 13
+4 14
+5 15
+
+t3
+--
+1 21
+2 22
+3 23
+4 24
+5 25
+
+t4
+--
+1 31
+2 32
+3 33
+4 34
+5 35
+drop table t1;
+create table t1
+(pk int key
+,a1 MEDIUMINT, a2 MEDIUMINT UNSIGNED
+) engine ndb;
+insert into t1 values(1, 8388607, 16777215);
+insert into t1 values(2, -8388608, 0);
+insert into t1 values(3, -1, 1);
+CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP;
+DELETE FROM test.backup_info;
+LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ',';
+SELECT @the_backup_id:=backup_id FROM test.backup_info;
+@the_backup_id:=backup_id
+<the_backup_id>
+DROP TABLE test.backup_info;
+1;8388607;16777215
+2;-8388608;0
+3;-1;1
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
diff --git a/mysql-test/r/ndb_single_user.result b/mysql-test/r/ndb_single_user.result
index 771a02ecc84..85ad30db8b0 100644
--- a/mysql-test/r/ndb_single_user.result
+++ b/mysql-test/r/ndb_single_user.result
@@ -1,7 +1,7 @@
use test;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
create table t1 (a int key, b int unique, c int) engine ndb;
-ERROR HY000: Can't create table 'test.t1' (errno: 4007)
+ERROR HY000: Can't create table 'test.t1' (errno: 299)
create table t1 (a int key, b int unique, c int) engine ndb;
insert into t1 values (1,1,0),(2,2,0),(3,3,0),(4,4,0),(5,5,0),(6,6,0),(7,7,0),(8,8,0),(9,9,0),(10,10,0);
create table t2 as select * from t1;
@@ -28,19 +28,29 @@ insert into t1 select * from t2;
drop table t1;
ERROR 42S02: Unknown table 't1'
create index new_index on t1 (c);
-ERROR 42S02: Table 'test.t1' doesn't exist
+ERROR HY000: Got error 299 'Operation not allowed or aborted due to single user mode' from NDBCLUSTER
insert into t1 values (1,1,0),(2,2,0),(3,3,0),(4,4,0),(5,5,0),(6,6,0),(7,7,0),(8,8,0),(9,9,0),(10,10,0);
-ERROR 42S02: Table 'test.t1' doesn't exist
+ERROR HY000: Got error 299 'Operation not allowed or aborted due to single user mode' from NDBCLUSTER
select * from t1 where a = 1;
-ERROR 42S02: Table 'test.t1' doesn't exist
+ERROR HY000: Got error 299 'Operation not allowed or aborted due to single user mode' from NDBCLUSTER
select * from t1 where b = 4;
-ERROR 42S02: Table 'test.t1' doesn't exist
+ERROR HY000: Got error 299 'Operation not allowed or aborted due to single user mode' from NDBCLUSTER
update t1 set b=102 where a = 2;
-ERROR 42S02: Table 'test.t1' doesn't exist
+ERROR HY000: Got error 299 'Operation not allowed or aborted due to single user mode' from NDBCLUSTER
update t1 set b=103 where b = 3;
-ERROR 42S02: Table 'test.t1' doesn't exist
+ERROR HY000: Got error 299 'Operation not allowed or aborted due to single user mode' from NDBCLUSTER
update t1 set b=b+100;
-ERROR 42S02: Table 'test.t1' doesn't exist
+ERROR HY000: Got error 299 'Operation not allowed or aborted due to single user mode' from NDBCLUSTER
update t1 set b=b+100 where a > 7;
-ERROR 42S02: Table 'test.t1' doesn't exist
+ERROR HY000: Got error 299 'Operation not allowed or aborted due to single user mode' from NDBCLUSTER
+BEGIN;
+update t1 set b=b+100 where a=1;
+BEGIN;
+update t1 set b=b+100 where a=2;
+update t1 set b=b+100 where a=3;
+COMMIT;
+update t1 set b=b+100 where a=4;
+ERROR HY000: Got error 299 'Operation not allowed or aborted due to single user mode' from NDBCLUSTER
+COMMIT;
+ERROR HY000: Got error 4350 'Transaction already aborted' from NDBCLUSTER
drop table t1;
diff --git a/mysql-test/r/rpl_ndb_log.result b/mysql-test/r/rpl_ndb_log.result
index 543af3b9abe..c93af3441d8 100644
--- a/mysql-test/r/rpl_ndb_log.result
+++ b/mysql-test/r/rpl_ndb_log.result
@@ -87,12 +87,12 @@ master-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F
master-bin.000002 # Query 1 # COMMIT
show binary logs;
Log_name File_size
-master-bin.000001 1702
-master-bin.000002 593
+master-bin.000001 1740
+master-bin.000002 612
start slave;
show binary logs;
Log_name File_size
-slave-bin.000001 1797
+slave-bin.000001 1835
slave-bin.000002 198
show binlog events in 'slave-bin.000001' from 4;
Log_name Pos Event_type Server_id End_log_pos Info
@@ -126,7 +126,7 @@ slave-bin.000002 # Write_rows 2 # table_id: # flags: STMT_END_F
slave-bin.000002 # Query 2 # COMMIT
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 593 # # master-bin.000002 Yes Yes # 0 0 593 # None 0 No #
+# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 612 # # master-bin.000002 Yes Yes # 0 0 612 # None 0 No #
show binlog events in 'slave-bin.000005' from 4;
ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log
DROP TABLE t1;
diff --git a/mysql-test/r/rpl_ndb_sync.result b/mysql-test/r/rpl_ndb_sync.result
index a2c3b46db5a..d05367c5fc0 100644
--- a/mysql-test/r/rpl_ndb_sync.result
+++ b/mysql-test/r/rpl_ndb_sync.result
@@ -93,4 +93,4 @@ select * from mysql.ndb_binlog_index;
Position File epoch inserts updates deletes schemaops
reset slave;
select * from mysql.ndb_apply_status;
-server_id epoch
+server_id epoch log_name start_pos end_pos
diff --git a/mysql-test/r/rpl_truncate_7ndb.result b/mysql-test/r/rpl_truncate_7ndb.result
index 63d4b0f9411..21399be4686 100644
--- a/mysql-test/r/rpl_truncate_7ndb.result
+++ b/mysql-test/r/rpl_truncate_7ndb.result
@@ -33,12 +33,12 @@ master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4
master-bin.000001 102 Query 1 219 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
master-bin.000001 219 Query 1 283 BEGIN
master-bin.000001 283 Table_map 1 40 table_id: # (test.t1)
-master-bin.000001 323 Table_map 1 95 table_id: # (mysql.ndb_apply_status)
-master-bin.000001 378 Write_rows 1 137 table_id: #
-master-bin.000001 420 Write_rows 1 184 table_id: # flags: STMT_END_F
-master-bin.000001 467 Query 1 532 COMMIT
-master-bin.000001 532 Query 1 612 use `test`; TRUNCATE TABLE t1
-master-bin.000001 612 Query 1 688 use `test`; DROP TABLE t1
+master-bin.000001 323 Table_map 1 98 table_id: # (mysql.ndb_apply_status)
+master-bin.000001 381 Write_rows 1 156 table_id: #
+master-bin.000001 439 Write_rows 1 203 table_id: # flags: STMT_END_F
+master-bin.000001 486 Query 1 551 COMMIT
+master-bin.000001 551 Query 1 631 use `test`; TRUNCATE TABLE t1
+master-bin.000001 631 Query 1 707 use `test`; DROP TABLE t1
**** On Master ****
CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB;
INSERT INTO t1 VALUES (1,1), (2,2);
@@ -69,23 +69,23 @@ master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4
master-bin.000001 102 Query 1 219 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
master-bin.000001 219 Query 1 283 BEGIN
master-bin.000001 283 Table_map 1 40 table_id: # (test.t1)
-master-bin.000001 323 Table_map 1 95 table_id: # (mysql.ndb_apply_status)
-master-bin.000001 378 Write_rows 1 137 table_id: #
-master-bin.000001 420 Write_rows 1 184 table_id: # flags: STMT_END_F
-master-bin.000001 467 Query 1 532 COMMIT
-master-bin.000001 532 Query 1 612 use `test`; TRUNCATE TABLE t1
-master-bin.000001 612 Query 1 688 use `test`; DROP TABLE t1
-master-bin.000001 688 Query 1 805 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
-master-bin.000001 805 Query 1 869 BEGIN
-master-bin.000001 869 Table_map 1 40 table_id: # (test.t1)
-master-bin.000001 909 Table_map 1 95 table_id: # (mysql.ndb_apply_status)
-master-bin.000001 964 Write_rows 1 137 table_id: #
-master-bin.000001 1006 Write_rows 1 184 table_id: # flags: STMT_END_F
-master-bin.000001 1053 Query 1 1118 COMMIT
-master-bin.000001 1118 Query 1 1182 BEGIN
-master-bin.000001 1182 Table_map 1 40 table_id: # (test.t1)
-master-bin.000001 1222 Table_map 1 95 table_id: # (mysql.ndb_apply_status)
-master-bin.000001 1277 Write_rows 1 137 table_id: #
-master-bin.000001 1319 Delete_rows 1 176 table_id: # flags: STMT_END_F
-master-bin.000001 1358 Query 1 1423 COMMIT
-master-bin.000001 1423 Query 1 1499 use `test`; DROP TABLE t1
+master-bin.000001 323 Table_map 1 98 table_id: # (mysql.ndb_apply_status)
+master-bin.000001 381 Write_rows 1 156 table_id: #
+master-bin.000001 439 Write_rows 1 203 table_id: # flags: STMT_END_F
+master-bin.000001 486 Query 1 551 COMMIT
+master-bin.000001 551 Query 1 631 use `test`; TRUNCATE TABLE t1
+master-bin.000001 631 Query 1 707 use `test`; DROP TABLE t1
+master-bin.000001 707 Query 1 824 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
+master-bin.000001 824 Query 1 888 BEGIN
+master-bin.000001 888 Table_map 1 40 table_id: # (test.t1)
+master-bin.000001 928 Table_map 1 98 table_id: # (mysql.ndb_apply_status)
+master-bin.000001 986 Write_rows 1 156 table_id: #
+master-bin.000001 1044 Write_rows 1 203 table_id: # flags: STMT_END_F
+master-bin.000001 1091 Query 1 1156 COMMIT
+master-bin.000001 1156 Query 1 1220 BEGIN
+master-bin.000001 1220 Table_map 1 40 table_id: # (test.t1)
+master-bin.000001 1260 Table_map 1 98 table_id: # (mysql.ndb_apply_status)
+master-bin.000001 1318 Write_rows 1 156 table_id: #
+master-bin.000001 1376 Delete_rows 1 195 table_id: # flags: STMT_END_F
+master-bin.000001 1415 Query 1 1480 COMMIT
+master-bin.000001 1480 Query 1 1556 use `test`; DROP TABLE t1
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index be3e80dd969..60a28516195 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -35,4 +35,3 @@ synchronization : Bug#24529 Test 'synchronization' fails on Mac pushb
plugin : Bug#25659 memory leak via "plugins" test
rpl_ndb_dd_advance : Bug#25913 rpl_ndb_dd_advance fails randomly
-ndb_single_user : Bug#27021 Error codes in mysqld in single user mode varies
diff --git a/mysql-test/t/ndb_restore_print.test b/mysql-test/t/ndb_restore_print.test
new file mode 100644
index 00000000000..6dbbfdf5933
--- /dev/null
+++ b/mysql-test/t/ndb_restore_print.test
@@ -0,0 +1,189 @@
+-- source include/have_ndb.inc
+-- source include/ndb_default_cluster.inc
+-- source include/not_embedded.inc
+
+--disable_warnings
+use test;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
+--enable_warnings
+
+# basic datatypes
+create table t1
+ (pk int key
+ ,a1 BIT(1), a2 BIT(5), a3 BIT(33), a4 BIT(63), a5 BIT(64)
+ ,b1 TINYINT, b2 TINYINT UNSIGNED
+ ,c1 SMALLINT, c2 SMALLINT UNSIGNED
+ ,d1 INT, d2 INT UNSIGNED
+ ,e1 BIGINT, e2 BIGINT UNSIGNED
+ ,f1 CHAR(1) BINARY, f2 CHAR(32) BINARY, f3 CHAR(255) BINARY
+ ,g1 VARCHAR(32) BINARY, g2 VARCHAR(255) BINARY, g3 VARCHAR(1000) BINARY
+ ,h1 BINARY(1), h2 BINARY(8), h3 BINARY(255)
+ ,i1 VARBINARY(32), i2 VARBINARY(255), i3 VARBINARY(1000)
+ ) engine myisam;
+
+# max values
+insert into t1 values
+ (1
+ ,0x1, 0x17, 0x789a, 0x789abcde, 0xfedc0001
+ ,127, 255
+ ,32767, 65535
+ ,2147483647, 4294967295
+ ,9223372036854775807, 18446744073709551615
+ ,'1','12345678901234567890123456789012','123456789'
+ ,'1','12345678901234567890123456789012','123456789'
+ ,0x12,0x123456789abcdef0, 0x012345
+ ,0x12,0x123456789abcdef0, 0x00123450
+ );
+
+# min values
+insert into t1 values
+ (2
+ ,0, 0, 0, 0, 0
+ ,-128, 0
+ ,-32768, 0
+ ,-2147483648, 0
+ ,-9223372036854775808, 0
+ ,'','',''
+ ,'','',''
+ ,0x0,0x0,0x0
+ ,0x0,0x0,0x0
+ );
+
+# null values
+insert into t1 values
+ (3
+ ,NULL,NULL,NULL,NULL,NULL
+ ,NULL,NULL
+ ,NULL,NULL
+ ,NULL,NULL
+ ,NULL,NULL
+ ,NULL,NULL,NULL
+ ,NULL,NULL,NULL
+ ,NULL,NULL,NULL
+ ,NULL,NULL,NULL
+ );
+
+--vertical_results
+select pk
+ ,hex(a1), hex(a2), hex(a3), hex(a4), hex(a5)
+ ,b1, b2
+ ,c1 , c2
+ ,d1 , d2
+ ,e1 , e2
+ ,f1 , f2, f3
+ ,g1 , g2, g3
+ ,hex(h1), hex(h2), hex(h3)
+ ,hex(i1), hex(i2), hex(i3)
+ from t1 order by pk;
+
+alter table t1 engine ndb;
+
+select pk
+ ,hex(a1), hex(a2), hex(a3), hex(a4), hex(a5)
+ ,b1, b2
+ ,c1 , c2
+ ,d1 , d2
+ ,e1 , e2
+ ,f1 , f2, f3
+ ,g1 , g2, g3
+ ,hex(h1), hex(h2), hex(h3)
+ ,hex(i1), hex(i2), hex(i3)
+ from t1 order by pk;
+--horizontal_results
+
+--source include/ndb_backup.inc
+
+--let ndb_restore_filter=test t1
+--let ndb_restore_opts=--verbose=0 --print_data --hex --fields-terminated-by=";"
+--source include/ndb_backup_print.inc
+
+--let ndb_restore_filter=test t1
+--let ndb_restore_opts=--verbose=0 --print_data --hex --fields-terminated-by="," --fields-optionally-enclosed-by="'"
+--source include/ndb_backup_print.inc
+
+
+drop table t1;
+
+# some binary char tests with trailing spaces
+create table t1
+ (pk int key
+ ,f1 CHAR(1) BINARY, f2 CHAR(32) BINARY, f3 CHAR(255) BINARY
+ ,g1 VARCHAR(32) BINARY, g2 VARCHAR(255) BINARY, g3 VARCHAR(1000) BINARY
+ ,h1 BINARY(1), h2 BINARY(9), h3 BINARY(255)
+ ,i1 VARBINARY(32), i2 VARBINARY(255), i3 VARBINARY(1000)
+ ) engine ndb;
+
+insert into t1 values
+ (1
+ ,'1','12345678901234567890123456789012','123456789 '
+ ,'1 ','12345678901234567890123456789012 ','123456789 '
+ ,0x20,0x123456789abcdef020, 0x012345000020
+ ,0x1200000020,0x123456789abcdef000000020, 0x00123450000020
+ );
+
+create table t2 (pk int key, a int) engine ndb;
+create table t3 (pk int key, a int) engine ndb;
+create table t4 (pk int key, a int) engine ndb;
+
+insert into t2 values (1,11),(2,12),(3,13),(4,14),(5,15);
+insert into t3 values (1,21),(2,22),(3,23),(4,24),(5,25);
+insert into t4 values (1,31),(2,32),(3,33),(4,34),(5,35);
+
+--source include/ndb_backup.inc
+--let ndb_restore_opts=--verbose=0 --print_data --hex --fields-enclosed-by="'" --fields-optionally-enclosed-by="X"
+--let ndb_restore_filter=test t1
+--source include/ndb_backup_print.inc
+
+--exec rm -f $MYSQLTEST_VARDIR/tmp/t1.txt
+--exec rm -f $MYSQLTEST_VARDIR/tmp/t2.txt
+--exec rm -f $MYSQLTEST_VARDIR/tmp/t3.txt
+--exec rm -f $MYSQLTEST_VARDIR/tmp/t4.txt
+
+--let ndb_restore_opts=--verbose=0 --print_data --hex --tab $MYSQLTEST_VARDIR/tmp --append
+--let ndb_restore_filter=test
+--source include/ndb_backup_print.inc
+
+--let $message= t1
+--source include/show_msg.inc
+--exec sort $MYSQLTEST_VARDIR/tmp/t1.txt
+--let $message= t2
+--source include/show_msg.inc
+--exec sort $MYSQLTEST_VARDIR/tmp/t2.txt
+--let $message= t3
+--source include/show_msg.inc
+--exec sort $MYSQLTEST_VARDIR/tmp/t3.txt
+--let $message= t4
+--source include/show_msg.inc
+--exec sort $MYSQLTEST_VARDIR/tmp/t4.txt
+
+--exec rm -f $MYSQLTEST_VARDIR/tmp/t1.txt
+--exec rm -f $MYSQLTEST_VARDIR/tmp/t2.txt
+--exec rm -f $MYSQLTEST_VARDIR/tmp/t3.txt
+--exec rm -f $MYSQLTEST_VARDIR/tmp/t4.txt
+
+# now test some other datatypes
+drop table t1;
+create table t1
+ (pk int key
+ ,a1 MEDIUMINT, a2 MEDIUMINT UNSIGNED
+ ) engine ndb;
+
+# max values
+insert into t1 values(1, 8388607, 16777215);
+# min values
+insert into t1 values(2, -8388608, 0);
+# small values
+insert into t1 values(3, -1, 1);
+
+# backup and print
+--source include/ndb_backup.inc
+
+--let ndb_restore_filter=test t1
+--let ndb_restore_opts=--verbose=0 --print_data --hex --fields-terminated-by=";"
+--source include/ndb_backup_print.inc
+
+# clean up
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
diff --git a/mysql-test/t/ndb_single_user.test b/mysql-test/t/ndb_single_user.test
index c655124f79f..b191e573996 100644
--- a/mysql-test/t/ndb_single_user.test
+++ b/mysql-test/t/ndb_single_user.test
@@ -51,34 +51,55 @@ insert into t1 select * from t2;
--connection server2
--error 1051
drop table t1;
---error 1146
-#--error 1296
+--error 1296
create index new_index on t1 (c);
---error 1146
-#--error 1296
+--error 1296
insert into t1 values (1,1,0),(2,2,0),(3,3,0),(4,4,0),(5,5,0),(6,6,0),(7,7,0),(8,8,0),(9,9,0),(10,10,0);
---error 1146
-#--error 1296
+--error 1296
select * from t1 where a = 1;
---error 1146
-#--error 1296
+--error 1296
select * from t1 where b = 4;
---error 1146
-#--error 1296
+--error 1296
update t1 set b=102 where a = 2;
---error 1146
-#--error 1296
+--error 1296
update t1 set b=103 where b = 3;
---error 1146
-#--error 1296
+--error 1296
update t1 set b=b+100;
---error 1146
-#--error 1296
+--error 1296
update t1 set b=b+100 where a > 7;
--exec $NDB_MGM --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -e "exit single user mode" >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults >> $NDB_TOOLS_OUTPUT
+#
+# we should be able to run transaction while in single user mode
+#
+--connection server1
+BEGIN;
+update t1 set b=b+100 where a=1;
+
+--connection server2
+BEGIN;
+update t1 set b=b+100 where a=2;
+
+# enter single user mode
+--exec $NDB_MGM --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -e "enter single user mode $node_id" >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT" --single-user >> $NDB_TOOLS_OUTPUT
+
+--connection server1
+update t1 set b=b+100 where a=3;
+COMMIT;
+
+# while on other mysqld it should be aborted
+--connection server2
+--error 1296
+update t1 set b=b+100 where a=4;
+--error 1296
+COMMIT;
+
+--exec $NDB_MGM --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -e "exit single user mode" >> $NDB_TOOLS_OUTPUT
+--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults >> $NDB_TOOLS_OUTPUT
+
# cleanup
--connection server1
drop table t1;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index f0acab2b43d..24a9e30aa2e 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -4742,6 +4742,7 @@ int ha_ndbcluster::create(const char *name,
bool create_from_engine= (create_info->table_options & HA_OPTION_CREATE_FROM_ENGINE);
bool is_truncate= (thd->lex->sql_command == SQLCOM_TRUNCATE);
char tablespace[FN_LEN];
+ NdbDictionary::Table::SingleUserMode single_user_mode= NdbDictionary::Table::SingleUserModeLocked;
DBUG_ENTER("ha_ndbcluster::create");
DBUG_PRINT("enter", ("name: %s", name));
@@ -4793,19 +4794,23 @@ int ha_ndbcluster::create(const char *name,
schema distribution table is setup
( unless it is a creation of the schema dist table itself )
*/
- if (!ndb_schema_share &&
- !(strcmp(m_dbname, NDB_REP_DB) == 0 &&
- strcmp(m_tabname, NDB_SCHEMA_TABLE) == 0))
+ if (!ndb_schema_share)
{
- DBUG_PRINT("info", ("Schema distribution table not setup"));
- DBUG_RETURN(HA_ERR_NO_CONNECTION);
+ if (!(strcmp(m_dbname, NDB_REP_DB) == 0 &&
+ strcmp(m_tabname, NDB_SCHEMA_TABLE) == 0))
+ {
+ DBUG_PRINT("info", ("Schema distribution table not setup"));
+ DBUG_RETURN(HA_ERR_NO_CONNECTION);
+ }
+ single_user_mode = NdbDictionary::Table::SingleUserModeReadWrite;
}
#endif /* HAVE_NDB_BINLOG */
DBUG_PRINT("table", ("name: %s", m_tabname));
tab.setName(m_tabname);
tab.setLogging(!(create_info->options & HA_LEX_CREATE_TMP_TABLE));
-
+ tab.setSingleUserMode(single_user_mode);
+
// Save frm data for this table
if (readfrm(name, &data, &length))
DBUG_RETURN(1);
@@ -5569,6 +5574,7 @@ retry_temporary_error1:
{
ndb_table_id= h->m_table->getObjectId();
ndb_table_version= h->m_table->getObjectVersion();
+ DBUG_PRINT("info", ("success 1"));
}
else
{
@@ -5582,6 +5588,7 @@ retry_temporary_error1:
break;
}
res= ndb_to_mysql_error(&dict->getNdbError());
+ DBUG_PRINT("info", ("error(1) %u", res));
}
h->release_metadata(thd, ndb);
}
@@ -5598,6 +5605,8 @@ retry_temporary_error1:
{
ndb_table_id= ndbtab_g.get_table()->getObjectId();
ndb_table_version= ndbtab_g.get_table()->getObjectVersion();
+ DBUG_PRINT("info", ("success 2"));
+ break;
}
else
{
@@ -5617,8 +5626,8 @@ retry_temporary_error1:
}
}
}
- else
- res= ndb_to_mysql_error(&dict->getNdbError());
+ res= ndb_to_mysql_error(&dict->getNdbError());
+ DBUG_PRINT("info", ("error(2) %u", res));
break;
}
}
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index 2615732e7ee..8b51ac68e66 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -729,6 +729,9 @@ static int ndbcluster_create_ndb_apply_status_table(THD *thd)
NDB_REP_DB "." NDB_APPLY_TABLE
" ( server_id INT UNSIGNED NOT NULL,"
" epoch BIGINT UNSIGNED NOT NULL, "
+ " log_name VARCHAR(255) BINARY NOT NULL, "
+ " start_pos BIGINT UNSIGNED NOT NULL, "
+ " end_pos BIGINT UNSIGNED NOT NULL, "
" PRIMARY KEY USING HASH (server_id) ) ENGINE=NDB");
run_query(thd, buf, end, TRUE, TRUE);
@@ -3898,6 +3901,9 @@ restart:
bzero(table->record[0], table->s->null_bytes);
table->field[0]->store((longlong)::server_id);
table->field[1]->store((longlong)gci);
+ table->field[2]->store("", 0, &my_charset_bin);
+ table->field[3]->store((longlong)0);
+ table->field[4]->store((longlong)0);
trans.write_row(::server_id,
injector::transaction::table(table, TRUE),
&table->s->all_set, table->s->fields,
diff --git a/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp b/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
index bc41d8373fd..57b4f0e7520 100644
--- a/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
+++ b/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
@@ -140,6 +140,8 @@ public:
RowGCIFlag = 150,
RowChecksumFlag = 151,
+ SingleUserMode = 152,
+
TableEnd = 999,
AttributeName = 1000, // String, Mandatory
@@ -344,6 +346,8 @@ public:
Uint32 RowGCIFlag;
Uint32 RowChecksumFlag;
+
+ Uint32 SingleUserMode;
Table() {}
void init();
diff --git a/storage/ndb/include/ndb_constants.h b/storage/ndb/include/ndb_constants.h
index 8b3cb5b6cf9..e2f8e17e913 100644
--- a/storage/ndb/include/ndb_constants.h
+++ b/storage/ndb/include/ndb_constants.h
@@ -89,5 +89,12 @@
*/
#define NDB_TEMP_TAB_PERMANENT 0
#define NDB_TEMP_TAB_TEMPORARY 1
+
+/*
+ * Table single user mode
+ */
+#define NDB_SUM_LOCKED 0
+#define NDB_SUM_READONLY 1
+#define NDB_SUM_READ_WRITE 2
#endif
diff --git a/storage/ndb/include/ndbapi/NdbDictionary.hpp b/storage/ndb/include/ndbapi/NdbDictionary.hpp
index aada314e454..0a012f867f2 100644
--- a/storage/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp
@@ -576,6 +576,15 @@ public:
*/
class Table : public Object {
public:
+ /*
+ * Single user mode specifies access rights to table during single user mode
+ */
+ enum SingleUserMode {
+ SingleUserModeLocked = NDB_SUM_LOCKED,
+ SingleUserModeReadOnly = NDB_SUM_READONLY,
+ SingleUserModeReadWrite = NDB_SUM_READ_WRITE
+ };
+
/**
* @name General
* @{
@@ -895,6 +904,13 @@ public:
void setMinRows(Uint64 minRows);
Uint64 getMinRows() const;
+ /**
+ * Set/Get SingleUserMode
+ */
+ void setSingleUserMode(enum SingleUserMode);
+ enum SingleUserMode getSingleUserMode() const;
+
+
/** @} *******************************************************************/
/**
diff --git a/storage/ndb/include/ndbapi/NdbRecAttr.hpp b/storage/ndb/include/ndbapi/NdbRecAttr.hpp
index 40d5b598c0c..fe903de6498 100644
--- a/storage/ndb/include/ndbapi/NdbRecAttr.hpp
+++ b/storage/ndb/include/ndbapi/NdbRecAttr.hpp
@@ -131,6 +131,13 @@ public:
/**
* Get value stored in NdbRecAttr object.
+ *
+ * @return Medium value.
+ */
+ Int32 medium_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
*
* @return Short value.
*/
@@ -160,6 +167,13 @@ public:
/**
* Get value stored in NdbRecAttr object.
*
+ * @return Unsigned medium value.
+ */
+ Uint32 u_medium_value() const;
+
+ /**
+ * Get value stored in NdbRecAttr object.
+ *
* @return Unsigned short value.
*/
Uint16 u_short_value() const;
@@ -288,6 +302,16 @@ NdbRecAttr::int32_value() const
}
inline
+Int32
+NdbRecAttr::medium_value() const
+{
+ Uint32 tmp = *(Uint32*)theRef;
+ if (tmp & (0x1<<23))
+ tmp|= (0xFF<<24);
+ return (Int32)tmp;
+}
+
+inline
short
NdbRecAttr::short_value() const
{
@@ -309,6 +333,13 @@ NdbRecAttr::u_32_value() const
}
inline
+Uint32
+NdbRecAttr::u_medium_value() const
+{
+ return *(Uint32*)theRef;
+}
+
+inline
Uint16
NdbRecAttr::u_short_value() const
{
@@ -409,6 +440,25 @@ NdbRecAttr::setUNDEFINED()
class NdbOut& operator <<(class NdbOut&, const NdbRecAttr &);
+class NdbRecordPrintFormat
+{
+public:
+ NdbRecordPrintFormat();
+ virtual ~NdbRecordPrintFormat();
+ const char *lines_terminated_by;
+ const char *fields_terminated_by;
+ const char *start_array_enclosure;
+ const char *end_array_enclosure;
+ const char *fields_enclosed_by;
+ const char *fields_optionally_enclosed_by;
+ const char *hex_prefix;
+ const char *null_string;
+ int hex_format;
+};
+NdbOut&
+ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r,
+ const NdbRecordPrintFormat &f);
+
#endif // ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
#endif
diff --git a/storage/ndb/include/util/OutputStream.hpp b/storage/ndb/include/util/OutputStream.hpp
index 7f75283475f..05fc69a46c3 100644
--- a/storage/ndb/include/util/OutputStream.hpp
+++ b/storage/ndb/include/util/OutputStream.hpp
@@ -37,6 +37,7 @@ class FileOutputStream : public OutputStream {
public:
FileOutputStream(FILE * file = stdout);
virtual ~FileOutputStream() {}
+ FILE *getFile() { return f; }
int print(const char * fmt, ...);
int println(const char * fmt, ...);
diff --git a/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp b/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
index 6d713e53351..49392b9beeb 100644
--- a/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
+++ b/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
@@ -66,6 +66,7 @@ DictTabInfo::TableMapping[] = {
DTIMAP(Table, MaxRowsHigh, MaxRowsHigh),
DTIMAP(Table, MinRowsLow, MinRowsLow),
DTIMAP(Table, MinRowsHigh, MinRowsHigh),
+ DTIMAP(Table, SingleUserMode, SingleUserMode),
DTIBREAK(AttributeName)
};
@@ -164,6 +165,8 @@ DictTabInfo::Table::init(){
MaxRowsHigh = 0;
MinRowsLow = 0;
MinRowsHigh = 0;
+
+ SingleUserMode = 0;
}
void
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index dc6581afd05..46c7c71d886 100644
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -461,6 +461,7 @@ Dbdict::packTableIntoPages(SimpleProperties::Writer & w,
w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
w.add(DictTabInfo::MinRowsLow, tablePtr.p->minRowsLow);
w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh);
+ w.add(DictTabInfo::SingleUserMode, tablePtr.p->singleUserMode);
if(signal)
{
@@ -1871,6 +1872,7 @@ void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr)
tablePtr.p->m_bits = 0;
tablePtr.p->minRowsLow = 0;
tablePtr.p->minRowsHigh = 0;
+ tablePtr.p->singleUserMode = 0;
tablePtr.p->tableType = DictTabInfo::UserTable;
tablePtr.p->primaryTableId = RNIL;
// volatile elements
@@ -5698,7 +5700,9 @@ Dbdict::execTAB_COMMITCONF(Signal* signal){
signal->theData[4] = (Uint32)tabPtr.p->tableType;
signal->theData[5] = createTabPtr.p->key;
signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey;
- sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB);
+ signal->theData[7] = (Uint32)tabPtr.p->singleUserMode;
+
+ sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 8, JBB);
return;
}
@@ -6128,6 +6132,7 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
tablePtr.p->minRowsHigh = c_tableDesc.MinRowsHigh;
tablePtr.p->defaultNoPartFlag = c_tableDesc.DefaultNoPartFlag;
tablePtr.p->linearHashFlag = c_tableDesc.LinearHashFlag;
+ tablePtr.p->singleUserMode = c_tableDesc.SingleUserMode;
{
Rope frm(c_rope_pool, tablePtr.p->frmData);
diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
index 7e98daa39c3..9665f016600 100644
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
@@ -375,6 +375,11 @@ public:
Uint32 fragmentCount;
Uint32 m_tablespace_id;
+
+ /*
+ * Access rights to table during single user mode
+ */
+ Uint8 singleUserMode;
};
typedef Ptr<TableRecord> TableRecordPtr;
diff --git a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index 302e395f19e..42f4033dd4a 100644
--- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -710,6 +710,7 @@ public:
Uint8 tckeyrec; // Ändrad från R
Uint8 tcindxrec;
Uint8 apiFailState; // Ändrad från R
+ Uint8 singleUserMode;
ReturnSignal returnsignal;
Uint8 timeOutCounter;
@@ -961,10 +962,21 @@ public:
struct TableRecord {
TableRecord() {}
Uint32 currentSchemaVersion;
- Uint8 enabled;
- Uint8 dropping;
+ Uint16 m_flags;
Uint8 tableType;
- Uint8 storedTable;
+ Uint8 singleUserMode;
+
+ enum {
+ TR_ENABLED = 1 << 0,
+ TR_DROPPING = 1 << 1,
+ TR_STORED_TABLE = 1 << 2
+ };
+ Uint8 get_enabled() const { return (m_flags & TR_ENABLED) != 0; }
+ Uint8 get_dropping() const { return (m_flags & TR_DROPPING) != 0; }
+ Uint8 get_storedTable() const { return (m_flags & TR_STORED_TABLE) != 0; }
+ void set_enabled(Uint8 f) { f ? m_flags |= (Uint16)TR_ENABLED : m_flags &= ~(Uint16)TR_ENABLED; }
+ void set_dropping(Uint8 f) { f ? m_flags |= (Uint16)TR_DROPPING : m_flags &= ~(Uint16)TR_DROPPING; }
+ void set_storedTable(Uint8 f) { f ? m_flags |= (Uint16)TR_STORED_TABLE : m_flags &= ~(Uint16)TR_STORED_TABLE; }
Uint8 noOfKeyAttr;
Uint8 hasCharAttr;
@@ -972,7 +984,7 @@ public:
Uint8 hasVarKeys;
bool checkTable(Uint32 schemaVersion) const {
- return enabled && !dropping &&
+ return get_enabled() && !get_dropping() &&
(table_version_major(schemaVersion) == table_version_major(currentSchemaVersion));
}
@@ -1840,9 +1852,14 @@ private:
Uint32 transid2);
void removeMarkerForFailedAPI(Signal* signal, Uint32 nodeId, Uint32 bucket);
- bool getAllowStartTransaction() const {
- if(getNodeState().getSingleUserMode())
- return true;
+ bool getAllowStartTransaction(Uint32 nodeId, Uint32 table_single_user_mode) const {
+ if (unlikely(getNodeState().getSingleUserMode()))
+ {
+ if (getNodeState().getSingleUserApi() == nodeId || table_single_user_mode)
+ return true;
+ else
+ return false;
+ }
return getNodeState().startLevel < NodeState::SL_STOPPING_2;
}
diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index 7e7a264d1be..80bd67ee17e 100644
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -330,19 +330,21 @@ void Dbtc::execTC_SCHVERREQ(Signal* signal)
tabptr.i = signal->theData[0];
ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
tabptr.p->currentSchemaVersion = signal->theData[1];
- tabptr.p->storedTable = (bool)signal->theData[2];
+ tabptr.p->m_flags = 0;
+ tabptr.p->set_storedTable((bool)signal->theData[2]);
BlockReference retRef = signal->theData[3];
tabptr.p->tableType = (Uint8)signal->theData[4];
BlockReference retPtr = signal->theData[5];
Uint32 noOfKeyAttr = signal->theData[6];
+ tabptr.p->singleUserMode = (Uint8)signal->theData[7];
ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
- ndbrequire(tabptr.p->enabled == false);
- tabptr.p->enabled = true;
- tabptr.p->dropping = false;
+ ndbrequire(tabptr.p->get_enabled() == false);
+ tabptr.p->set_enabled(true);
+ tabptr.p->set_dropping(false);
tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
tabptr.p->hasCharAttr = desc->hasCharAttr;
tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
@@ -366,7 +368,7 @@ Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
Uint32 senderRef = req->senderRef;
Uint32 senderData = req->senderData;
- if(!tabPtr.p->enabled){
+ if(!tabPtr.p->get_enabled()){
jam();
PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
ref->senderRef = reference();
@@ -378,7 +380,7 @@ Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
return;
}
- if(tabPtr.p->dropping){
+ if(tabPtr.p->get_dropping()){
jam();
PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
ref->senderRef = reference();
@@ -390,7 +392,7 @@ Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
return;
}
- tabPtr.p->dropping = true;
+ tabPtr.p->set_dropping(true);
tabPtr.p->dropTable.senderRef = senderRef;
tabPtr.p->dropTable.senderData = senderData;
@@ -426,7 +428,7 @@ Dbtc::execWAIT_DROP_TAB_CONF(Signal* signal)
tabPtr.i = conf->tableId;
ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
- ndbrequire(tabPtr.p->dropping == true);
+ ndbrequire(tabPtr.p->get_dropping() == true);
Uint32 nodeId = refToNode(conf->senderRef);
tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
@@ -456,7 +458,7 @@ Dbtc::execWAIT_DROP_TAB_REF(Signal* signal)
tabPtr.i = ref->tableId;
ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
- ndbrequire(tabPtr.p->dropping == true);
+ ndbrequire(tabPtr.p->get_dropping() == true);
Uint32 nodeId = refToNode(ref->senderRef);
tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
@@ -493,7 +495,7 @@ Dbtc::checkWaitDropTabFailedLqh(Signal* signal, Uint32 nodeId, Uint32 tableId)
for(Uint32 i = 0; i<RT_BREAK && tabPtr.i < ctabrecFilesize; i++, tabPtr.i++){
jam();
ptrAss(tabPtr, tableRecord);
- if(tabPtr.p->enabled && tabPtr.p->dropping){
+ if(tabPtr.p->get_enabled() && tabPtr.p->get_dropping()){
if(tabPtr.p->dropTable.waitDropTabCount.isWaitingFor(nodeId)){
jam();
conf->senderRef = calcLqhBlockRef(nodeId);
@@ -534,7 +536,7 @@ Dbtc::execDROP_TAB_REQ(Signal* signal)
Uint32 senderData = req->senderData;
DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
- if(!tabPtr.p->enabled && rt == DropTabReq::OnlineDropTab){
+ if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
jam();
DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
ref->senderRef = reference();
@@ -546,7 +548,7 @@ Dbtc::execDROP_TAB_REQ(Signal* signal)
return;
}
- if(!tabPtr.p->dropping && rt == DropTabReq::OnlineDropTab){
+ if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
jam();
DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
ref->senderRef = reference();
@@ -558,8 +560,8 @@ Dbtc::execDROP_TAB_REQ(Signal* signal)
return;
}
- tabPtr.p->enabled = false;
- tabPtr.p->dropping = false;
+ tabPtr.p->set_enabled(false);
+ tabPtr.p->set_dropping(false);
DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
conf->tableId = tabPtr.i;
@@ -1202,16 +1204,14 @@ void Dbtc::execTCSEIZEREQ(Signal* signal)
const NodeId senderNodeId = refToNode(tapiBlockref);
const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0;
- if(!(senderNodeId == getNodeState().getSingleUserApi()) &&
- !getNodeState().getSingleUserMode()) {
- if(!(sl==NodeState::SL_SINGLEUSER &&
- senderNodeId == getNodeState().getSingleUserApi())) {
+ {
+ {
if (!(sl == NodeState::SL_STARTED ||
(sl == NodeState::SL_STARTING && local == true))) {
jam();
- Uint32 errCode;
- if(!(sl == NodeState::SL_SINGLEUSER && local))
+ Uint32 errCode = 0;
+ if(!local)
{
switch(sl){
case NodeState::SL_STARTING:
@@ -1219,6 +1219,8 @@ void Dbtc::execTCSEIZEREQ(Signal* signal)
break;
case NodeState::SL_STOPPING_1:
case NodeState::SL_STOPPING_2:
+ if (getNodeState().getSingleUserMode())
+ break;
case NodeState::SL_STOPPING_3:
case NodeState::SL_STOPPING_4:
if(getNodeState().stopping.systemShutdown)
@@ -1227,16 +1229,18 @@ void Dbtc::execTCSEIZEREQ(Signal* signal)
errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
break;
case NodeState::SL_SINGLEUSER:
- errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
break;
default:
errCode = ZWRONG_STATE;
break;
}
- signal->theData[0] = tapiPointer;
- signal->theData[1] = errCode;
- sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
- return;
+ if (errCode)
+ {
+ signal->theData[0] = tapiPointer;
+ signal->theData[1] = errCode;
+ sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
+ return;
+ }
}//if (!(sl == SL_SINGLEUSER))
} //if
}
@@ -1724,8 +1728,14 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
* Initialize object before starting error handling
*/
initApiConnectRec(signal, apiConnectptr.p, true);
+start_failure:
switch(getNodeState().startLevel){
case NodeState::SL_STOPPING_2:
+ if (getNodeState().getSingleUserMode())
+ {
+ terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
+ break;
+ }
case NodeState::SL_STOPPING_3:
case NodeState::SL_STOPPING_4:
if(getNodeState().stopping.systemShutdown)
@@ -1736,6 +1746,12 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
case NodeState::SL_SINGLEUSER:
terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
break;
+ case NodeState::SL_STOPPING_1:
+ if (getNodeState().getSingleUserMode())
+ {
+ terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
+ break;
+ }
default:
terrorCode = ZWRONG_STATE;
break;
@@ -1757,6 +1773,13 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
return;
}
+ case 60:
+ {
+ jam();
+ initApiConnectRec(signal, apiConnectptr.p, true);
+ apiConnectptr.p->m_exec_flag = 1;
+ goto start_failure;
+ }
default:
jam();
systemErrorLab(signal, __LINE__);
@@ -2377,6 +2400,7 @@ void Dbtc::initApiConnectRec(Signal* signal,
regApiPtr->buddyPtr = RNIL;
regApiPtr->currSavePointId = 0;
regApiPtr->m_transaction_nodes.clear();
+ regApiPtr->singleUserMode = 0;
// Trigger data
releaseFiredTriggerData(&regApiPtr->theFiredTriggers),
// Index data
@@ -2486,6 +2510,7 @@ Dbtc::seizeCacheRecord(Signal* signal)
/*****************************************************************************/
void Dbtc::execTCKEYREQ(Signal* signal)
{
+ Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef());
UintR compare_transid1, compare_transid2;
UintR titcLenAiInTckeyreq;
UintR TkeyLength;
@@ -2529,9 +2554,12 @@ void Dbtc::execTCKEYREQ(Signal* signal)
bool isIndexOpReturn = regApiPtr->indexOpReturn;
regApiPtr->isIndexOp = false; // Reset marker
regApiPtr->m_exec_flag |= TexecFlag;
+ TableRecordPtr localTabptr;
+ localTabptr.i = TtabIndex;
+ localTabptr.p = &tableRecord[TtabIndex];
switch (regApiPtr->apiConnectstate) {
case CS_CONNECTED:{
- if (TstartFlag == 1 && getAllowStartTransaction() == true){
+ if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
//---------------------------------------------------------------------
// Initialise API connect record if transaction is started.
//---------------------------------------------------------------------
@@ -2539,7 +2567,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
initApiConnectRec(signal, regApiPtr);
regApiPtr->m_exec_flag = TexecFlag;
} else {
- if(getAllowStartTransaction() == true){
+ if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
/*------------------------------------------------------------------
* WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
* RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
@@ -2549,9 +2577,9 @@ void Dbtc::execTCKEYREQ(Signal* signal)
return;
} else {
/**
- * getAllowStartTransaction() == false
+ * getAllowStartTransaction(sendersNodeId) == false
*/
- TCKEY_abort(signal, 57);
+ TCKEY_abort(signal, TexecFlag ? 60 : 57);
return;
}//if
}
@@ -2566,6 +2594,13 @@ void Dbtc::execTCKEYREQ(Signal* signal)
* the state will be CS_STARTED
*/
jam();
+ if (unlikely(getNodeState().getSingleUserMode()) &&
+ getNodeState().getSingleUserApi() != sendersNodeId &&
+ !localTabptr.p->singleUserMode)
+ {
+ TCKEY_abort(signal, TexecFlag ? 60 : 57);
+ return;
+ }
initApiConnectRec(signal, regApiPtr);
regApiPtr->m_exec_flag = TexecFlag;
} else {
@@ -2586,6 +2621,10 @@ void Dbtc::execTCKEYREQ(Signal* signal)
case CS_ABORTING:
if (regApiPtr->abortState == AS_IDLE) {
if (TstartFlag == 1) {
+ if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == false){
+ TCKEY_abort(signal, TexecFlag ? 60 : 57);
+ return;
+ }
//--------------------------------------------------------------------
// Previous transaction had been aborted and the abort was completed.
// It is then OK to start a new transaction again.
@@ -2649,9 +2688,6 @@ void Dbtc::execTCKEYREQ(Signal* signal)
return;
}//switch
- TableRecordPtr localTabptr;
- localTabptr.i = TtabIndex;
- localTabptr.p = &tableRecord[TtabIndex];
if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) {
;
} else {
@@ -2710,6 +2746,8 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regTcPtr->savePointId = regApiPtr->currSavePointId;
regApiPtr->executingIndexOp = RNIL;
+ regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
+
if (TcKeyReq::getExecutingTrigger(Treqinfo)) {
// Save the TcOperationPtr for fireing operation
regTcPtr->triggeringOperation = TsenderData;
@@ -2841,7 +2879,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
* THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND
* TEMP TABLES DON'T PARTICIPATE.
* -------------------------------------------------------------------- */
- if (localTabptr.p->storedTable) {
+ if (localTabptr.p->get_storedTable()) {
coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
}
c_counters.cwriteCount = TwriteCount + 1;
@@ -4674,6 +4712,7 @@ void Dbtc::copyApi(Signal* signal)
regApiPtr->lqhkeyconfrec = Tlqhkeyconfrec;
regApiPtr->commitAckMarker = TcommitAckMarker;
regApiPtr->m_transaction_nodes = Tnodes;
+ regApiPtr->singleUserMode = 0;
gcpPtr.i = TgcpPointer;
ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord);
@@ -4685,6 +4724,7 @@ void Dbtc::copyApi(Signal* signal)
regTmpApiPtr->firstTcConnect = RNIL;
regTmpApiPtr->lastTcConnect = RNIL;
regTmpApiPtr->m_transaction_nodes.clear();
+ regTmpApiPtr->singleUserMode = 0;
releaseAllSeizedIndexOperations(regTmpApiPtr);
}//Dbtc::copyApi()
@@ -6154,9 +6194,11 @@ and otherwise we spread it out 310 ms.
void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
{
Uint32 end_ptr, time_passed, time_out_value, mask_value;
+ Uint32 old_mask_value= 0;
const Uint32 api_con_sz= capiConnectFilesize;
const Uint32 tc_timer= ctcTimer;
const Uint32 time_out_param= ctimeOutValue;
+ const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
ctimeOutCheckHeartbeat = tc_timer;
@@ -6177,16 +6219,50 @@ void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
jam();
mask_value= 31;
}
+ if (time_out_param != old_time_out_param &&
+ getNodeState().getSingleUserMode())
+ {
+ // abort during single user mode, use old_mask_value as flag
+ // and calculate value to be used for connections with allowed api
+ if (old_time_out_param > 300) {
+ jam();
+ old_mask_value= 63;
+ } else if (old_time_out_param < 30) {
+ jam();
+ old_mask_value= 7;
+ } else {
+ jam();
+ old_mask_value= 31;
+ }
+ }
for ( ; api_con_ptr < end_ptr; api_con_ptr++) {
Uint32 api_timer= getApiConTimer(api_con_ptr);
jam();
if (api_timer != 0) {
+ Uint32 error= ZTIME_OUT_ERROR;
time_out_value= time_out_param + (api_con_ptr & mask_value);
+ if (unlikely(old_mask_value)) // abort during single user mode
+ {
+ apiConnectptr.i = api_con_ptr;
+ ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
+ if ((getNodeState().getSingleUserApi() ==
+ refToNode(apiConnectptr.p->ndbapiBlockref)) ||
+ !(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
+ {
+ // api allowed during single user, use original timeout
+ time_out_value=
+ old_time_out_param + (api_con_ptr & old_mask_value);
+ }
+ else
+ {
+ error= ZCLUSTER_IN_SINGLEUSER_MODE;
+ }
+ }
time_passed= tc_timer - api_timer;
if (time_passed > time_out_value)
{
jam();
- timeOutFoundLab(signal, api_con_ptr, ZTIME_OUT_ERROR);
+ timeOutFoundLab(signal, api_con_ptr, error);
api_con_ptr++;
break;
}
@@ -6226,7 +6302,8 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
<< " code: " << errCode);
switch (apiConnectptr.p->apiConnectstate) {
case CS_STARTED:
- if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec){
+ if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec &&
+ errCode != ZCLUSTER_IN_SINGLEUSER_MODE){
jam();
/*
We are waiting for application to continue the transaction. In this
@@ -6798,6 +6875,33 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
c_scan_frag_pool.getPtr(ptr, TscanConPtr);
DEBUG(TscanConPtr << " timeOutFoundFragLab: scanFragState = "<< ptr.p->scanFragState);
+ const Uint32 time_out_param= ctimeOutValue;
+ const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
+
+ if (unlikely(time_out_param != old_time_out_param &&
+ getNodeState().getSingleUserMode()))
+ {
+ jam();
+ ScanRecordPtr scanptr;
+ scanptr.i = ptr.p->scanRec;
+ ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+ ApiConnectRecordPtr TlocalApiConnectptr;
+ TlocalApiConnectptr.i = scanptr.p->scanApiRec;
+ ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
+
+ if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) ==
+ getNodeState().getSingleUserApi())
+ {
+ jam();
+ Uint32 val = ctcTimer - ptr.p->scanFragTimer;
+ if (val <= old_time_out_param)
+ {
+ jam();
+ goto next;
+ }
+ }
+ }
+
/*-------------------------------------------------------------------------*/
// The scan fragment has expired its timeout. Check its state to decide
// what to do.
@@ -6859,6 +6963,7 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
break;
}//switch
+next:
signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
signal->theData[1] = TscanConPtr + 1;
sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
@@ -8077,6 +8182,7 @@ void Dbtc::initApiConnectFail(Signal* signal)
apiConnectptr.p->ndbapiConnect = 0;
apiConnectptr.p->buddyPtr = RNIL;
apiConnectptr.p->m_transaction_nodes.clear();
+ apiConnectptr.p->singleUserMode = 0;
setApiConTimer(apiConnectptr.i, 0, __LINE__);
switch(ttransStatus){
case LqhTransConf::Committed:
@@ -8689,6 +8795,14 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
}
}
+ if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
+ getNodeState().getSingleUserApi() !=
+ refToNode(apiConnectptr.p->ndbapiBlockref))
+ {
+ errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
+ goto SCAN_TAB_error;
+ }
+
seizeTcConnect(signal);
tcConnectptr.p->apiConnect = apiConnectptr.i;
tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN;
@@ -9984,6 +10098,7 @@ void Dbtc::initApiConnect(Signal* signal)
apiConnectptr.p->buddyPtr = RNIL;
apiConnectptr.p->currSavePointId = 0;
apiConnectptr.p->m_transaction_nodes.clear();
+ apiConnectptr.p->singleUserMode = 0;
}//for
apiConnectptr.i = tiacTmp - 1;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -10012,6 +10127,7 @@ void Dbtc::initApiConnect(Signal* signal)
apiConnectptr.p->buddyPtr = RNIL;
apiConnectptr.p->currSavePointId = 0;
apiConnectptr.p->m_transaction_nodes.clear();
+ apiConnectptr.p->singleUserMode = 0;
}//for
apiConnectptr.i = (2 * tiacTmp) - 1;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -10040,6 +10156,7 @@ void Dbtc::initApiConnect(Signal* signal)
apiConnectptr.p->buddyPtr = RNIL;
apiConnectptr.p->currSavePointId = 0;
apiConnectptr.p->m_transaction_nodes.clear();
+ apiConnectptr.p->singleUserMode = 0;
}//for
apiConnectptr.i = (3 * tiacTmp) - 1;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -10224,10 +10341,11 @@ void Dbtc::initTable(Signal* signal)
refresh_watch_dog();
ptrAss(tabptr, tableRecord);
tabptr.p->currentSchemaVersion = 0;
- tabptr.p->storedTable = true;
+ tabptr.p->m_flags = 0;
+ tabptr.p->set_storedTable(true);
tabptr.p->tableType = 0;
- tabptr.p->enabled = false;
- tabptr.p->dropping = false;
+ tabptr.p->set_enabled(false);
+ tabptr.p->set_dropping(false);
tabptr.p->noOfKeyAttr = 0;
tabptr.p->hasCharAttr = 0;
tabptr.p->noOfDistrKeys = 0;
@@ -10361,6 +10479,7 @@ void Dbtc::releaseAbortResources(Signal* signal)
apiConnectptr.p->firstTcConnect = RNIL;
apiConnectptr.p->lastTcConnect = RNIL;
apiConnectptr.p->m_transaction_nodes.clear();
+ apiConnectptr.p->singleUserMode = 0;
// MASV let state be CS_ABORTING until all
// signals in the "air" have been received. Reset to CS_CONNECTED
@@ -11009,7 +11128,7 @@ void Dbtc::execABORT_ALL_REQ(Signal* signal)
const Uint32 senderData = req->senderData;
const BlockReference senderRef = req->senderRef;
- if(getAllowStartTransaction() == true && !getNodeState().getSingleUserMode()){
+ if(getAllowStartTransaction(refToNode(senderRef), 0) == true && !getNodeState().getSingleUserMode()){
jam();
ref->senderData = senderData;
@@ -11437,6 +11556,17 @@ void Dbtc::execTCINDXREQ(Signal* signal)
regApiPtr->transid[1] = tcIndxReq->transId2;
}//if
+ if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
+ getNodeState().getSingleUserApi() !=
+ refToNode(regApiPtr->ndbapiBlockref))
+ {
+ terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
+ regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo);
+ apiConnectptr = transPtr;
+ abortErrorLab(signal);
+ return;
+ }
+
if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
jam();
// Failed to allocate index operation
@@ -13275,9 +13405,9 @@ void Dbtc::deleteFromIndexTable(Signal* signal,
Uint32
Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
- if(!enabled)
+ if(!get_enabled())
return ZNO_SUCH_TABLE;
- if(dropping)
+ if(get_dropping())
return ZDROP_TABLE_IN_PROGRESS;
if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
return ZWRONG_SCHEMA_VERSION_ERROR;
diff --git a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index 672c11f32e1..adc6d1e3ed4 100644
--- a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -1684,6 +1684,7 @@ void Ndbcntr::createSystableLab(Signal* signal, unsigned index)
//w.add(DictTabInfo::NoOfVariable, (Uint32)0);
//w.add(DictTabInfo::KeyLength, 1);
w.add(DictTabInfo::TableTypeVal, (Uint32)table.tableType);
+ w.add(DictTabInfo::SingleUserMode, (Uint32)NDB_SUM_READ_WRITE);
for (unsigned i = 0; i < table.columnCount; i++) {
const SysColumn& column = table.columnList[i];
diff --git a/storage/ndb/src/ndbapi/ClusterMgr.cpp b/storage/ndb/src/ndbapi/ClusterMgr.cpp
index 2a794f69ecb..52c95df6d15 100644
--- a/storage/ndb/src/ndbapi/ClusterMgr.cpp
+++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp
@@ -389,7 +389,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){
node.m_state = apiRegConf->nodeState;
if (node.compatible && (node.m_state.startLevel == NodeState::SL_STARTED ||
- node.m_state.startLevel == NodeState::SL_SINGLEUSER)){
+ node.m_state.getSingleUserMode())){
set_node_alive(node, true);
} else {
set_node_alive(node, false);
diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp
index e90dfbfa959..495b848645f 100644
--- a/storage/ndb/src/ndbapi/Ndb.cpp
+++ b/storage/ndb/src/ndbapi/Ndb.cpp
@@ -58,6 +58,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode)
// We have connections now to the desired node. Return
//****************************************************************************
DBUG_RETURN(getConnectedNdbTransaction(tConNode));
+ } else if (TretCode < 0) {
+ DBUG_RETURN(NULL);
} else if (TretCode != 0) {
tAnyAlive = 1;
}//if
@@ -81,6 +83,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode)
// We have connections now to the desired node. Return
//****************************************************************************
DBUG_RETURN(getConnectedNdbTransaction(tNode));
+ } else if (TretCode < 0) {
+ DBUG_RETURN(NULL);
} else if (TretCode != 0) {
tAnyAlive= 1;
}//if
@@ -109,6 +113,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode)
// We have connections now to the desired node. Return
//****************************************************************************
DBUG_RETURN(getConnectedNdbTransaction(tNode));
+ } else if (TretCode < 0) {
+ DBUG_RETURN(NULL);
} else if (TretCode != 0) {
tAnyAlive= 1;
}//if
@@ -195,6 +201,11 @@ Ndb::NDB_connect(Uint32 tNode)
DBUG_PRINT("info",
("unsuccessful connect tReturnCode %d, tNdbCon->Status() %d",
tReturnCode, tNdbCon->Status()));
+ if (theError.code == 299)
+ {
+ // single user mode so no need to retry with other node
+ DBUG_RETURN(-1);
+ }
DBUG_RETURN(3);
}//if
}//Ndb::NDB_connect()
diff --git a/storage/ndb/src/ndbapi/NdbDictionary.cpp b/storage/ndb/src/ndbapi/NdbDictionary.cpp
index 47ba0335183..b7a7087c302 100644
--- a/storage/ndb/src/ndbapi/NdbDictionary.cpp
+++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp
@@ -495,6 +495,18 @@ NdbDictionary::Table::getFrmLength() const {
return m_impl.getFrmLength();
}
+enum NdbDictionary::Table::SingleUserMode
+NdbDictionary::Table::getSingleUserMode() const
+{
+ return (enum SingleUserMode)m_impl.m_single_user_mode;
+}
+
+void
+NdbDictionary::Table::setSingleUserMode(enum NdbDictionary::Table::SingleUserMode mode)
+{
+ m_impl.m_single_user_mode = (Uint8)mode;
+}
+
void
NdbDictionary::Table::setTablespaceNames(const void *data, Uint32 len)
{
diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index 917f4e17051..2bd59c6e06f 100644
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -51,7 +51,7 @@
#define ERR_RETURN(a,b) \
{\
- DBUG_PRINT("exit", ("error %d", (a).code));\
+ DBUG_PRINT("exit", ("error %d return %d", (a).code, b));\
DBUG_RETURN(b);\
}
@@ -470,6 +470,7 @@ NdbTableImpl::init(){
m_tablespace_name.clear();
m_tablespace_id = ~0;
m_tablespace_version = ~0;
+ m_single_user_mode = 0;
}
bool
@@ -663,6 +664,15 @@ NdbTableImpl::equal(const NdbTableImpl& obj) const
DBUG_RETURN(false);
}
}
+
+ if(m_single_user_mode != obj.m_single_user_mode)
+ {
+ DBUG_PRINT("info",("m_single_user_mode %d != %d",
+ (int32)m_single_user_mode,
+ (int32)obj.m_single_user_mode));
+ DBUG_RETURN(false);
+ }
+
DBUG_RETURN(true);
}
@@ -726,6 +736,8 @@ NdbTableImpl::assign(const NdbTableImpl& org)
m_keyLenInWords = org.m_keyLenInWords;
m_fragmentCount = org.m_fragmentCount;
+ m_single_user_mode = org.m_single_user_mode;
+
if (m_index != 0)
delete m_index;
m_index = org.m_index;
@@ -2103,6 +2115,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
impl->m_kvalue = tableDesc->TableKValue;
impl->m_minLoadFactor = tableDesc->MinLoadFactor;
impl->m_maxLoadFactor = tableDesc->MaxLoadFactor;
+ impl->m_single_user_mode = tableDesc->SingleUserMode;
impl->m_indexType = (NdbDictionary::Object::Type)
getApiConstant(tableDesc->TableType,
@@ -2564,6 +2577,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
tmpTab->MinRowsLow = (Uint32)(impl.m_min_rows & 0xFFFFFFFF);
tmpTab->DefaultNoPartFlag = impl.m_default_no_part_flag;
tmpTab->LinearHashFlag = impl.m_linear_flag;
+ tmpTab->SingleUserMode = impl.m_single_user_mode;
if (impl.m_ts_name.length())
{
diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index 26d7c13f968..b474b6e7fc0 100644
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -204,6 +204,7 @@ public:
int m_maxLoadFactor;
Uint16 m_keyLenInWords;
Uint16 m_fragmentCount;
+ Uint8 m_single_user_mode;
NdbIndexImpl * m_index;
NdbColumnImpl * getColumn(unsigned attrId);
diff --git a/storage/ndb/src/ndbapi/NdbRecAttr.cpp b/storage/ndb/src/ndbapi/NdbRecAttr.cpp
index 188e718d968..0bd0cdf8572 100644
--- a/storage/ndb/src/ndbapi/NdbRecAttr.cpp
+++ b/storage/ndb/src/ndbapi/NdbRecAttr.cpp
@@ -138,8 +138,24 @@ NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz)
return false;
}
+NdbRecordPrintFormat::NdbRecordPrintFormat()
+{
+ fields_terminated_by= ";";
+ start_array_enclosure= "[";
+ end_array_enclosure= "]";
+ fields_enclosed_by= "";
+ fields_optionally_enclosed_by= "\"";
+ lines_terminated_by= "\n";
+ hex_prefix= "H'";
+ null_string= "[NULL]";
+ hex_format= 0;
+}
+NdbRecordPrintFormat::~NdbRecordPrintFormat() {}
+static const NdbRecordPrintFormat default_print_format;
+
static void
-ndbrecattr_print_string(NdbOut& out, const char *type,
+ndbrecattr_print_string(NdbOut& out, const NdbRecordPrintFormat &f,
+ const char *type, bool is_binary,
const char *aref, unsigned sz)
{
const unsigned char* ref = (const unsigned char*)aref;
@@ -148,6 +164,25 @@ ndbrecattr_print_string(NdbOut& out, const char *type,
for (i=sz-1; i >= 0; i--)
if (ref[i] == 0) sz--;
else break;
+ if (!is_binary)
+ {
+ // trailing spaces are not printed
+ for (i=sz-1; i >= 0; i--)
+ if (ref[i] == 32) sz--;
+ else break;
+ }
+ if (is_binary && f.hex_format)
+ {
+ if (sz == 0)
+ {
+ out.print("0x0");
+ return;
+ }
+ out.print("0x");
+ for (len = 0; len < (int)sz; len++)
+ out.print("%02X", (int)ref[len]);
+ return;
+ }
if (sz == 0) return; // empty
for (len=0; len < (int)sz && ref[i] != 0; len++)
@@ -168,37 +203,68 @@ ndbrecattr_print_string(NdbOut& out, const char *type,
for (i= len+1; ref[i] != 0; i++)
out.print("%u]",len-i);
assert((int)sz > i);
- ndbrecattr_print_string(out,type,aref+i,sz-i);
+ ndbrecattr_print_string(out,f,type,is_binary,aref+i,sz-i);
}
}
-NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
+NdbOut&
+ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r,
+ const NdbRecordPrintFormat &f)
{
if (r.isNULL())
{
- out << "[NULL]";
+ out << f.null_string;
return out;
}
const NdbDictionary::Column* c = r.getColumn();
uint length = c->getLength();
- if (length > 1)
- out << "[";
-
- for (Uint32 j = 0; j < length; j++)
{
- if (j > 0)
- out << " ";
-
+ const char *fields_optionally_enclosed_by;
+ if (f.fields_enclosed_by[0] == '\0')
+ fields_optionally_enclosed_by=
+ f.fields_optionally_enclosed_by;
+ else
+ fields_optionally_enclosed_by= "";
+ out << f.fields_enclosed_by;
+ Uint32 j;
switch(r.getType()){
case NdbDictionary::Column::Bigunsigned:
out << r.u_64_value();
break;
case NdbDictionary::Column::Bit:
- out << hex << "H'" << r.u_32_value() << dec;
+ out << f.hex_prefix << "0x";
+ if (length < 33)
+ {
+ out.print("%X", r.u_32_value());
+ }
+ else if (length < 65)
+ {
+ out.print("%llX", r.u_64_value());
+ }
+ else
+ {
+ const unsigned char *buf = (unsigned char *)r.aRef();
+ int k = 4*((length+31)/32);
+ while (k > 0 && (*(buf + --k) == 0));
+ do
+ {
+ out.print("%X", (Uint32)*(buf + k--));
+ }
+ while (k >= 0);
+ }
break;
case NdbDictionary::Column::Unsigned:
- out << *((Uint32*)r.aRef() + j);
+ if (length > 1)
+ out << f.start_array_enclosure;
+ out << *(Uint32*)r.aRef();
+ for (j = 1; j < length; j++)
+ out << " " << *((Uint32*)r.aRef() + j);
+ if (length > 1)
+ out << f.end_array_enclosure;
+ break;
+ case NdbDictionary::Column::Mediumunsigned:
+ out << r.u_medium_value();
break;
case NdbDictionary::Column::Smallunsigned:
out << r.u_short_value();
@@ -212,6 +278,9 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
case NdbDictionary::Column::Int:
out << r.int32_value();
break;
+ case NdbDictionary::Column::Mediumint:
+ out << r.medium_value();
+ break;
case NdbDictionary::Column::Smallint:
out << r.short_value();
break;
@@ -219,25 +288,37 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
out << (int) r.char_value();
break;
case NdbDictionary::Column::Binary:
+ if (!f.hex_format)
+ out << fields_optionally_enclosed_by;
j = r.get_size_in_bytes();
- ndbrecattr_print_string(out,"Binary", r.aRef(), j);
+ ndbrecattr_print_string(out,f,"Binary", true, r.aRef(), j);
+ if (!f.hex_format)
+ out << fields_optionally_enclosed_by;
break;
case NdbDictionary::Column::Char:
+ out << fields_optionally_enclosed_by;
j = r.get_size_in_bytes();
- ndbrecattr_print_string(out,"Char", r.aRef(), j);
+ ndbrecattr_print_string(out,f,"Char", false, r.aRef(), j);
+ out << fields_optionally_enclosed_by;
break;
case NdbDictionary::Column::Varchar:
{
+ out << fields_optionally_enclosed_by;
unsigned len = *(const unsigned char*)r.aRef();
- ndbrecattr_print_string(out,"Varchar", r.aRef()+1,len);
+ ndbrecattr_print_string(out,f,"Varchar", false, r.aRef()+1,len);
j = length;
+ out << fields_optionally_enclosed_by;
}
break;
case NdbDictionary::Column::Varbinary:
{
+ if (!f.hex_format)
+ out << fields_optionally_enclosed_by;
unsigned len = *(const unsigned char*)r.aRef();
- ndbrecattr_print_string(out,"Varbinary", r.aRef()+1,len);
+ ndbrecattr_print_string(out,f,"Varbinary", true, r.aRef()+1,len);
j = length;
+ if (!f.hex_format)
+ out << fields_optionally_enclosed_by;
}
break;
case NdbDictionary::Column::Float:
@@ -366,16 +447,26 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
break;
case NdbDictionary::Column::Longvarchar:
{
+ out << fields_optionally_enclosed_by;
+ unsigned len = uint2korr(r.aRef());
+ ndbrecattr_print_string(out,f,"Longvarchar", false, r.aRef()+2,len);
+ j = length;
+ out << fields_optionally_enclosed_by;
+ }
+ break;
+ case NdbDictionary::Column::Longvarbinary:
+ {
+ if (!f.hex_format)
+ out << fields_optionally_enclosed_by;
unsigned len = uint2korr(r.aRef());
- ndbrecattr_print_string(out,"Longvarchar", r.aRef()+2,len);
+ ndbrecattr_print_string(out,f,"Longvarbinary", true, r.aRef()+2,len);
j = length;
+ if (!f.hex_format)
+ out << fields_optionally_enclosed_by;
}
break;
case NdbDictionary::Column::Undefined:
- case NdbDictionary::Column::Mediumint:
- case NdbDictionary::Column::Mediumunsigned:
- case NdbDictionary::Column::Longvarbinary:
unknown:
//default: /* no print functions for the rest, just print type */
out << (int) r.getType();
@@ -384,16 +475,17 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
out << " " << j << " times";
break;
}
- }
-
- if (length > 1)
- {
- out << "]";
+ out << f.fields_enclosed_by;
}
return out;
}
+NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
+{
+ return ndbrecattr_print_formatted(out, r, default_print_format);
+}
+
Int64
NdbRecAttr::int64_value() const
{
diff --git a/storage/ndb/src/ndbapi/TransporterFacade.hpp b/storage/ndb/src/ndbapi/TransporterFacade.hpp
index d19974f8999..23fea8792f7 100644
--- a/storage/ndb/src/ndbapi/TransporterFacade.hpp
+++ b/storage/ndb/src/ndbapi/TransporterFacade.hpp
@@ -365,7 +365,8 @@ inline
bool
TransporterFacade::get_node_stopping(NodeId n) const {
const ClusterMgr::Node & node = theClusterMgr->getNodeInfo(n);
- return ((node.m_state.startLevel == NodeState::SL_STOPPING_1) ||
+ return (!node.m_state.getSingleUserMode() &&
+ (node.m_state.startLevel == NodeState::SL_STOPPING_1) ||
(node.m_state.startLevel == NodeState::SL_STOPPING_2));
}
@@ -376,16 +377,9 @@ TransporterFacade::getIsNodeSendable(NodeId n) const {
const Uint32 startLevel = node.m_state.startLevel;
if (node.m_info.m_type == NodeInfo::DB) {
- if(node.m_state.singleUserMode &&
- ownId() == node.m_state.singleUserApi) {
- return (node.compatible &&
- (node.m_state.startLevel == NodeState::SL_STOPPING_1 ||
- node.m_state.startLevel == NodeState::SL_STARTED ||
- node.m_state.startLevel == NodeState::SL_SINGLEUSER));
- }
- else
- return node.compatible && (startLevel == NodeState::SL_STARTED ||
- startLevel == NodeState::SL_STOPPING_1);
+ return node.compatible && (startLevel == NodeState::SL_STARTED ||
+ startLevel == NodeState::SL_STOPPING_1 ||
+ node.m_state.getSingleUserMode());
} else {
ndbout_c("TransporterFacade::getIsNodeSendable: Illegal node type: "
"%d of node: %d",
diff --git a/storage/ndb/test/src/NDBT_Table.cpp b/storage/ndb/test/src/NDBT_Table.cpp
index d6a0b014fda..f970aae972b 100644
--- a/storage/ndb/test/src/NDBT_Table.cpp
+++ b/storage/ndb/test/src/NDBT_Table.cpp
@@ -33,7 +33,7 @@ operator <<(class NdbOut& ndbout, const NDBT_Table & tab)
ndbout << "Length of frm data: " << tab.getFrmLength() << endl;
ndbout << "Row Checksum: " << tab.getRowChecksumIndicator() << endl;
ndbout << "Row GCI: " << tab.getRowGCIIndicator() << endl;
-
+ ndbout << "SingleUserMode: " << tab.getSingleUserMode() << endl;
//<< ((tab.getTupleKey() == TupleId) ? " tupleid" : "") <<endl;
ndbout << "TableStatus: ";
diff --git a/storage/ndb/tools/restore/Restore.cpp b/storage/ndb/tools/restore/Restore.cpp
index 6b00d69108d..f99cacfc613 100644
--- a/storage/ndb/tools/restore/Restore.cpp
+++ b/storage/ndb/tools/restore/Restore.cpp
@@ -27,6 +27,7 @@
#include <NdbAutoPtr.hpp>
#include "../../../../sql/ha_ndbcluster_tables.h"
+extern NdbRecordPrintFormat g_ndbrecord_print_format;
Uint16 Twiddle16(Uint16 in); // Byte shift 16-bit data
Uint32 Twiddle32(Uint32 in); // Byte shift 32-bit data
@@ -298,6 +299,7 @@ RestoreMetaData::markSysTables()
Uint32 i;
for (i = 0; i < getNoOfTables(); i++) {
TableS* table = allTables[i];
+ table->m_local_id = i;
const char* tableName = table->getTableName();
if ( // XXX should use type
strcmp(tableName, "SYSTAB_0") == 0 ||
@@ -314,6 +316,7 @@ 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;
}
for (i = 0; i < getNoOfTables(); i++) {
@@ -331,6 +334,7 @@ RestoreMetaData::markSysTables()
if (table->getTableId() == (Uint32) id1) {
if (table->isSysTable)
blobTable->isSysTable = true;
+ blobTable->m_main_table = table;
break;
}
}
@@ -428,6 +432,7 @@ TableS::TableS(Uint32 version, NdbTableImpl* tableImpl)
m_noOfRecords= 0;
backupVersion = version;
isSysTable = false;
+ m_main_table = NULL;
for (int i = 0; i < tableImpl->getNoOfColumns(); i++)
createAttr(tableImpl->getColumn(i));
@@ -897,6 +902,7 @@ bool RestoreDataIterator::readFragmentHeader(int & ret, Uint32 *fragmentId)
return false;
}
+ info.setLevel(254);
info << "_____________________________________________________" << endl
<< "Processing data in table: " << m_currentTable->getTableName()
<< "(" << Header.TableId << ") fragment "
@@ -1154,14 +1160,14 @@ operator<<(NdbOut& ndbout, const AttributeS& attr){
if (data.null)
{
- ndbout << "<NULL>";
+ ndbout << g_ndbrecord_print_format.null_string;
return ndbout;
}
NdbRecAttr tmprec(0);
- tmprec.setup(desc.m_column, (char *)data.void_value);
+ tmprec.setup(desc.m_column, 0);
tmprec.receive_data((Uint32*)data.void_value, data.size);
- ndbout << tmprec;
+ ndbrecattr_print_formatted(ndbout, tmprec, g_ndbrecord_print_format);
return ndbout;
}
@@ -1170,17 +1176,15 @@ operator<<(NdbOut& ndbout, const AttributeS& attr){
NdbOut&
operator<<(NdbOut& ndbout, const TupleS& tuple)
{
- ndbout << tuple.getTable()->getTableName() << "; ";
for (int i = 0; i < tuple.getNoOfAttributes(); i++)
{
+ if (i > 0)
+ ndbout << g_ndbrecord_print_format.fields_terminated_by;
AttributeData * attr_data = tuple.getData(i);
const AttributeDesc * attr_desc = tuple.getDesc(i);
const AttributeS attr = {attr_desc, *attr_data};
debug << i << " " << attr_desc->m_column->getName();
ndbout << attr;
-
- if (i != (tuple.getNoOfAttributes() - 1))
- ndbout << delimiter << " ";
} // for
return ndbout;
}
diff --git a/storage/ndb/tools/restore/Restore.hpp b/storage/ndb/tools/restore/Restore.hpp
index 74834fe0abc..406899b2b4d 100644
--- a/storage/ndb/tools/restore/Restore.hpp
+++ b/storage/ndb/tools/restore/Restore.hpp
@@ -25,8 +25,6 @@
#include <ndb_version.h>
#include <version.h>
-#define delimiter ";"
-
const int FileNameLenC = 256;
const int TableNameLenC = 256;
const int AttrNameLenC = 256;
@@ -142,6 +140,8 @@ class TableS {
Uint64 m_max_auto_val;
bool isSysTable;
+ TableS *m_main_table;
+ Uint32 m_local_id;
Uint64 m_noOfRecords;
Vector<FragmentInfo *> m_fragmentInfo;
@@ -156,6 +156,9 @@ public:
Uint32 getTableId() const {
return m_dictTable->getTableId();
}
+ Uint32 getLocalId() const {
+ return m_local_id;
+ }
Uint32 getNoOfRecords() const {
return m_noOfRecords;
}
@@ -239,6 +242,10 @@ public:
return isSysTable;
}
+ const TableS *getMainTable() const {
+ return m_main_table;
+ }
+
TableS& operator=(TableS& org) ;
}; // TableS;
diff --git a/storage/ndb/tools/restore/consumer_printer.cpp b/storage/ndb/tools/restore/consumer_printer.cpp
index dabd77f7358..721e0332381 100644
--- a/storage/ndb/tools/restore/consumer_printer.cpp
+++ b/storage/ndb/tools/restore/consumer_printer.cpp
@@ -14,6 +14,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "consumer_printer.hpp"
+extern FilteredNdbOut info;
+extern NdbRecordPrintFormat g_ndbrecord_print_format;
+extern const char *tab_path;
bool
BackupPrinter::table(const TableS & tab)
@@ -21,7 +24,8 @@ BackupPrinter::table(const TableS & tab)
if (m_print || m_print_meta)
{
m_ndbout << tab;
- ndbout_c("Successfully printed table: %s", tab.m_dictTable->getName());
+ info.setLevel(254);
+ info << "Successfully printed table: ", tab.m_dictTable->getName();
}
return true;
}
@@ -31,7 +35,14 @@ BackupPrinter::tuple(const TupleS & tup, Uint32 fragId)
{
m_dataCount++;
if (m_print || m_print_data)
- m_ndbout << tup << endl;
+ {
+ if (m_ndbout.m_out == info.m_out)
+ {
+ info.setLevel(254);
+ info << tup.getTable()->getTableName() << "; ";
+ }
+ m_ndbout << tup << g_ndbrecord_print_format.lines_terminated_by;
+ }
}
void
@@ -47,9 +58,10 @@ BackupPrinter::endOfLogEntrys()
{
if (m_print || m_print_log)
{
- ndbout << "Printed " << m_dataCount << " tuples and "
- << m_logCount << " log entries"
- << " to stdout." << endl;
+ info.setLevel(254);
+ info << "Printed " << m_dataCount << " tuples and "
+ << m_logCount << " log entries"
+ << " to stdout." << endl;
}
}
bool
diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp
index 2ea79a2aa6c..e8f9842e554 100644
--- a/storage/ndb/tools/restore/consumer_restore.cpp
+++ b/storage/ndb/tools/restore/consumer_restore.cpp
@@ -619,6 +619,7 @@ BackupRestore::update_apply_status(const RestoreMetaData &metaData)
return true;
bool result= false;
+ unsigned apply_table_format= 0;
m_ndb->setDatabaseName(NDB_REP_DB);
m_ndb->setSchemaName("def");
@@ -631,8 +632,33 @@ BackupRestore::update_apply_status(const RestoreMetaData &metaData)
<< dict->getNdbError() << endl;
return false;
}
+ if
+ (ndbtab->getColumn(0)->getType() == NdbDictionary::Column::Unsigned &&
+ ndbtab->getColumn(1)->getType() == NdbDictionary::Column::Bigunsigned)
+ {
+ if (ndbtab->getNoOfColumns() == 2)
+ {
+ apply_table_format= 1;
+ }
+ else if
+ (ndbtab->getColumn(2)->getType() == NdbDictionary::Column::Varchar &&
+ ndbtab->getColumn(3)->getType() == NdbDictionary::Column::Bigunsigned &&
+ ndbtab->getColumn(4)->getType() == NdbDictionary::Column::Bigunsigned)
+ {
+ apply_table_format= 2;
+ }
+ }
+ if (apply_table_format == 0)
+ {
+ err << Ndb_apply_table << " has wrong format\n";
+ return false;
+ }
+
Uint32 server_id= 0;
Uint64 epoch= metaData.getStopGCP();
+ Uint64 zero= 0;
+ char empty_string[1];
+ empty_string[0]= 0;
NdbTransaction * trans= m_ndb->startTransaction();
if (!trans)
{
@@ -655,6 +681,15 @@ BackupRestore::update_apply_status(const RestoreMetaData &metaData)
<< op->getNdbError() << endl;
goto err;
}
+ if ((apply_table_format == 2) &&
+ (op->setValue(2u, (const char *)&empty_string, 1) ||
+ op->setValue(3u, (const char *)&zero, sizeof(zero)) ||
+ op->setValue(4u, (const char *)&zero, sizeof(zero))))
+ {
+ err << Ndb_apply_table << ": "
+ << op->getNdbError() << endl;
+ goto err;
+ }
if (trans->execute(NdbTransaction::Commit))
{
err << Ndb_apply_table << ": "
diff --git a/storage/ndb/tools/restore/restore_main.cpp b/storage/ndb/tools/restore/restore_main.cpp
index ee3af467aa7..8353f049647 100644
--- a/storage/ndb/tools/restore/restore_main.cpp
+++ b/storage/ndb/tools/restore/restore_main.cpp
@@ -20,6 +20,7 @@
#include <NdbTCP.h>
#include <NdbMem.h>
#include <NdbOut.hpp>
+#include <OutputStream.hpp>
#include <NDBT_ReturnCodes.h>
#include "consumer_restore.hpp"
@@ -34,14 +35,24 @@ static int ga_nParallelism = 128;
static int ga_backupId = 0;
static bool ga_dont_ignore_systab_0 = false;
static Vector<class BackupConsumer *> g_consumers;
+static BackupPrinter* g_printer = NULL;
-static const char* ga_backupPath = "." DIR_SEPARATOR;
+static const char* default_backupPath = "." DIR_SEPARATOR;
+static const char* ga_backupPath = default_backupPath;
static const char *opt_nodegroup_map_str= 0;
static unsigned opt_nodegroup_map_len= 0;
static NODE_GROUP_MAP opt_nodegroup_map[MAX_NODE_GROUP_MAPS];
#define OPT_NDB_NODEGROUP_MAP 'z'
+const char *opt_ndb_database= NULL;
+const char *opt_ndb_table= NULL;
+unsigned int opt_verbose;
+unsigned int opt_hex_format;
+Vector<BaseString> g_databases;
+Vector<BaseString> g_tables;
+NdbRecordPrintFormat g_ndbrecord_print_format;
+
NDB_STD_OPTS_VARS;
/**
@@ -62,6 +73,28 @@ BaseString g_options("ndb_restore");
const char *load_default_groups[]= { "mysql_cluster","ndb_restore",0 };
+enum ndb_restore_options {
+ OPT_PRINT= NDB_STD_OPTIONS_LAST,
+ OPT_PRINT_DATA,
+ OPT_PRINT_LOG,
+ OPT_PRINT_META,
+ OPT_BACKUP_PATH,
+ OPT_HEX_FORMAT,
+ OPT_FIELDS_ENCLOSED_BY,
+ OPT_FIELDS_TERMINATED_BY,
+ OPT_FIELDS_OPTIONALLY_ENCLOSED_BY,
+ OPT_LINES_TERMINATED_BY,
+ OPT_APPEND,
+ OPT_VERBOSE
+};
+static const char *opt_fields_enclosed_by= NULL;
+static const char *opt_fields_terminated_by= NULL;
+static const char *opt_fields_optionally_enclosed_by= NULL;
+static const char *opt_lines_terminated_by= NULL;
+
+static const char *tab_path= NULL;
+static int opt_append;
+
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_restore"),
@@ -100,19 +133,19 @@ static struct my_option my_long_options[] =
"(parallelism can be 1 to 1024)",
(gptr*) &ga_nParallelism, (gptr*) &ga_nParallelism, 0,
GET_INT, REQUIRED_ARG, 128, 1, 1024, 0, 1, 0 },
- { "print", 256, "Print data and log to stdout",
+ { "print", OPT_PRINT, "Print data and log to stdout",
(gptr*) &_print, (gptr*) &_print, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
- { "print_data", 257, "Print data to stdout",
+ { "print_data", OPT_PRINT_DATA, "Print data to stdout",
(gptr*) &_print_data, (gptr*) &_print_data, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
- { "print_meta", 258, "Print meta data to stdout",
+ { "print_meta", OPT_PRINT_META, "Print meta data to stdout",
(gptr*) &_print_meta, (gptr*) &_print_meta, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
- { "print_log", 259, "Print log to stdout",
+ { "print_log", OPT_PRINT_LOG, "Print log to stdout",
(gptr*) &_print_log, (gptr*) &_print_log, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
- { "backup_path", 260, "Path to backup files",
+ { "backup_path", OPT_BACKUP_PATH, "Path to backup files",
(gptr*) &ga_backupPath, (gptr*) &ga_backupPath, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ "dont_ignore_systab_0", 'f',
@@ -125,6 +158,37 @@ static struct my_option my_long_options[] =
(gptr*) &opt_nodegroup_map_str,
0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "fields-enclosed-by", OPT_FIELDS_ENCLOSED_BY,
+ "Fields are enclosed by ...",
+ (gptr*) &opt_fields_enclosed_by, (gptr*) &opt_fields_enclosed_by, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "fields-terminated-by", OPT_FIELDS_TERMINATED_BY,
+ "Fields are terminated by ...",
+ (gptr*) &opt_fields_terminated_by,
+ (gptr*) &opt_fields_terminated_by, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "fields-optionally-enclosed-by", OPT_FIELDS_OPTIONALLY_ENCLOSED_BY,
+ "Fields are optionally enclosed by ...",
+ (gptr*) &opt_fields_optionally_enclosed_by,
+ (gptr*) &opt_fields_optionally_enclosed_by, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "hex", OPT_HEX_FORMAT, "print binary types in hex format",
+ (gptr*) &opt_hex_format, (gptr*) &opt_hex_format, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "tab", 'T', "Creates tab separated textfile for each table to "
+ "given path. (creates .txt files)",
+ (gptr*) &tab_path, (gptr*) &tab_path, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ { "append", OPT_APPEND, "for --tab append data to file",
+ (gptr*) &opt_append, (gptr*) &opt_append, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "lines-terminated-by", OPT_LINES_TERMINATED_BY, "",
+ (gptr*) &opt_lines_terminated_by, (gptr*) &opt_lines_terminated_by, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "verbose", OPT_VERBOSE,
+ "verbosity",
+ (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0,
+ GET_INT, REQUIRED_ARG, 1, 0, 255, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -259,20 +323,25 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
#endif
ndb_std_get_one_option(optid, opt, argument);
switch (optid) {
+ case OPT_VERBOSE:
+ info.setThreshold(255-opt_verbose);
+ break;
case 'n':
if (ga_nodeId == 0)
{
- printf("Error in --nodeid,-n setting, see --help\n");
+ err << "Error in --nodeid,-n setting, see --help";
exit(NDBT_ProgramExit(NDBT_WRONGARGS));
}
+ info.setLevel(254);
info << "Nodeid = " << ga_nodeId << endl;
break;
case 'b':
if (ga_backupId == 0)
{
- printf("Error in --backupid,-b setting, see --help\n");
+ err << "Error in --backupid,-b setting, see --help";
exit(NDBT_ProgramExit(NDBT_WRONGARGS));
}
+ info.setLevel(254);
info << "Backup Id = " << ga_backupId << endl;
break;
case OPT_NDB_NODEGROUP_MAP:
@@ -281,6 +350,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
to nodegroup in new cluster.
*/
opt_nodegroup_map_len= 0;
+
+ info.setLevel(254);
info << "Analyse node group map" << endl;
if (analyse_nodegroup_map(opt_nodegroup_map_str,
&opt_nodegroup_map[0]))
@@ -335,9 +406,9 @@ o verify nodegroup mapping
exit(NDBT_ProgramExit(NDBT_WRONGARGS));
#endif
- BackupPrinter* printer = new BackupPrinter(opt_nodegroup_map,
- opt_nodegroup_map_len);
- if (printer == NULL)
+ g_printer = new BackupPrinter(opt_nodegroup_map,
+ opt_nodegroup_map_len);
+ if (g_printer == NULL)
return false;
BackupRestore* restore = new BackupRestore(opt_nodegroup_map,
@@ -345,7 +416,8 @@ o verify nodegroup mapping
ga_nParallelism);
if (restore == NULL)
{
- delete printer;
+ delete g_printer;
+ g_printer = NULL;
return false;
}
@@ -353,22 +425,22 @@ o verify nodegroup mapping
{
ga_print = true;
ga_restore = true;
- printer->m_print = true;
+ g_printer->m_print = true;
}
if (_print_meta)
{
ga_print = true;
- printer->m_print_meta = true;
+ g_printer->m_print_meta = true;
}
if (_print_data)
{
ga_print = true;
- printer->m_print_data = true;
+ g_printer->m_print_data = true;
}
if (_print_log)
{
ga_print = true;
- printer->m_print_log = true;
+ g_printer->m_print_log = true;
}
if (_restore_data)
@@ -394,19 +466,64 @@ o verify nodegroup mapping
}
{
- BackupConsumer * c = printer;
+ BackupConsumer * c = g_printer;
g_consumers.push_back(c);
}
{
BackupConsumer * c = restore;
g_consumers.push_back(c);
}
- // Set backup file path
- if (*pargv[0] != NULL)
+ for (;;)
{
- ga_backupPath = *pargv[0];
+ int i= 0;
+ if (ga_backupPath == default_backupPath)
+ {
+ // Set backup file path
+ if ((*pargv)[i] == NULL)
+ break;
+ ga_backupPath = (*pargv)[i++];
+ }
+ if ((*pargv)[i] == NULL)
+ break;
+ g_databases.push_back((*pargv)[i++]);
+ while ((*pargv)[i] != NULL)
+ {
+ g_tables.push_back((*pargv)[i++]);
+ }
+ break;
}
+ info.setLevel(254);
info << "backup path = " << ga_backupPath << endl;
+ if (g_databases.size() > 0)
+ {
+ info << "Restoring only from database " << g_databases[0].c_str() << endl;
+ if (g_tables.size() > 0)
+ info << "Restoring only tables:";
+ for (unsigned i= 0; i < g_tables.size(); i++)
+ {
+ info << " " << g_tables[i].c_str();
+ }
+ if (g_tables.size() > 0)
+ info << endl;
+ }
+ /*
+ the below formatting follows the formatting from mysqldump
+ do not change unless to adopt to changes in mysqldump
+ */
+ g_ndbrecord_print_format.fields_enclosed_by=
+ opt_fields_enclosed_by ? opt_fields_enclosed_by : "";
+ g_ndbrecord_print_format.fields_terminated_by=
+ opt_fields_terminated_by ? opt_fields_terminated_by : "\t";
+ g_ndbrecord_print_format.fields_optionally_enclosed_by=
+ opt_fields_optionally_enclosed_by ? opt_fields_optionally_enclosed_by : "";
+ g_ndbrecord_print_format.lines_terminated_by=
+ opt_lines_terminated_by ? opt_lines_terminated_by : "\n";
+ if (g_ndbrecord_print_format.fields_optionally_enclosed_by[0] == '\0')
+ g_ndbrecord_print_format.null_string= "\\N";
+ else
+ g_ndbrecord_print_format.null_string= "";
+ g_ndbrecord_print_format.hex_prefix= "";
+ g_ndbrecord_print_format.hex_format= opt_hex_format;
return true;
}
@@ -431,6 +548,70 @@ checkSysTable(const RestoreMetaData& metaData, uint i)
return checkSysTable(metaData[i]);
}
+static inline bool
+isBlobTable(const TableS* table)
+{
+ return table->getMainTable() != NULL;
+}
+
+static inline bool
+isIndex(const TableS* table)
+{
+ const NdbTableImpl & tmptab = NdbTableImpl::getImpl(* table->m_dictTable);
+ return (int) tmptab.m_indexType != (int) NdbDictionary::Index::Undefined;
+}
+
+static inline bool
+checkDbAndTableName(const TableS* table)
+{
+ if (g_tables.size() == 0 &&
+ g_databases.size() == 0)
+ return true;
+ if (g_databases.size() == 0)
+ g_databases.push_back("TEST_DB");
+
+ // Filter on the main table name for indexes and blobs
+ const char *table_name;
+ if (isBlobTable(table))
+ table_name= table->getMainTable()->getTableName();
+ else if (isIndex(table))
+ table_name=
+ NdbTableImpl::getImpl(*table->m_dictTable).m_primaryTable.c_str();
+ else
+ table_name= table->getTableName();
+
+ unsigned i;
+ for (i= 0; i < g_databases.size(); i++)
+ {
+ if (strncmp(table_name, g_databases[i].c_str(),
+ g_databases[i].length()) == 0 &&
+ table_name[g_databases[i].length()] == '/')
+ {
+ // we have a match
+ if (g_databases.size() > 1 || g_tables.size() == 0)
+ return true;
+ break;
+ }
+ }
+ if (i == g_databases.size())
+ return false; // no match found
+
+ while (*table_name != '/') table_name++;
+ table_name++;
+ while (*table_name != '/') table_name++;
+ table_name++;
+
+ for (i= 0; i < g_tables.size(); i++)
+ {
+ if (strcmp(table_name, g_tables[i].c_str()) == 0)
+ {
+ // we have a match
+ return true;
+ }
+ }
+ return false;
+}
+
static void
free_data_callback()
{
@@ -490,9 +671,10 @@ main(int argc, char** argv)
const Uint32 version = tmp.NdbVersion;
char buf[NDB_VERSION_STRING_BUF_SZ];
+ info.setLevel(254);
info << "Ndb version in backup files: "
- << getVersionString(version, 0, buf, sizeof(buf)) << endl;
-
+ << getVersionString(version, 0, buf, sizeof(buf)) << endl;
+
/**
* check wheater we can restore the backup (right version).
*/
@@ -560,27 +742,59 @@ main(int argc, char** argv)
exitHandler(NDBT_FAILED);
}
}
- debug << "Restoring tables" << endl;
+
+ Vector<OutputStream *> table_output(metaData.getNoOfTables());
+ debug << "Restoring tables" << endl;
for(i = 0; i<metaData.getNoOfTables(); i++)
{
- if (checkSysTable(metaData, i))
+ const TableS *table= metaData[i];
+ table_output.push_back(NULL);
+ if (!checkDbAndTableName(table))
+ continue;
+ if (checkSysTable(table))
{
+ if (!tab_path || isBlobTable(table) || isIndex(table))
+ {
+ table_output[i]= ndbout.m_out;
+ }
+ else
+ {
+ FILE* res;
+ char filename[FN_REFLEN], tmp_path[FN_REFLEN];
+ const char *table_name;
+ table_name= table->getTableName();
+ while (*table_name != '/') table_name++;
+ table_name++;
+ while (*table_name != '/') table_name++;
+ table_name++;
+ convert_dirname(tmp_path, tab_path, NullS);
+ res= my_fopen(fn_format(filename, table_name, tmp_path, ".txt", 4),
+ opt_append ?
+ O_WRONLY|O_APPEND|O_CREAT :
+ O_WRONLY|O_TRUNC|O_CREAT,
+ MYF(MY_WME));
+ if (res == 0)
+ {
+ exitHandler(NDBT_FAILED);
+ }
+ FileOutputStream *f= new FileOutputStream(res);
+ table_output[i]= f;
+ }
for(Uint32 j= 0; j < g_consumers.size(); j++)
- if (!g_consumers[j]->table(* metaData[i]))
+ if (!g_consumers[j]->table(* table))
{
err << "Restore: Failed to restore table: ";
- err << metaData[i]->getTableName() << " ... Exiting " << endl;
+ err << table->getTableName() << " ... Exiting " << endl;
exitHandler(NDBT_FAILED);
}
} else {
for(Uint32 j= 0; j < g_consumers.size(); j++)
- if (!g_consumers[j]->createSystable(* metaData[i]))
+ if (!g_consumers[j]->createSystable(* table))
{
err << "Restore: Failed to restore system table: ";
- err << metaData[i]->getTableName() << " ... Exiting " << endl;
+ err << table->getTableName() << " ... Exiting " << endl;
exitHandler(NDBT_FAILED);
}
-
}
}
debug << "Close tables" << endl;
@@ -624,9 +838,15 @@ main(int argc, char** argv)
const TupleS* tuple;
while ((tuple = dataIter.getNextTuple(res= 1)) != 0)
{
- if (checkSysTable(tuple->getTable()))
- for(Uint32 j= 0; j < g_consumers.size(); j++)
- g_consumers[j]->tuple(* tuple, fragmentId);
+ const TableS* table = tuple->getTable();
+ OutputStream *output = table_output[table->getLocalId()];
+ if (!output)
+ continue;
+ OutputStream *tmp = ndbout.m_out;
+ ndbout.m_out = output;
+ for(Uint32 j= 0; j < g_consumers.size(); j++)
+ g_consumers[j]->tuple(* tuple, fragmentId);
+ ndbout.m_out = tmp;
} // while (tuple != NULL);
if (res < 0)
@@ -668,9 +888,12 @@ main(int argc, char** argv)
const LogEntry * logEntry = 0;
while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0)
{
- if (checkSysTable(logEntry->m_table))
- for(Uint32 j= 0; j < g_consumers.size(); j++)
- g_consumers[j]->logEntry(* logEntry);
+ const TableS* table = logEntry->m_table;
+ OutputStream *output = table_output[table->getLocalId()];
+ if (!output)
+ continue;
+ for(Uint32 j= 0; j < g_consumers.size(); j++)
+ g_consumers[j]->logEntry(* logEntry);
}
if (res < 0)
{
@@ -687,27 +910,27 @@ main(int argc, char** argv)
{
for(i = 0; i<metaData.getNoOfTables(); i++)
{
- if (checkSysTable(metaData, i))
- {
- for(Uint32 j= 0; j < g_consumers.size(); j++)
- if (!g_consumers[j]->finalize_table(* metaData[i]))
- {
- err << "Restore: Failed to finalize restore table: %s. ";
- err << "Exiting... " << metaData[i]->getTableName() << endl;
- exitHandler(NDBT_FAILED);
- }
- }
+ const TableS* table = metaData[i];
+ OutputStream *output = table_output[table->getLocalId()];
+ if (!output)
+ continue;
+ for(Uint32 j= 0; j < g_consumers.size(); j++)
+ if (!g_consumers[j]->finalize_table(*table))
+ {
+ err << "Restore: Failed to finalize restore table: %s. ";
+ err << "Exiting... " << metaData[i]->getTableName() << endl;
+ exitHandler(NDBT_FAILED);
+ }
}
}
}
-
if (ga_restore_epoch)
{
for (i= 0; i < g_consumers.size(); i++)
if (!g_consumers[i]->update_apply_status(metaData))
{
- err << "Restore: Failed to restore epoch" << endl;
- return -1;
+ err << "Restore: Failed to restore epoch" << endl;
+ return -1;
}
}
@@ -722,7 +945,23 @@ main(int argc, char** argv)
}
clearConsumers();
- return NDBT_ProgramExit(NDBT_OK);
+
+ for(i = 0; i < metaData.getNoOfTables(); i++)
+ {
+ if (table_output[i] &&
+ table_output[i] != ndbout.m_out)
+ {
+ my_fclose(((FileOutputStream *)table_output[i])->getFile(), MYF(MY_WME));
+ delete table_output[i];
+ table_output[i] = NULL;
+ }
+ }
+
+ if (opt_verbose)
+ return NDBT_ProgramExit(NDBT_OK);
+ else
+ return 0;
} // main
template class Vector<BackupConsumer*>;
+template class Vector<OutputStream*>;