#At file:///home/zhl/mysql/wl4397/
3072 Leonard Zhou 2008-12-15
WL#4397 Backup at start time
added:
mysql-test/std_data/ndb_backup51_undolog_be/
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1-0.1.Data
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1-0.2.Data
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.1.ctl
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.1.log
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.2.ctl
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.2.log
mysql-test/std_data/ndb_backup51_undolog_le/
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1-0.1.Data
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1-0.2.Data
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.1.ctl
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.1.log
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.2.ctl
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.2.log
mysql-test/suite/ndb/r/ndb_restore_undolog.result
mysql-test/suite/ndb/t/ndb_restore_undolog.test
modified:
mysql-test/Makefile.am
storage/ndb/include/kernel/signaldata/BackupImpl.hpp
storage/ndb/include/kernel/signaldata/BackupSignalData.hpp
storage/ndb/include/mgmapi/mgmapi.h
storage/ndb/src/kernel/blocks/ERROR_codes.txt
storage/ndb/src/kernel/blocks/backup/Backup.cpp
storage/ndb/src/kernel/blocks/backup/Backup.txt
storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp
storage/ndb/src/mgmapi/mgmapi.cpp
storage/ndb/src/mgmclient/CommandInterpreter.cpp
storage/ndb/src/mgmsrv/MgmtSrvr.cpp
storage/ndb/src/mgmsrv/MgmtSrvr.hpp
storage/ndb/src/mgmsrv/Services.cpp
storage/ndb/test/include/NdbBackup.hpp
storage/ndb/test/ndbapi/testBackup.cpp
storage/ndb/test/src/NdbBackup.cpp
storage/ndb/tools/restore/Restore.cpp
storage/ndb/tools/restore/Restore.hpp
per-file messages:
mysql-test/Makefile.am
Add backup files for undo log test
mysql-test/std_data/ndb_backup51_undolog_be
Backup files
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1-0.1.Data
Backup files
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1-0.2.Data
Backup files
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.1.ctl
Backup files
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.1.log
Backup files
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.2.ctl
Backup files
mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.2.log
Backup files
mysql-test/std_data/ndb_backup51_undolog_le
Backup files
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1-0.1.Data
Backup files
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1-0.2.Data
Backup files
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.1.ctl
Backup files
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.1.log
Backup files
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.2.ctl
Backup files
mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.2.log
Backup files
mysql-test/suite/ndb/r/ndb_restore_undolog.result
Test result of backup/restore undo log
mysql-test/suite/ndb/t/ndb_restore_undolog.test
Test case of backup/restore undo log
storage/ndb/include/kernel/signaldata/BackupImpl.hpp
Add comment for the bits of flags
storage/ndb/include/kernel/signaldata/BackupSignalData.hpp
Add comment for the bits of flags
storage/ndb/include/mgmapi/mgmapi.h
Add new function to implement backup undo log
storage/ndb/src/kernel/blocks/ERROR_codes.txt
Add new error code comment
storage/ndb/src/kernel/blocks/backup/Backup.cpp
Implement backup undo log.
storage/ndb/src/kernel/blocks/backup/Backup.txt
Change description
storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp
Add new file type
storage/ndb/src/mgmapi/mgmapi.cpp
Add new api function
storage/ndb/src/mgmclient/CommandInterpreter.cpp
Explain the user command.
storage/ndb/src/mgmsrv/MgmtSrvr.cpp
Add log type into the signal
storage/ndb/src/mgmsrv/MgmtSrvr.hpp
Extend the function's parameters
storage/ndb/src/mgmsrv/Services.cpp
Implement backup undo log
storage/ndb/test/include/NdbBackup.hpp
Modify the parameter of start backup function
storage/ndb/test/ndbapi/testBackup.cpp
Api test case for backup undo log
storage/ndb/test/src/NdbBackup.cpp
New function to get the status of backup
storage/ndb/tools/restore/Restore.cpp
Restore undo log file
storage/ndb/tools/restore/Restore.hpp
Add flag for undo log
=== modified file 'mysql-test/Makefile.am'
--- a/mysql-test/Makefile.am 2008-09-02 16:31:03 +0000
+++ b/mysql-test/Makefile.am 2008-12-15 12:34:21 +0000
@@ -47,6 +47,8 @@ dist-hook:
$(distdir)/std_data/ndb_backup51_data_le \
$(distdir)/std_data/ndb_backup51_d2_be \
$(distdir)/std_data/ndb_backup51_d2_le \
+ $(distdir)/std_data/ndb_backup51_undolog_be \
+ $(distdir)/std_data/ndb_backup51_undolog_le \
$(distdir)/std_data/ndb_backup_packed \
$(distdir)/std_data/parts \
$(distdir)/lib \
@@ -83,6 +85,8 @@ dist-hook:
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_data_le/BACKUP* $(distdir)/std_data/ndb_backup51_data_le
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_d2_be/BACKUP* $(distdir)/std_data/ndb_backup51_d2_be
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_d2_le/BACKUP* $(distdir)/std_data/ndb_backup51_d2_le
+ $(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_undolog_be/BACKUP* $(distdir)/std_data/ndb_backup51_undolog_be
+ $(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_undolog_le/BACKUP* $(distdir)/std_data/ndb_backup51_undolog_le
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup_packed/BACKUP* $(distdir)/std_data/ndb_backup_packed
$(INSTALL_DATA) $(srcdir)/std_data/parts/part_* $(distdir)/std_data/parts
$(INSTALL_DATA) $(srcdir)/std_data/parts/*.MY* $(distdir)/std_data/parts
@@ -106,6 +110,8 @@ install-data-local:
$(DESTDIR)$(testdir)/std_data/ndb_backup51_data_le \
$(DESTDIR)$(testdir)/std_data/ndb_backup51_d2_be \
$(DESTDIR)$(testdir)/std_data/ndb_backup51_d2_le \
+ $(DESTDIR)$(testdir)/std_data/ndb_backup51_undolog_be \
+ $(DESTDIR)$(testdir)/std_data/ndb_backup51_undolog_le \
$(DESTDIR)$(testdir)/std_data/ndb_backup_packed \
$(DESTDIR)$(testdir)/std_data/parts \
$(DESTDIR)$(testdir)/lib \
@@ -147,6 +153,8 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_data_le/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup51_data_le
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_d2_be/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup51_d2_be
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_d2_le/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup51_d2_le
+ $(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_undolog_be/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup51_undolog_be
+ $(INSTALL_DATA) $(srcdir)/std_data/ndb_backup51_undolog_le/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup51_undolog_le
$(INSTALL_DATA) $(srcdir)/std_data/ndb_backup_packed/BACKUP* $(DESTDIR)$(testdir)/std_data/ndb_backup_packed
$(INSTALL_DATA) $(srcdir)/std_data/parts/part_* $(DESTDIR)$(testdir)/std_data/parts
$(INSTALL_DATA) $(srcdir)/std_data/parts/*.MY* $(DESTDIR)$(testdir)/std_data/parts
=== added directory 'mysql-test/std_data/ndb_backup51_undolog_be'
=== added file 'mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1-0.1.Data'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1-0.1.Data 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1-0.1.Data 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1-0.2.Data'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1-0.2.Data 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1-0.2.Data 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.1.ctl'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.1.ctl 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.1.ctl 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.1.log'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.1.log 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.1.log 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.2.ctl'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.2.ctl 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.2.ctl 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.2.log'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.2.log 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_be/BACKUP-1.2.log 2008-12-15 12:34:21 +0000 differ
=== added directory 'mysql-test/std_data/ndb_backup51_undolog_le'
=== added file 'mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1-0.1.Data'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1-0.1.Data 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1-0.1.Data 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1-0.2.Data'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1-0.2.Data 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1-0.2.Data 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.1.ctl'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.1.ctl 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.1.ctl 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.1.log'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.1.log 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.1.log 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.2.ctl'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.2.ctl 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.2.ctl 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.2.log'
Binary files a/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.2.log 1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/ndb_backup51_undolog_le/BACKUP-1.2.log 2008-12-15 12:34:21 +0000 differ
=== added file 'mysql-test/suite/ndb/r/ndb_restore_undolog.result'
--- a/mysql-test/suite/ndb/r/ndb_restore_undolog.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_restore_undolog.result 2008-12-15 12:34:21 +0000
@@ -0,0 +1,325 @@
+USE test;
+DROP TABLE IF EXISTS t_num,t_datetime,t_string_1,t_string_2,t_gis,t_string_3,t_string_4,t_string_5;
+SHOW TABLES;
+Tables_in_test
+t_datetime
+t_gis
+t_num
+t_string_1
+t_string_2
+t_string_3
+t_string_4
+t_string_5
+SHOW CREATE TABLE t_num;
+Table Create Table
+t_num CREATE TABLE `t_num` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_bit` bit(64) DEFAULT NULL,
+ `t_tinyint` tinyint(4) DEFAULT NULL,
+ `t_bool` tinyint(1) DEFAULT NULL,
+ `t_smallint` smallint(6) DEFAULT NULL,
+ `t_mediumint` mediumint(9) DEFAULT NULL,
+ `t_int` int(11) DEFAULT NULL,
+ `t_bigint` bigint(20) DEFAULT NULL,
+ `t_float` float DEFAULT NULL,
+ `t_double` double DEFAULT NULL,
+ `t_decimal` decimal(37,16) DEFAULT NULL,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_datetime;
+Table Create Table
+t_datetime CREATE TABLE `t_datetime` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_date` date DEFAULT NULL,
+ `t_datetime` datetime DEFAULT NULL,
+ `t_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `t_time` time DEFAULT NULL,
+ `t_year` year(4) DEFAULT NULL,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_string_1;
+Table Create Table
+t_string_1 CREATE TABLE `t_string_1` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_char` char(255) DEFAULT NULL,
+ `t_varchar` varchar(655) DEFAULT NULL,
+ `t_binary` binary(255) DEFAULT NULL,
+ `t_varbinary` varbinary(6553) DEFAULT NULL,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_string_2;
+Table Create Table
+t_string_2 CREATE TABLE `t_string_2` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_tinyblob` tinyblob,
+ `t_tinytext` tinytext,
+ `t_blob` blob,
+ `t_text` text,
+ `t_mediumblob` mediumblob,
+ `t_mediumtext` mediumtext,
+ `t_longblob` longblob,
+ `t_longtext` longtext,
+ `t_enum` enum('001001','001004','001010','001018','001019','001020','001021','001027','001028','001029','001030','001031','001100','002003','002004','002005','002007') NOT NULL DEFAULT '001001',
+ `t_set` set('a','B') DEFAULT NULL,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_gis;
+Table Create Table
+t_gis CREATE TABLE `t_gis` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_point` point DEFAULT NULL,
+ `t_linestring` linestring DEFAULT NULL,
+ `t_polygon` polygon DEFAULT NULL,
+ `t_multipoint` multipoint DEFAULT NULL,
+ `t_multilinestring` multilinestring DEFAULT NULL,
+ `t_multipolygon` multipolygon DEFAULT NULL,
+ `t_geometrycollection` geometrycollection DEFAULT NULL,
+ `t_geometry` geometry DEFAULT NULL,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_string_3;
+Table Create Table
+t_string_3 CREATE TABLE `t_string_3` (
+ `t_pk` int(11) NOT NULL,
+ `t_longblob` longblob,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_string_4;
+Table Create Table
+t_string_4 CREATE TABLE `t_string_4` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_name` char(30) DEFAULT NULL,
+ `t_blob` blob,
+ `t_text` text,
+ PRIMARY KEY (`t_pk`),
+ KEY `t_pk` (`t_pk`,`t_name`)
+) /*!50100 TABLESPACE ts1 STORAGE DISK */ ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_string_5;
+Table Create Table
+t_string_5 CREATE TABLE `t_string_5` (
+ `t_pk` int(11) NOT NULL,
+ `t_longblob` longblob,
+ `t_longtext` longtext,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SELECT * FROM t_datetime ORDER by t_pk;
+t_pk t_test t_date t_datetime t_timestamp t_time t_year
+1 1 1998-01-01 2006-08-10 10:11:12 2002-10-29 16:51:06 19:38:34 2155
+2 1 1998-01-01 2006-08-10 10:11:12 2002-10-29 16:51:06 19:38:34 2155
+SELECT t_pk,t_test,hex(t_bit),t_tinyint,t_bool,t_smallint,t_mediumint,t_int,t_bigint,t_float,t_double,t_decimal FROM t_num ORDER by t_pk;
+t_pk t_test hex(t_bit) t_tinyint t_bool t_smallint t_mediumint t_int t_bigint t_float t_double t_decimal
+1 1 AAAAAAAAAAAAAAAA 125 1 32765 8388606 2147483647 9223372036854775807 1e+20 1e+150 331.0000000000000000
+2 1 AAAAAAAAAAAAAAAA 125 1 32765 8388606 2147483647 9223372036854775807 1e+20 1e+150 331.0000000000000000
+SELECT t_pk,t_test,t_char,t_varchar,hex(t_binary),hex(t_varbinary) FROM t_string_1 ORDER by t_pk;
+t_pk t_test t_char t_varchar hex(t_binary) hex(t_varbinary)
+1 1 abcdefghijklmn abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn 612020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 4100
+2 1 abcdefghijklmn abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn 612020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 4100
+SELECT * FROM t_string_2 ORDER by t_pk;
+t_pk t_test t_tinyblob t_tinytext t_blob t_text t_mediumblob t_mediumtext t_longblob t_longtext t_enum t_set
+1 1 abcdefghijklmnabcdefghijklmn abcdefghijklmnabcdefghijklmn a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 001001 a
+2 1 abcdefghijklmnabcdefghijklmn abcdefghijklmnabcdefghijklmn a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 001001 a
+SELECT t_pk,t_test,AsText(t_point), AsText(t_linestring),AsText(t_polygon) FROM t_gis ORDER by t_pk;
+t_pk t_test AsText(t_point) AsText(t_linestring) AsText(t_polygon)
+1 1 POINT(10 10) LINESTRING(10 10,20 10,20 20,10 20,10 10) POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10))
+2 1 POINT(10 20) LINESTRING(10 10,40 10) POLYGON((0 0,30 0,30 30,0 0))
+3 1 POINT(10 10) LINESTRING(10 10,20 10,20 20,10 20,10 10) POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10))
+4 1 POINT(10 20) LINESTRING(10 10,40 10) POLYGON((0 0,30 0,30 30,0 0))
+SELECT t_pk,t_test,AsText(t_multipoint), AsText(t_multilinestring),AsText(t_multipolygon) FROM t_gis ORDER by t_pk;
+t_pk t_test AsText(t_multipoint) AsText(t_multilinestring) AsText(t_multipolygon)
+1 1 MULTIPOINT(1 1,11 11,11 21,21 21) MULTILINESTRING((10 48,10 21,10 0)) MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+2 1 MULTIPOINT(3 6,4 10) MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
+3 1 MULTIPOINT(1 1,11 11,11 21,21 21) MULTILINESTRING((10 48,10 21,10 0)) MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+4 1 MULTIPOINT(3 6,4 10) MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
+SELECT t_pk,t_test,AsText(t_geometrycollection), AsText(t_geometry) FROM t_gis ORDER by t_pk;
+t_pk t_test AsText(t_geometrycollection) AsText(t_geometry)
+1 1 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+2 1 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
+3 1 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+4 1 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
+SELECT COUNT(*) FROM t_string_3 ORDER BY t_pk;
+COUNT(*)
+5000
+SELECT * FROM t_string_4 ORDER BY t_pk;
+t_pk t_test t_name t_blob t_text
+1 1 name1 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789
+2 1 name2 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789
+SELECT t_pk,LENGTH(t_longblob),LENGTH(t_longtext) FROM t_string_5 ORDER BY t_pk;
+t_pk LENGTH(t_longblob) LENGTH(t_longtext)
+1 131072 131072
+2 131072 131072
+DROP TABLE IF EXISTS t_num,t_datetime,t_string_1,t_string_2,t_gis,t_string_3,t_string_4,t_string_5;
+ALTER TABLESPACE ts1
+DROP DATAFILE 'datafile.dat'
+ENGINE = NDB;
+DROP TABLESPACE ts1
+ENGINE = NDB;
+DROP LOGFILE GROUP lg1
+ENGINE =NDB;
+USE test;
+SHOW TABLES;
+Tables_in_test
+t_datetime
+t_gis
+t_num
+t_string_1
+t_string_2
+t_string_3
+t_string_4
+t_string_5
+SHOW CREATE TABLE t_num;
+Table Create Table
+t_num CREATE TABLE `t_num` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_bit` bit(64) DEFAULT NULL,
+ `t_tinyint` tinyint(4) DEFAULT NULL,
+ `t_bool` tinyint(1) DEFAULT NULL,
+ `t_smallint` smallint(6) DEFAULT NULL,
+ `t_mediumint` mediumint(9) DEFAULT NULL,
+ `t_int` int(11) DEFAULT NULL,
+ `t_bigint` bigint(20) DEFAULT NULL,
+ `t_float` float DEFAULT NULL,
+ `t_double` double DEFAULT NULL,
+ `t_decimal` decimal(37,16) DEFAULT NULL,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_datetime;
+Table Create Table
+t_datetime CREATE TABLE `t_datetime` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_date` date DEFAULT NULL,
+ `t_datetime` datetime DEFAULT NULL,
+ `t_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `t_time` time DEFAULT NULL,
+ `t_year` year(4) DEFAULT NULL,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_string_1;
+Table Create Table
+t_string_1 CREATE TABLE `t_string_1` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_char` char(255) DEFAULT NULL,
+ `t_varchar` varchar(655) DEFAULT NULL,
+ `t_binary` binary(255) DEFAULT NULL,
+ `t_varbinary` varbinary(6553) DEFAULT NULL,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_string_2;
+Table Create Table
+t_string_2 CREATE TABLE `t_string_2` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_tinyblob` tinyblob,
+ `t_tinytext` tinytext,
+ `t_blob` blob,
+ `t_text` text,
+ `t_mediumblob` mediumblob,
+ `t_mediumtext` mediumtext,
+ `t_longblob` longblob,
+ `t_longtext` longtext,
+ `t_enum` enum('001001','001004','001010','001018','001019','001020','001021','001027','001028','001029','001030','001031','001100','002003','002004','002005','002007') NOT NULL DEFAULT '001001',
+ `t_set` set('a','B') DEFAULT NULL,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_gis;
+Table Create Table
+t_gis CREATE TABLE `t_gis` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_point` point DEFAULT NULL,
+ `t_linestring` linestring DEFAULT NULL,
+ `t_polygon` polygon DEFAULT NULL,
+ `t_multipoint` multipoint DEFAULT NULL,
+ `t_multilinestring` multilinestring DEFAULT NULL,
+ `t_multipolygon` multipolygon DEFAULT NULL,
+ `t_geometrycollection` geometrycollection DEFAULT NULL,
+ `t_geometry` geometry DEFAULT NULL,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_string_3;
+Table Create Table
+t_string_3 CREATE TABLE `t_string_3` (
+ `t_pk` int(11) NOT NULL,
+ `t_longblob` longblob,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_string_4;
+Table Create Table
+t_string_4 CREATE TABLE `t_string_4` (
+ `t_pk` int(11) NOT NULL,
+ `t_test` int(11) DEFAULT NULL,
+ `t_name` char(30) DEFAULT NULL,
+ `t_blob` blob,
+ `t_text` text,
+ PRIMARY KEY (`t_pk`),
+ KEY `t_pk` (`t_pk`,`t_name`)
+) /*!50100 TABLESPACE ts1 STORAGE DISK */ ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SHOW CREATE TABLE t_string_5;
+Table Create Table
+t_string_5 CREATE TABLE `t_string_5` (
+ `t_pk` int(11) NOT NULL,
+ `t_longblob` longblob,
+ `t_longtext` longtext,
+ PRIMARY KEY (`t_pk`)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1
+SELECT * FROM t_datetime ORDER by t_pk;
+t_pk t_test t_date t_datetime t_timestamp t_time t_year
+1 1 1998-01-01 2006-08-10 10:11:12 2002-10-29 16:51:06 19:38:34 2155
+2 1 1998-01-01 2006-08-10 10:11:12 2002-10-29 16:51:06 19:38:34 2155
+SELECT t_pk,t_test,hex(t_bit),t_tinyint,t_bool,t_smallint,t_mediumint,t_int,t_bigint,t_float,t_double,t_decimal FROM t_num ORDER by t_pk;
+t_pk t_test hex(t_bit) t_tinyint t_bool t_smallint t_mediumint t_int t_bigint t_float t_double t_decimal
+1 1 AAAAAAAAAAAAAAAA 125 1 32765 8388606 2147483647 9223372036854775807 1e+20 1e+150 331.0000000000000000
+2 1 AAAAAAAAAAAAAAAA 125 1 32765 8388606 2147483647 9223372036854775807 1e+20 1e+150 331.0000000000000000
+SELECT t_pk,t_test,t_char,t_varchar,hex(t_binary),hex(t_varbinary) FROM t_string_1 ORDER by t_pk;
+t_pk t_test t_char t_varchar hex(t_binary) hex(t_varbinary)
+1 1 abcdefghijklmn abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn 612020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 4100
+2 1 abcdefghijklmn abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn 612020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 4100
+SELECT * FROM t_string_2 ORDER by t_pk;
+t_pk t_test t_tinyblob t_tinytext t_blob t_text t_mediumblob t_mediumtext t_longblob t_longtext t_enum t_set
+1 1 abcdefghijklmnabcdefghijklmn abcdefghijklmnabcdefghijklmn a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 001001 a
+2 1 abcdefghijklmnabcdefghijklmn abcdefghijklmnabcdefghijklmn a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 001001 a
+SELECT t_pk,t_test,AsText(t_point), AsText(t_linestring),AsText(t_polygon) FROM t_gis ORDER by t_pk;
+t_pk t_test AsText(t_point) AsText(t_linestring) AsText(t_polygon)
+1 1 POINT(10 10) LINESTRING(10 10,20 10,20 20,10 20,10 10) POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10))
+2 1 POINT(10 20) LINESTRING(10 10,40 10) POLYGON((0 0,30 0,30 30,0 0))
+3 1 POINT(10 10) LINESTRING(10 10,20 10,20 20,10 20,10 10) POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10))
+4 1 POINT(10 20) LINESTRING(10 10,40 10) POLYGON((0 0,30 0,30 30,0 0))
+SELECT t_pk,t_test,AsText(t_multipoint), AsText(t_multilinestring),AsText(t_multipolygon) FROM t_gis ORDER by t_pk;
+t_pk t_test AsText(t_multipoint) AsText(t_multilinestring) AsText(t_multipolygon)
+1 1 MULTIPOINT(1 1,11 11,11 21,21 21) MULTILINESTRING((10 48,10 21,10 0)) MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+2 1 MULTIPOINT(3 6,4 10) MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
+3 1 MULTIPOINT(1 1,11 11,11 21,21 21) MULTILINESTRING((10 48,10 21,10 0)) MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+4 1 MULTIPOINT(3 6,4 10) MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
+SELECT t_pk,t_test,AsText(t_geometrycollection), AsText(t_geometry) FROM t_gis ORDER by t_pk;
+t_pk t_test AsText(t_geometrycollection) AsText(t_geometry)
+1 1 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+2 1 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
+3 1 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
+4 1 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
+SELECT COUNT(*) FROM t_string_3 ORDER BY t_pk;
+COUNT(*)
+5000
+SELECT * FROM t_string_4 ORDER BY t_pk;
+t_pk t_test t_name t_blob t_text
+1 1 name1 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789
+2 1 name2 a123456789b123456789c123456789d123456789e123456789f123456789g123456789 a123456789b123456789c123456789d123456789e123456789f123456789g123456789
+SELECT t_pk,LENGTH(t_longblob),LENGTH(t_longtext) FROM t_string_5 ORDER BY t_pk;
+t_pk LENGTH(t_longblob) LENGTH(t_longtext)
+1 131072 131072
+2 131072 131072
+DROP TABLE IF EXISTS t_num,t_datetime,t_string_1,t_string_2,t_gis,t_string_3,t_string_4,t_string_5;
+ALTER TABLESPACE ts1
+DROP DATAFILE 'datafile.dat'
+ENGINE = NDB;
+DROP TABLESPACE ts1
+ENGINE = NDB;
+DROP LOGFILE GROUP lg1
+ENGINE =NDB;
=== added file 'mysql-test/suite/ndb/t/ndb_restore_undolog.test'
--- a/mysql-test/suite/ndb/t/ndb_restore_undolog.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_restore_undolog.test 2008-12-15 12:34:21 +0000
@@ -0,0 +1,514 @@
+-- source include/have_ndb.inc
+-- source include/ndb_default_cluster.inc
+
+#
+# The table structure and data list below
+#
+##############################################
+##### for basic test with all data type #####
+##############################################
+# CREATE TABLE t_num (
+# t_pk INT PRIMARY KEY,
+# t_test INT,
+# t_bit BIT(64),
+# t_tinyint TINYINT,
+# t_bool BOOL,
+# t_smallint SMALLINT,
+# t_mediumint MEDIUMINT,
+# t_int INT,
+# t_bigint BIGINT,
+# t_float FLOAT,
+# t_double DOUBLE,
+# t_decimal DECIMAL (37, 16)
+# ) ENGINE=NDBCLUSTER;
+#
+# INSERT INTO t_num VALUE (
+# 1,
+# 1,
+# b'1010101010101010101010101010101010101010101010101010101010101010',
+# 125,
+# 1,
+# 32765,
+# 8388606,
+# 2147483647,
+# 9223372036854775807,
+# 1e+20,
+# 1e+150,
+# '331.0000000000'
+# );
+# INSERT INTO t_num VALUE (
+# 2,
+# 1,
+# b'1010101010101010101010101010101010101010101010101010101010101010',
+# 125,
+# 1,
+# 32765,
+# 8388606,
+# 2147483647,
+# 9223372036854775807,
+# 1e+20,
+# 1e+150,
+# '331.0000000000'
+# );
+# CREATE TABLE t_datetime (
+# t_pk INT PRIMARY KEY,
+# t_test INT,
+# t_date DATE,
+# t_datetime DATETIME,
+# t_timestamp TIMESTAMP,
+# t_time TIME,
+# t_year YEAR
+# ) ENGINE=NDBCLUSTER;
+#
+# INSERT INTO t_datetime VALUE (
+# 1,
+# 1,
+# '1998-01-01',
+# '2006-08-10 10:11:12',
+# 20021029165106,
+# '19:38:34',
+# 2155
+# );
+# INSERT INTO t_datetime VALUE (
+# 2,
+# 1,
+# '1998-01-01',
+# '2006-08-10 10:11:12',
+# 20021029165106,
+# '19:38:34',
+# 2155
+# );
+#
+# CREATE TABLE t_string_1 (
+# t_pk INT PRIMARY KEY,
+# t_test INT,
+# t_char CHAR(255),
+# t_varchar VARCHAR(655),
+# t_binary BINARY(255),
+# t_varbinary VARBINARY(6553)
+# ) ENGINE=NDBCLUSTER;
+#
+# CREATE TABLE t_string_2 (
+# t_pk INT PRIMARY KEY,
+# t_test INT,
+# t_tinyblob TINYBLOB,
+# t_tinytext TINYTEXT,
+# t_blob BLOB,
+# t_text TEXT,
+# t_mediumblob MEDIUMBLOB,
+# t_mediumtext MEDIUMTEXT,
+# t_longblob LONGBLOB,
+# t_longtext LONGTEXT,
+# t_enum ENUM('001001','001004','001010','001018','001019','001020','001021','001027','001028','001029','001030','001031','001100','002003','002004','002005','002007')DEFAULT '001001' NOT NULL,
+# t_set SET('a','B')
+# ) ENGINE=NDBCLUSTER;
+#
+# INSERT INTO t_string_1 VALUE (
+# 1,
+# 1,
+# 'abcdefghijklmn',
+# 'abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn',
+# 0x612020,
+# 0x4100
+# );
+# INSERT INTO t_string_1 VALUE (
+# 2,
+# 1,
+# 'abcdefghijklmn',
+# 'abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn',
+# 0x612020,
+# 0x4100
+# );
+#
+# INSERT INTO t_string_2 VALUE (
+# 1,
+# 1,
+# 'abcdefghijklmnabcdefghijklmn',
+# 'abcdefghijklmnabcdefghijklmn',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# '001001',
+# 'a'
+# );
+#
+# INSERT INTO t_string_2 VALUE (
+# 2,
+# 1,
+# 'abcdefghijklmnabcdefghijklmn',
+# 'abcdefghijklmnabcdefghijklmn',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# '001001',
+# 'a'
+# );
+#
+# CREATE TABLE t_gis (
+# t_pk INT PRIMARY KEY,
+# t_test INT,
+# t_point POINT,
+# t_linestring LINESTRING,
+# t_polygon POLYGON,
+# t_multipoint MULTIPOINT,
+# t_multilinestring MULTILINESTRING,
+# t_multipolygon MULTIPOLYGON,
+# t_geometrycollection GEOMETRYCOLLECTION,
+# t_geometry GEOMETRY
+# ) ENGINE=NDBCLUSTER;
+#
+# INSERT INTO t_gis VALUE (
+# 1,
+# 1,
+# PointFromText('POINT(10 10)'),
+# LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)'),
+# PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))'),
+# MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)'),
+# MLineFromText('MULTILINESTRING((10 48,10 21,10 0))'),
+# MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))'),
+# GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))'),
+# MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')
+# );
+#
+# INSERT INTO t_gis VALUE (
+# 3,
+# 1,
+# PointFromText('POINT(10 10)'),
+# LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)'),
+# PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))'),
+# MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)'),
+# MLineFromText('MULTILINESTRING((10 48,10 21,10 0))'),
+# MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))'),
+# GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))'),
+# MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')
+# );
+#
+# INSERT INTO t_gis VALUE (
+# 2,
+# 1,
+# PointFromWKB(AsWKB(PointFromText('POINT(10 20)'))),
+# LineStringFromWKB(LineString(Point(10, 10), Point(40, 10))),
+# PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)))),
+# MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10))),
+# MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7)))),
+# MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3))))),
+# GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))),
+# GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))
+# );
+#
+# INSERT INTO t_gis VALUE (
+# 4,
+# 1,
+# PointFromWKB(AsWKB(PointFromText('POINT(10 20)'))),
+# LineStringFromWKB(LineString(Point(10, 10), Point(40, 10))),
+# PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)))),
+# MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10))),
+# MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7)))),
+# MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3))))),
+# GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))),
+# GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))
+# );
+#
+#
+#######################################
+###### for multi entries #############
+#######################################
+# CREATE TABLE t_string_3 (
+# t_pk INT NOT NULL PRIMARY KEY,
+# t_longblob LONGBLOB
+# ) ENGINE=NDB;
+#
+#delimiter |;
+#
+# CREATE PROCEDURE test_proc1()
+# BEGIN
+# DECLARE tmp INT DEFAULT 5000;
+# WHILE tmp > 1 DO
+# INSERT INTO t_string_3 VALUES (
+# tmp,
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789');
+# SET tmp = tmp -1;
+# END WHILE;
+# END;
+#
+# delimiter ;|
+#
+# INSERT INTO t_string_3 VALUE (
+# 1,
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789');
+#
+# call test_proc1();
+#
+##########################################
+##### for disk data and order index #####
+##########################################
+# CREATE LOGFILE GROUP lg1
+# ADD UNDOFILE 'undofile.dat'
+# INITIAL_SIZE 16M
+# UNDO_BUFFER_SIZE = 1M
+# ENGINE=NDB;
+#
+# CREATE TABLESPACE ts1
+# ADD DATAFILE 'datafile.dat'
+# USE LOGFILE GROUP lg1
+# INITIAL_SIZE 12M
+# ENGINE NDB;
+#
+# CREATE TABLE t_string_4 (
+# t_pk INT NOT NULL PRIMARY KEY,
+# t_test INT,
+# t_name CHAR(30),
+# t_blob BLOB,
+# t_text TEXT,
+# INDEX (t_pk,t_name)
+# )
+# TABLESPACE ts1 STORAGE DISK
+# ENGINE=NDB;
+#
+# INSERT INTO t_string_4 VALUE (
+# 1,
+# 1,
+# 'name1',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789');
+# INSERT INTO t_string_4 VALUE (
+# 2,
+# 1,
+# 'name2',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789');
+#
+##########################################
+############## for long blob ############
+##########################################
+#
+# CREATE TABLE t_string_5 (
+# t_pk INT NOT NULL PRIMARY KEY,
+# t_longblob LONGBLOB,
+# t_longtext LONGTEXT
+# ) ENGINE=NDB;
+#
+##### b1 length 128k ######
+#
+# set @b1 = '01234567012345670123456701234567';
+# set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
+# set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
+# set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
+# set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
+#
+# INSERT INTO t_string_5 VALUES(1,@b1,@b1);
+# INSERT INTO t_string_5 VALUES(2,@b1,@b1);
+#
+#######################################
+### Operations during backup ####
+#######################################
+#
+######## for basic test with all data type ########
+#
+# DELETE FROM t_num WHERE t_pk=2;
+# DELETE FROM t_datetime WHERE t_pk=2;
+# DELETE FROM t_string_1 WHERE t_pk=2;
+# DELETE FROM t_string_2 WHERE t_pk=2;
+# DELETE FROM t_gis WHERE t_pk=3;
+# DELETE FROM t_gis WHERE t_pk=4;
+#
+#
+# INSERT INTO t_num VALUE (
+# 2,
+# 2,
+# b'1010101010101010101010101010101010101010101010101010101010101010',
+# 125,
+# 1,
+# 32765,
+# 8388606,
+# 2147483647,
+# 9223372036854775807,
+# 1e+20,
+# 1e+150,
+# '331.0000000000'
+# );
+# INSERT INTO t_datetime VALUE (
+# 2,
+# 2,
+# '1998-01-01',
+# '2006-08-10 10:11:12',
+# 20021029165106,
+# '19:38:34',
+# 2155
+# );
+#
+# INSERT INTO t_string_1 VALUE (
+# 2,
+# 2,
+# 'abcdefghijklmn',
+# 'abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn',
+# 0x612020,
+# 0x4100
+# );
+#
+# INSERT INTO t_string_2 VALUE (
+# 2,
+# 2,
+# 'abcdefghijklmnabcdefghijklmn',
+# 'abcdefghijklmnabcdefghijklmn',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# '001001',
+# 'a'
+# );
+#
+#
+# INSERT INTO t_gis VALUE (
+# 3,
+# 2,
+# PointFromText('POINT(10 10)'),
+# LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)'),
+# PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))'),
+# MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)'),
+# MLineFromText('MULTILINESTRING((10 48,10 21,10 0))'),
+# MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))'),
+# GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))'),
+# MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')
+# );
+#
+#
+# INSERT INTO t_gis VALUE (
+# 4,
+# 2,
+# PointFromWKB(AsWKB(PointFromText('POINT(10 20)'))),
+# LineStringFromWKB(LineString(Point(10, 10), Point(40, 10))),
+# PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)))),
+# MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10))),
+# MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7)))),
+# MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3))))),
+# GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))),
+# GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))
+# );
+#
+#
+# UPDATE t_num SET t_test=3 WHERE t_pk=1;
+# UPDATE t_datetime SET t_test=3 WHERE t_pk=1;
+# UPDATE t_string_1 SET t_test=3 WHERE t_pk=1;
+# UPDATE t_string_2 SET t_test=3 WHERE t_pk=1;
+# UPDATE t_gis SET t_test=3 WHERE t_pk=1;
+# UPDATE t_gis SET t_test=3 WHERE t_pk=2;
+#
+#
+######### multi undo log entries ########
+#
+# DELETE FROM t_string_3 WHERE t_pk>1;
+#
+######### disk table and ordered index ########
+#
+# DELETE FROM t_string_4 WHERE t_pk=2;
+# INSERT INTO t_string_4 VALUE (
+# 2,
+# 2,
+# 'name2',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789',
+# 'a123456789b123456789c123456789d123456789e123456789f123456789g123456789'
+# );
+# UPDATE t_string_4 SET t_test=3 WHERE t_pk=1;
+#
+######## long blob ########
+#
+# DELETE FROM t_string_5 WHERE t_pk>1;
+#
+#
+#
+#
+#
+#
+######################################################
+##### Restore backup files (from little endian) ######
+######################################################
+
+--disable_warnings
+USE test;
+DROP TABLE IF EXISTS t_num,t_datetime,t_string_1,t_string_2,t_gis,t_string_3,t_string_4,t_string_5;
+--enable_warnings
+--exec $NDB_RESTORE --no-defaults -b 1 -n 1 -m -r $MYSQL_TEST_DIR/std_data/ndb_backup51_undolog_le >> $NDB_TOOLS_OUTPUT
+--exec $NDB_RESTORE --no-defaults -b 1 -n 2 -r $MYSQL_TEST_DIR/std_data/ndb_backup51_undolog_le >> $NDB_TOOLS_OUTPUT
+--sorted_result
+SHOW TABLES;
+SHOW CREATE TABLE t_num;
+SHOW CREATE TABLE t_datetime;
+SHOW CREATE TABLE t_string_1;
+SHOW CREATE TABLE t_string_2;
+SHOW CREATE TABLE t_gis;
+SHOW CREATE TABLE t_string_3;
+SHOW CREATE TABLE t_string_4;
+SHOW CREATE TABLE t_string_5;
+SELECT * FROM t_datetime ORDER by t_pk;
+SELECT t_pk,t_test,hex(t_bit),t_tinyint,t_bool,t_smallint,t_mediumint,t_int,t_bigint,t_float,t_double,t_decimal FROM t_num ORDER by t_pk;
+SELECT t_pk,t_test,t_char,t_varchar,hex(t_binary),hex(t_varbinary) FROM t_string_1 ORDER by t_pk;
+SELECT * FROM t_string_2 ORDER by t_pk;
+SELECT t_pk,t_test,AsText(t_point), AsText(t_linestring),AsText(t_polygon) FROM t_gis ORDER by t_pk;
+SELECT t_pk,t_test,AsText(t_multipoint), AsText(t_multilinestring),AsText(t_multipolygon) FROM t_gis ORDER by t_pk;
+SELECT t_pk,t_test,AsText(t_geometrycollection), AsText(t_geometry) FROM t_gis ORDER by t_pk;
+SELECT COUNT(*) FROM t_string_3 ORDER BY t_pk;
+SELECT * FROM t_string_4 ORDER BY t_pk;
+SELECT t_pk,LENGTH(t_longblob),LENGTH(t_longtext) FROM t_string_5 ORDER BY t_pk;
+
+DROP TABLE IF EXISTS t_num,t_datetime,t_string_1,t_string_2,t_gis,t_string_3,t_string_4,t_string_5;
+ALTER TABLESPACE ts1
+DROP DATAFILE 'datafile.dat'
+ENGINE = NDB;
+
+DROP TABLESPACE ts1
+ENGINE = NDB;
+
+DROP LOGFILE GROUP lg1
+ENGINE =NDB;
+
+
+#
+# Restore backup files (from big endian)
+#
+
+USE test;
+--exec $NDB_RESTORE --no-defaults -b 1 -n 1 -m -r $MYSQL_TEST_DIR/std_data/ndb_backup51_undolog_be >> $NDB_TOOLS_OUTPUT
+--exec $NDB_RESTORE --no-defaults -b 1 -n 2 -r $MYSQL_TEST_DIR/std_data/ndb_backup51_undolog_be >> $NDB_TOOLS_OUTPUT
+--sorted_result
+SHOW TABLES;
+SHOW CREATE TABLE t_num;
+SHOW CREATE TABLE t_datetime;
+SHOW CREATE TABLE t_string_1;
+SHOW CREATE TABLE t_string_2;
+SHOW CREATE TABLE t_gis;
+SHOW CREATE TABLE t_string_3;
+SHOW CREATE TABLE t_string_4;
+SHOW CREATE TABLE t_string_5;
+SELECT * FROM t_datetime ORDER by t_pk;
+SELECT t_pk,t_test,hex(t_bit),t_tinyint,t_bool,t_smallint,t_mediumint,t_int,t_bigint,t_float,t_double,t_decimal FROM t_num ORDER by t_pk;
+SELECT t_pk,t_test,t_char,t_varchar,hex(t_binary),hex(t_varbinary) FROM t_string_1 ORDER by t_pk;
+SELECT * FROM t_string_2 ORDER by t_pk;
+SELECT t_pk,t_test,AsText(t_point), AsText(t_linestring),AsText(t_polygon) FROM t_gis ORDER by t_pk;
+SELECT t_pk,t_test,AsText(t_multipoint), AsText(t_multilinestring),AsText(t_multipolygon) FROM t_gis ORDER by t_pk;
+SELECT t_pk,t_test,AsText(t_geometrycollection), AsText(t_geometry) FROM t_gis ORDER by t_pk;
+SELECT COUNT(*) FROM t_string_3 ORDER BY t_pk;
+SELECT * FROM t_string_4 ORDER BY t_pk;
+SELECT t_pk,LENGTH(t_longblob),LENGTH(t_longtext) FROM t_string_5 ORDER BY t_pk;
+
+DROP TABLE IF EXISTS t_num,t_datetime,t_string_1,t_string_2,t_gis,t_string_3,t_string_4,t_string_5;
+ALTER TABLESPACE ts1
+DROP DATAFILE 'datafile.dat'
+ENGINE = NDB;
+
+DROP TABLESPACE ts1
+ENGINE = NDB;
+
+DROP LOGFILE GROUP lg1
+ENGINE =NDB;
+
+## end of test ##
=== modified file 'storage/ndb/include/kernel/signaldata/BackupImpl.hpp'
--- a/storage/ndb/include/kernel/signaldata/BackupImpl.hpp 2008-03-03 11:12:37 +0000
+++ b/storage/ndb/include/kernel/signaldata/BackupImpl.hpp 2008-12-15 12:34:21 +0000
@@ -65,6 +65,7 @@ private:
* Backup flags
*/
/* & 0x3 - waitCompleted
+ * & 0x4 - Use undo log
*/
Uint32 flags;
};
=== modified file 'storage/ndb/include/kernel/signaldata/BackupSignalData.hpp'
--- a/storage/ndb/include/kernel/signaldata/BackupSignalData.hpp 2008-03-03 11:12:37 +0000
+++ b/storage/ndb/include/kernel/signaldata/BackupSignalData.hpp 2008-12-15 12:34:21 +0000
@@ -36,11 +36,14 @@ class BackupReq {
friend bool printBACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public:
STATIC_CONST( SignalLength = 4 );
+ STATIC_CONST( WAITCOMPLETED = 0x3 );
+ STATIC_CONST( USE_UNDO_LOG = 0x4 );
private:
Uint32 senderData;
Uint32 backupDataLen;
/* & 0x3 - waitCompleted
+ * & 0x4 - use undo log
*/
Uint32 flags;
Uint32 inputBackupId;
=== modified file 'storage/ndb/include/mgmapi/mgmapi.h'
--- a/storage/ndb/include/mgmapi/mgmapi.h 2008-10-05 07:13:39 +0000
+++ b/storage/ndb/include/mgmapi/mgmapi.h 2008-12-15 12:34:21 +0000
@@ -1045,6 +1045,27 @@ extern "C" {
unsigned int input_backupId);
/**
+ * Start backup
+ *
+ * @param handle NDB management handle.
+ * @param wait_completed 0: Don't wait for confirmation<br>
+ * 1: Wait for backup to be started<br>
+ * 2: Wait for backup to be completed
+ * @param backup_id Backup ID is returned from function.
+ * @param reply Reply message.
+ * @param input_backupId run as backupId and set next backup id to input_backupId+1.
+ * @param backuppoint Backup happen at start time(1) or complete time(0).
+ * @return -1 on error.
+ * @note backup_id will not be returned if
+ * wait_completed == 0
+ */
+ int ndb_mgm_start_backup3(NdbMgmHandle handle, int wait_completed,
+ unsigned int* backup_id,
+ struct ndb_mgm_reply* reply,
+ unsigned int input_backupId,
+ unsigned int backuppoint);
+
+ /**
* Abort backup
*
* @param handle NDB management handle.
=== modified file 'storage/ndb/src/kernel/blocks/ERROR_codes.txt'
--- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt 2008-10-29 09:15:35 +0000
+++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt 2008-12-15 12:34:21 +0000
@@ -8,7 +8,7 @@ Next DBDICT 6013
Next DBDIH 7215
Next DBTC 8064
Next CMVMI 9000
-Next BACKUP 10041
+Next BACKUP 10042
Next DBUTIL 11002
Next DBTUX 12008
Next SUMA 13043
@@ -486,6 +486,7 @@ Backup Stuff:
10039: Halt backup for table >= 2
10040: Resume backup (from 10039)
10038: Receive abort backup in the middle of locking tables.
+10041: delay backup after create trigger. for testing undo log file.
11001: Send UTIL_SEQUENCE_REF (in master)
=== modified file 'storage/ndb/src/kernel/blocks/backup/Backup.cpp'
--- a/storage/ndb/src/kernel/blocks/backup/Backup.cpp 2008-10-09 19:17:11 +0000
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.cpp 2008-12-15 12:34:21 +0000
@@ -1319,10 +1319,7 @@ Backup::execBACKUP_REQ(Signal* signal)
ptr.p->flags = flags;
ptr.p->masterRef = reference();
ptr.p->nodes = c_aliveNodes;
- if(input_backupId)
- ptr.p->backupId = input_backupId;
- else
- ptr.p->backupId = 0;
+ ptr.p->backupId = input_backupId;
ptr.p->backupKey[0] = 0;
ptr.p->backupKey[1] = 0;
ptr.p->backupDataLen = 0;
@@ -1627,27 +1624,8 @@ Backup::defineBackupReply(Signal* signal
return;
}
- /**
- * Reply to client
- */
CRASH_INSERTION((10034));
- if (SEND_BACKUP_STARTED_FLAG(ptr.p->flags))
- {
- BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
- conf->backupId = ptr.p->backupId;
- conf->senderData = ptr.p->clientData;
- conf->nodes = ptr.p->nodes;
- sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
- BackupConf::SignalLength, JBB);
- }
-
- signal->theData[0] = NDB_LE_BackupStarted;
- signal->theData[1] = ptr.p->clientRef;
- signal->theData[2] = ptr.p->backupId;
- ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+3);
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3+NdbNodeBitmask::Size, JBB);
-
/**
* We've received GSN_DEFINE_BACKUP_CONF from all participants.
*
@@ -1738,7 +1716,21 @@ Backup::sendCreateTrig(Signal* signal,
req->indexVersion = 0;
Uint32 ti = 0;
- TriggerInfo::setTriggerType(ti, TriggerType::SUBSCRIPTION);
+ /*
+ * We always send PK for any operations and any triggertypes.
+ * For SUBSCRIPTION_BEFORE
+ * We send after image for INSERT.
+ * We send before image for DELETE.
+ * We send before+after image for UPDATE.
+ * For SUBSCRIPTION
+ * We send after image for INSERT.
+ * We send only PK for DELETE.
+ * We send after image for UPDATE.
+ */
+ if(ptr.p->flags & BackupReq::USE_UNDO_LOG)
+ TriggerInfo::setTriggerType(ti, TriggerType::SUBSCRIPTION_BEFORE);
+ else
+ TriggerInfo::setTriggerType(ti, TriggerType::SUBSCRIPTION);
TriggerInfo::setTriggerActionTime(ti, TriggerActionTime::TA_DETACHED);
TriggerInfo::setMonitorReplicas(ti, true);
TriggerInfo::setMonitorAllAttributes(ti, false);
@@ -1958,6 +1950,25 @@ Backup::startBackupReply(Signal* signal,
return;
}
+ /*
+ * We reply to client after create trigger
+ */
+ if (SEND_BACKUP_STARTED_FLAG(ptr.p->flags))
+ {
+ BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
+ conf->backupId = ptr.p->backupId;
+ conf->senderData = ptr.p->clientData;
+ conf->nodes = ptr.p->nodes;
+ sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
+ BackupConf::SignalLength, JBB);
+ }
+
+ signal->theData[0] = NDB_LE_BackupStarted;
+ signal->theData[1] = ptr.p->clientRef;
+ signal->theData[2] = ptr.p->backupId;
+ ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+3);
+ sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3+NdbNodeBitmask::Size, JBB);
+
/**
* Wait for GCP
*/
@@ -1968,8 +1979,14 @@ Backup::startBackupReply(Signal* signal,
waitGCPReq->senderRef = reference();
waitGCPReq->senderData = ptr.i;
waitGCPReq->requestType = WaitGCPReq::CompleteForceStart;
- sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
- WaitGCPReq::SignalLength,JBB);
+ //we delay 10 seconds for testcases to generate events to be recorded in the UNDO log
+ if (ERROR_INSERTED(10041))
+ {
+ sendSignalWithDelay(DBDIH_REF, GSN_WAIT_GCP_REQ, signal, 10*1000, WaitGCPReq::SignalLength);
+ }
+ else
+ sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
+ WaitGCPReq::SignalLength,JBB);
}
void
@@ -2404,7 +2421,10 @@ Backup::sendDropTrig(Signal* signal, Bac
// TUP needs some triggerInfo to find right list
Uint32 ti = 0;
- TriggerInfo::setTriggerType(ti, TriggerType::SUBSCRIPTION);
+ if(ptr.p->flags & BackupReq::USE_UNDO_LOG)
+ TriggerInfo::setTriggerType(ti, TriggerType::SUBSCRIPTION_BEFORE);
+ else
+ TriggerInfo::setTriggerType(ti, TriggerType::SUBSCRIPTION);
TriggerInfo::setTriggerActionTime(ti, TriggerActionTime::TA_DETACHED);
TriggerInfo::setMonitorReplicas(ti, true);
TriggerInfo::setMonitorAllAttributes(ti, false);
@@ -2877,7 +2897,7 @@ Backup::execDEFINE_BACKUP_REQ(Signal* si
if(senderRef == reference())
ptr.p->flags = req->flags;
else
- ptr.p->flags = req->flags & ~((Uint32)0x3); /* remove waitCompleted flags
+ ptr.p->flags = req->flags & ~((Uint32)BackupReq::WAITCOMPLETED); /* remove waitCompleted flags
* as non master should never
* reply
*/
@@ -2987,7 +3007,10 @@ Backup::execDEFINE_BACKUP_REQ(Signal* si
ptr.p->ctlFilePtr = files[i].i;
break;
case 1:
- files[i].p->fileType = BackupFormat::LOG_FILE;
+ if(ptr.p->flags & BackupReq::USE_UNDO_LOG)
+ files[i].p->fileType = BackupFormat::UNDO_FILE;
+ else
+ files[i].p->fileType = BackupFormat::LOG_FILE;
ptr.p->logFilePtr = files[i].i;
break;
case 2:
@@ -3157,6 +3180,10 @@ Backup::openFiles(Signal* signal, Backup
c_backupFilePool.getPtr(filePtr, ptr.p->logFilePtr);
filePtr.p->m_flags |= BackupFile::BF_OPENING;
+ //write uncompressed log file when enable undo log,since log file is read from back to front.
+ if(ptr.p->flags & BackupReq::USE_UNDO_LOG)
+ req->fileFlags &= ~FsOpenReq::OM_GZ;
+
req->userPointer = filePtr.i;
FsOpenReq::setVersion(req->fileNumber, 2);
FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_LOG);
@@ -3172,6 +3199,8 @@ Backup::openFiles(Signal* signal, Backup
if (c_defaults.m_o_direct)
req->fileFlags |= FsOpenReq::OM_DIRECT;
+ if (c_defaults.m_compressed_backup)
+ req->fileFlags |= FsOpenReq::OM_GZ;
req->userPointer = filePtr.i;
FsOpenReq::setVersion(req->fileNumber, 2);
FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
@@ -3275,8 +3304,14 @@ Backup::openFilesReply(Signal* signal,
return;
}//if
+ BackupFormat::FileType logfiletype;
+ if(ptr.p->flags & BackupReq::USE_UNDO_LOG)
+ logfiletype = BackupFormat::UNDO_FILE;
+ else
+ logfiletype = BackupFormat::LOG_FILE;
+
ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
- if(!insertFileHeader(BackupFormat::LOG_FILE, ptr.p, filePtr.p)) {
+ if(!insertFileHeader(logfiletype, ptr.p, filePtr.p)) {
jam();
defineBackupRef(signal, ptr, DefineBackupRef::FailedInsertFileHeader);
return;
@@ -4709,13 +4744,27 @@ Backup::execTRIG_ATTRINFO(Signal* signal
return;
}//if
- if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES) {
- jam();
- /**
- * Backup is doing REDO logging and don't need before values
- */
- return;
- }//if
+ BackupRecordPtr ptr LINT_SET_PTR;
+ c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
+
+ if(ptr.p->flags & BackupReq::USE_UNDO_LOG) {
+ if(trg->getAttrInfoType() == TrigAttrInfo::AFTER_VALUES) {
+ jam();
+ /**
+ * Backup is doing UNDO logging and don't need after values
+ */
+ return;
+ }//if
+ }
+ else {
+ if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES) {
+ jam();
+ /**
+ * Backup is doing REDO logging and don't need before values
+ */
+ return;
+ }//if
+ }
BackupFormat::LogFile::LogEntry * logEntry = trigPtr.p->logEntry;
if(logEntry == 0)
@@ -4755,6 +4804,9 @@ Backup::execFIRE_TRIG_ORD(Signal* signal
ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID);
+ BackupRecordPtr ptr LINT_SET_PTR;
+ c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
+
if(trigPtr.p->errorCode != 0) {
jam();
SectionHandle handle(this, signal);
@@ -4778,21 +4830,47 @@ Backup::execFIRE_TRIG_ORD(Signal* signal
return;
}
- SegmentedSectionPtr ptr[3];
- handle.getSection(ptr[0], 0);
- handle.getSection(ptr[1], 1);
- handle.getSection(ptr[2], 2);
- trigPtr.p->logEntry = get_log_buffer(signal,
- trigPtr, ptr[0].sz + ptr[2].sz);
- if (unlikely(trigPtr.p->logEntry == 0))
- {
- jam();
- releaseSections(handle);
- return;
+ SegmentedSectionPtr dataPtr[3];
+ handle.getSection(dataPtr[0], 0);
+ handle.getSection(dataPtr[1], 1);
+ handle.getSection(dataPtr[2], 2);
+ /**
+ * dataPtr[0] : Primary key info
+ * dataPtr[1] : Before values
+ * dataPtr[2] : After values
+ */
+
+ /* Backup is doing UNDO logging and need before values
+ * Add 2 extra words to get_log_buffer for potential gci and logEntry length info stored at end.
+ */
+ if(ptr.p->flags & BackupReq::USE_UNDO_LOG) {
+ trigPtr.p->logEntry = get_log_buffer(signal,
+ trigPtr, dataPtr[0].sz + dataPtr[1].sz + 2);
+ if (unlikely(trigPtr.p->logEntry == 0))
+ {
+ jam();
+ releaseSections(handle);
+ return;
+ }
+ copy(trigPtr.p->logEntry->Data, dataPtr[0]);
+ copy(trigPtr.p->logEntry->Data+dataPtr[0].sz, dataPtr[1]);
+ trigPtr.p->logEntry->Length = dataPtr[0].sz + dataPtr[1].sz;
+ }
+ // Backup is doing REDO logging and need after values
+ else {
+ trigPtr.p->logEntry = get_log_buffer(signal,
+ trigPtr, dataPtr[0].sz + dataPtr[2].sz + 1);
+ if (unlikely(trigPtr.p->logEntry == 0))
+ {
+ jam();
+ releaseSections(handle);
+ return;
+ }
+ copy(trigPtr.p->logEntry->Data, dataPtr[0]);
+ copy(trigPtr.p->logEntry->Data+dataPtr[0].sz, dataPtr[2]);
+ trigPtr.p->logEntry->Length = dataPtr[0].sz + dataPtr[2].sz;
}
- copy(trigPtr.p->logEntry->Data, ptr[0]);
- copy(trigPtr.p->logEntry->Data+ptr[0].sz, ptr[2]);
- trigPtr.p->logEntry->Length = ptr[0].sz + ptr[2].sz;
+
releaseSections(handle);
}
@@ -4800,8 +4878,6 @@ Backup::execFIRE_TRIG_ORD(Signal* signal
Uint32 len = trigPtr.p->logEntry->Length;
trigPtr.p->logEntry->FragId = htonl(fragId);
- BackupRecordPtr ptr LINT_SET_PTR;
- c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
if(gci != ptr.p->currGCP)
{
jam();
@@ -4811,17 +4887,30 @@ Backup::execFIRE_TRIG_ORD(Signal* signal
ptr.p->currGCP = gci;
}
+ Uint32 datalen = len;
len += (sizeof(BackupFormat::LogFile::LogEntry) >> 2) - 2;
trigPtr.p->logEntry->Length = htonl(len);
- ndbrequire(len + 1 <= trigPtr.p->operation->dataBuffer.getMaxWrite());
- trigPtr.p->operation->dataBuffer.updateWritePtr(len + 1);
+ if(ptr.p->flags & BackupReq::USE_UNDO_LOG)
+ {
+ /* keep the length at both the end of logEntry and ->logEntry variable
+ The total length of logEntry is len + 2
+ */
+ trigPtr.p->logEntry->Data[datalen] = htonl(len);
+ }
+
+ Uint32 entryLength = len +1;
+ if(ptr.p->flags & BackupReq::USE_UNDO_LOG)
+ entryLength ++;
+
+ ndbrequire(entryLength <= trigPtr.p->operation->dataBuffer.getMaxWrite());
+ trigPtr.p->operation->dataBuffer.updateWritePtr(entryLength);
trigPtr.p->logEntry = 0;
{
- const Uint32 tmp = (len + 1) << 2;
- trigPtr.p->operation->noOfBytes += tmp;
- trigPtr.p->operation->m_bytes_total += tmp;
+ const Uint32 entryByteLength = entryLength << 2;
+ trigPtr.p->operation->noOfBytes += entryByteLength;
+ trigPtr.p->operation->m_bytes_total += entryByteLength;
trigPtr.p->operation->noOfRecords += 1;
trigPtr.p->operation->m_records_total += 1;
}
=== modified file 'storage/ndb/src/kernel/blocks/backup/Backup.txt'
--- a/storage/ndb/src/kernel/blocks/backup/Backup.txt 2006-01-20 04:42:00 +0000
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.txt 2008-12-15 12:34:21 +0000
@@ -23,14 +23,14 @@ BACKUP_REQ
--------------->
<---------------
<-------------------------------
-BACKUP_CONF
-<----------------
START_BACKUP
------------------------------>
CREATE_TRIG
-------------->
<--------------
<------------------------------
+BACKUP_CONF
+<----------------
WAIT_GCP
-------------->
<--------------
@@ -67,20 +67,20 @@ USER BACKUP-MASTER
3) Wait for conf
-4) <-- BACKUP_CONF
-
-5) For Each Table
+4) For Each Table
PREP_CREATE_TRIG_REQ
Wait for Conf
-6) To all slaves START_BACKUP_REQ
+5) To all slaves START_BACKUP_REQ
Include trigger ids
Wait for conf
-7) For Each Table
+6) For Each Table
CREATE_TRIG_REQ
Wait for conf
+7) <-- BACKUP_CONF *
+
8) Wait for GCP
9) For each table
@@ -97,6 +97,10 @@ USER BACKUP-MASTER
13) <-- BACKUP_COMPLETE_REP
+* The start is confired after the triggers are defined.
+ Once the signal is received by client,
+ any further changes will not be included in
+ a 'start backup snapshotstart' backup.
----
Slave: Master Died
=== modified file 'storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp'
--- a/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp 2008-03-18 07:12:39 +0000
+++ b/storage/ndb/src/kernel/blocks/backup/BackupFormat.hpp 2008-12-15 12:34:21 +0000
@@ -69,9 +69,10 @@ struct BackupFormat {
*/
enum FileType {
CTL_FILE = 1,
- LOG_FILE = 2,
+ LOG_FILE = 2, //redo log file for backup.
DATA_FILE = 3,
- LCP_FILE = 4
+ LCP_FILE = 4,
+ UNDO_FILE = 5 //undo log for backup.
};
/**
=== modified file 'storage/ndb/src/mgmapi/mgmapi.cpp'
--- a/storage/ndb/src/mgmapi/mgmapi.cpp 2008-11-05 07:57:18 +0000
+++ b/storage/ndb/src/mgmapi/mgmapi.cpp 2008-12-15 12:34:21 +0000
@@ -2128,10 +2128,11 @@ ndb_mgm_start(NdbMgmHandle handle, int n
*****************************************************************************/
extern "C"
int
-ndb_mgm_start_backup2(NdbMgmHandle handle, int wait_completed,
+ndb_mgm_start_backup3(NdbMgmHandle handle, int wait_completed,
unsigned int* _backup_id,
struct ndb_mgm_reply*, /*reply*/
- unsigned int input_backupId)
+ unsigned int input_backupId,
+ unsigned int backuppoint)
{
CHECK_HANDLE(handle, -1);
SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_start_backup");
@@ -2147,6 +2148,7 @@ ndb_mgm_start_backup2(NdbMgmHandle handl
args.put("completed", wait_completed);
if(input_backupId > 0)
args.put("backupid", input_backupId);
+ args.put("backuppoint", backuppoint);
const Properties *reply;
{ // start backup can take some time, set timeout high
int old_timeout= handle->timeout;
@@ -2174,12 +2176,21 @@ ndb_mgm_start_backup2(NdbMgmHandle handl
extern "C"
int
+ndb_mgm_start_backup2(NdbMgmHandle handle, int wait_completed,
+ unsigned int* _backup_id,
+ struct ndb_mgm_reply* reply,
+ unsigned int input_backupId)
+{
+ return ndb_mgm_start_backup3(handle, wait_completed, _backup_id, reply, input_backupId, 0);
+}
+
+extern "C"
+int
ndb_mgm_start_backup(NdbMgmHandle handle, int wait_completed,
unsigned int* _backup_id,
- struct ndb_mgm_reply* /*reply*/)
+ struct ndb_mgm_reply* reply)
{
- struct ndb_mgm_reply reply;
- return ndb_mgm_start_backup2(handle, wait_completed, _backup_id, &reply, 0);
+ return ndb_mgm_start_backup2(handle, wait_completed, _backup_id, reply, 0);
}
extern "C"
=== modified file 'storage/ndb/src/mgmclient/CommandInterpreter.cpp'
--- a/storage/ndb/src/mgmclient/CommandInterpreter.cpp 2008-10-29 09:15:35 +0000
+++ b/storage/ndb/src/mgmclient/CommandInterpreter.cpp 2008-12-15 12:34:21 +0000
@@ -272,7 +272,8 @@ static const char* helpText =
"DROP NODEGROUP <NG> Drop nodegroup with id NG\n"
"START BACKUP [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
"START BACKUP [<backup id>] [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
-" Start backup (default WAIT COMPLETED)\n"
+"START BACKUP [<backup id>] [SNAPSHOTSTART | SNAPSHOTEND] [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
+" Start backup (default WAIT COMPLETED,SNAPSHOTEND)\n"
"ABORT BACKUP <backup id> Abort backup\n"
"SHUTDOWN Shutdown all processes in cluster\n"
"CLUSTERLOG ON [<severity>] ... Enable Cluster logging\n"
@@ -336,7 +337,7 @@ static const char* helpTextStartBackup =
" NDB Cluster -- Management Client -- Help for START BACKUP command\n"
"---------------------------------------------------------------------------\n"
"START BACKUP Start a cluster backup\n\n"
-"START BACKUP [<backup id>] [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
+"START BACKUP [<backup id>] [SNAPSHOTSTART | SNAPSHOTEND] [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
" Start a backup for the cluster.\n"
" Each backup gets an ID number that is reported to the\n"
" user. This ID number can help you find the backup on the\n"
@@ -345,6 +346,10 @@ static const char* helpTextStartBackup =
" You can also start specified backup using START BACKUP <backup id> \n\n"
" <backup id> \n"
" Start a specified backup using <backup id> as bakcup ID number.\n"
+" SNAPSHOTSTART \n"
+" Backup snapshot is taken around the time the backup is started.\n"
+" SNAPSHOTEND \n"
+" Backup snapshot is taken around the time the backup is completed.\n"
" NOWAIT \n"
" Start a cluster backup and return immediately.\n"
" The management client will return control directly\n"
@@ -2909,51 +2914,96 @@ CommandInterpreter::executeStartBackup(c
int result;
int flags = 2;
- if (sz == 2 && args[1] == "NOWAIT")
- {
- flags = 0;
- }
- else if (sz == 1 || (sz == 3 && args[1] == "WAIT" && args[2] == "COMPLETED"))
- {
- flags = 2;
- ndbout_c("Waiting for completed, this may take several minutes");
- }
- else if (sz == 3 && args[1] == "WAIT" && args[2] == "STARTED")
- {
- ndbout_c("Waiting for started, this may take several minutes");
- flags = 1;
- }
- else if (sscanf(args[1].c_str(), "%u", &input_backupId) == 1 && input_backupId > 0 && input_backupId < MAX_BACKUPS)
+ //1,snapshot at start time. 0 snapshot at end time
+ unsigned int backuppoint = 0;
+ bool b_log = false;
+ bool b_nowait = false;
+ bool b_wait_completed = false;
+ bool b_wait_started = false;
+
+ /*
+ All the commands list as follow:
+ start backup <backupid> nowait | start backup <backupid> snapshotstart/snapshotend nowati | start backup <backupid> nowait snapshotstart/snapshotend
+ start backup <backupid> | start backup <backupid> wait completed | start backup <backupid> snapshotstart/snapshotend
+ start backup <backupid> snapshotstart/snapshotend wait completed | start backup <backupid> wait completed snapshotstart/snapshotend
+ start backup <backupid> wait started | start backup <backupid> snapshotstart/snapshotend wait started
+ start backup <backupid> wait started snapshotstart/snapshotend
+ */
+ for (int i= 1; i < sz; i++)
{
- // start backup n nowait
- if (sz == 3 && args[2] == "NOWAIT")
- {
- flags = 0;
+ if (i == 1 && sscanf(args[1].c_str(), "%u", &input_backupId) == 1) {
+ if (input_backupId > 0 && input_backupId < MAX_BACKUPS)
+ continue;
+ else {
+ invalid_command(parameters);
+ return -1;
+ }
}
- // start backup n; start backup n wait complete
- else if ( sz == 2 || (sz == 4 && args[2] == "WAIT" && args[3] =="COMPLETED"))
- {
- flags = 2;
- ndbout_c("Waiting for completed, this may take several minutes");
+
+ if (args[i] == "SNAPSHOTEND") {
+ if (b_log ==true) {
+ invalid_command(parameters);
+ return -1;
+ }
+ b_log = true;
+ backuppoint = 0;
+ continue;
}
- //start backup n wait started
- else if (sz == 4 && args[2] == "WAIT" && args[3] == "STARTED")
- {
- ndbout_c("Waiting for started, this may take several minutes");
- flags = 1;
+ if (args[i] == "SNAPSHOTSTART") {
+ if (b_log ==true) {
+ invalid_command(parameters);
+ return -1;
+ }
+ b_log = true;
+ backuppoint = 1;
+ continue;
}
- else
- {
- invalid_command(parameters);
- return -1;
+ if (args[i] == "NOWAIT") {
+ if (b_nowait == true || b_wait_completed == true || b_wait_started ==true) {
+ invalid_command(parameters);
+ return -1;
+ }
+ b_nowait == true;
+ flags = 0;
+ continue;
+ }
+ if (args[i] == "WAIT") {
+ if (b_nowait == true || b_wait_completed == true || b_wait_started ==true) {
+ invalid_command(parameters);
+ return -1;
+ }
+ if (i+1 < sz) {
+ if (args[i+1] == "COMPLETED") {
+ b_wait_completed == true;
+ flags = 2;
+ i++;
+ }
+ else if (args[i+1] == "STARTED") {
+ b_wait_started == true;
+ flags = 1;
+ i++;
+ }
+ else {
+ invalid_command(parameters);
+ return -1;
+ }
+ }
+ else {
+ invalid_command(parameters);
+ return -1;
+ }
+ continue;
}
- }
- else
- {
invalid_command(parameters);
return -1;
}
+ //print message
+ if (b_wait_completed)
+ ndbout_c("Waiting for completed, this may take several minutes");
+ if (b_wait_started)
+ ndbout_c("Waiting for started, this may take several minutes");
+
NdbLogEventHandle log_handle= NULL;
struct ndb_logevent log_event;
if (flags == 2 && !interactive)
@@ -2967,8 +3017,11 @@ CommandInterpreter::executeStartBackup(c
return -1;
}
}
- if (input_backupId > 0)
- result = ndb_mgm_start_backup2(m_mgmsrv, flags, &backupId, &reply, input_backupId);
+
+ //start backup N | start backup snapshotstart/snapshotend
+ if (input_backupId > 0 || b_log == true)
+ result = ndb_mgm_start_backup3(m_mgmsrv, flags, &backupId, &reply, input_backupId, backuppoint);
+ //start backup
else
result = ndb_mgm_start_backup(m_mgmsrv, flags, &backupId, &reply);
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2008-11-10 11:50:45 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2008-12-15 12:34:21 +0000
@@ -3083,7 +3083,7 @@ MgmtSrvr::eventReport(const Uint32 * the
***************************************************************************/
int
-MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted, Uint32 input_backupId)
+MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted, Uint32 input_backupId, Uint32 backuppoint)
{
SignalSender ss(theFacade);
ss.lock(); // lock will be released on exit
@@ -3120,6 +3120,8 @@ MgmtSrvr::startBackup(Uint32& backupId,
req->backupDataLen = 0;
assert(waitCompleted < 3);
req->flags = waitCompleted & 0x3;
+ if(backuppoint == 1)
+ req->flags |= BackupReq::USE_UNDO_LOG;
BackupEvent event;
int do_send = 1;
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2008-11-06 10:56:21 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2008-12-15 12:34:21 +0000
@@ -267,7 +267,7 @@ public:
/**
* Backup functionallity
*/
- int startBackup(Uint32& backupId, int waitCompleted= 2, Uint32 input_backupId= 0);
+ int startBackup(Uint32& backupId, int waitCompleted= 2, Uint32 input_backupId= 0, Uint32 backuppoint= 0);
int abortBackup(Uint32 backupId);
int performBackup(Uint32* backupId);
=== modified file 'storage/ndb/src/mgmsrv/Services.cpp'
--- a/storage/ndb/src/mgmsrv/Services.cpp 2008-11-07 11:00:38 +0000
+++ b/storage/ndb/src/mgmsrv/Services.cpp 2008-12-15 12:34:21 +0000
@@ -190,6 +190,7 @@ ParserRow<MgmApiSession> commands[] = {
MGM_CMD("start backup", &MgmApiSession::startBackup, ""),
MGM_ARG("completed", Int, Optional ,"Wait until completed"),
MGM_ARG("backupid", Int, Optional ,"User input backup id"),
+ MGM_ARG("backuppoint", Int, Optional ,"backup snapshot at start time or complete time"),
MGM_CMD("abort backup", &MgmApiSession::abortBackup, ""),
MGM_ARG("id", Int, Mandatory, "Backup id"),
@@ -750,19 +751,19 @@ MgmApiSession::startBackup(Parser<MgmApi
Properties const &args) {
DBUG_ENTER("MgmApiSession::startBackup");
unsigned backupId;
- unsigned input_backupId;
+ unsigned input_backupId= 0;
+ unsigned backuppoint= 0;
Uint32 completed= 2;
int result;
args.get("completed", &completed);
if(args.contains("backupid"))
- {
args.get("backupid", &input_backupId);
- result = m_mgmsrv.startBackup(backupId, completed, input_backupId);
- }
- else
- result = m_mgmsrv.startBackup(backupId, completed);
+ if(args.contains("backuppoint"))
+ args.get("backuppoint", &backuppoint);
+
+ result = m_mgmsrv.startBackup(backupId, completed, input_backupId, backuppoint);
m_output->println("start backup reply");
if(result != 0)
=== modified file 'storage/ndb/test/include/NdbBackup.hpp'
--- a/storage/ndb/test/include/NdbBackup.hpp 2006-12-23 19:20:40 +0000
+++ b/storage/ndb/test/include/NdbBackup.hpp 2008-12-15 12:34:21 +0000
@@ -26,7 +26,10 @@ public:
NdbBackup(int _own_id, const char* _addr = 0)
: NdbConfig(_own_id, _addr) {};
- int start(unsigned & _backup_id);
+ int start(unsigned & _backup_id,
+ int flags = 2,
+ unsigned int user_backup_id= 0,
+ unsigned int logtype= 0);
int restore(unsigned _backup_id);
int NFMaster(NdbRestarter& _restarter);
@@ -38,6 +41,8 @@ public:
int FailMasterAsSlave(NdbRestarter& _restarter);
int FailSlave(NdbRestarter& _restarter);
int Fail(NdbRestarter& _restarter, int *Fail_codes, const int sz, bool onMaster);
+ int startLogEvent();
+ int checkBackupStatus();
private:
@@ -47,6 +52,7 @@ private:
unsigned _backup_id);
const char * getBackupDataDirForNode(int _node_id);
+ NdbLogEventHandle log_handle;
};
=== modified file 'storage/ndb/test/ndbapi/testBackup.cpp'
--- a/storage/ndb/test/ndbapi/testBackup.cpp 2008-10-07 05:45:09 +0000
+++ b/storage/ndb/test/ndbapi/testBackup.cpp 2008-12-15 12:34:21 +0000
@@ -472,6 +472,155 @@ int runRestoreBankAndVerify(NDBT_Context
return result;
}
+int runBackupUndoWaitStarted(NDBT_Context* ctx, NDBT_Step* step){
+ NdbBackup backup(GETNDB(step)->getNodeId()+1);
+ unsigned backupId = 0;
+ int undoError = 10041;
+ NdbRestarter restarter;
+
+ if(restarter.waitClusterStarted(60)){
+ g_err << "waitClusterStarted failed"<< endl;
+ return NDBT_FAILED;
+ }
+
+ if (restarter.insertErrorInAllNodes(undoError) != 0) {
+ g_err << "Error insert failed" << endl;
+ return NDBT_FAILED;
+ }
+ // start backup wait started
+ if (backup.start(backupId, 1, 0, 1) == -1){
+ return NDBT_FAILED;
+ }
+ ndbout << "Started backup " << backupId << endl;
+ ctx->setProperty("BackupId", backupId);
+
+ return NDBT_OK;
+}
+int runChangeUndoDataDuringBackup(NDBT_Context* ctx, NDBT_Step* step){
+ Ndb* pNdb= GETNDB(step);
+
+ int records = ctx->getNumRecords();
+ int num = 5;
+ if (records - 5 < 0)
+ num = 1;
+
+ HugoTransactions hugoTrans(*ctx->getTab());
+
+ //update all rows
+ if(hugoTrans.pkUpdateRecords(pNdb, records) != 0) {
+ g_err << "Can't update all the records" << endl;
+ return NDBT_FAILED;
+ }
+
+ //delete first 10 rows
+ if(hugoTrans.pkDelRecords(pNdb, num*2) != 0) {
+ g_err << "Can't delete first 5 rows" << endl;
+ return NDBT_FAILED;
+ }
+
+ //add 5 new rows at the first(0 ~ 4)
+ NdbTransaction *pTransaction= pNdb->startTransaction();
+ if (pTransaction == NULL) {
+ g_err << "Can't get transaction pointer" << endl;
+ return NDBT_FAILED;
+ }
+ if(hugoTrans.setTransaction(pTransaction) != 0) {
+ g_err << "Set transaction error" << endl;
+ pNdb->closeTransaction(pTransaction);
+ return NDBT_FAILED;
+ }
+ if(hugoTrans.pkInsertRecord(pNdb, 0, num, 2) != 0) {
+ g_err << "pkInsertRecord error" << endl;
+ pNdb->closeTransaction(pTransaction);
+ return NDBT_FAILED;
+ }
+ if(pTransaction->execute(Commit ) != 0) {
+ g_err << "Can't commit transaction delete" << endl;
+ return NDBT_FAILED;
+ }
+ hugoTrans.closeTransaction(pNdb);
+
+ // make sure backup have finish
+ NdbBackup backup(GETNDB(step)->getNodeId()+1);
+
+ // start log event
+ if(backup.startLogEvent() != 0) {
+ g_err << "Can't create log event" << endl;
+ return NDBT_FAILED;
+ }
+ NdbSleep_SecSleep(15);
+ int i = 0;
+ while (1) {
+ if (backup.checkBackupStatus() == 2) //complete
+ break;
+ else if (i == 15) {
+ g_err << "Backup timeout" << endl;
+ return NDBT_FAILED;
+ } else
+ NdbSleep_SecSleep(2);
+ i++;
+ }
+
+ return NDBT_OK;
+}
+
+int runVerifyUndoData(NDBT_Context* ctx, NDBT_Step* step){
+ int records = ctx->getNumRecords();
+ Ndb* pNdb = GETNDB(step);
+ int count = 0;
+ int num = 5;
+ if (records - 5 < 0)
+ num = 1;
+
+ const NdbDictionary::Table* tab =
+ GETNDB(step)->getDictionary()->getTable(ctx->getTab()->getName());
+
+ if(tab == 0) {
+ g_err << " Can't find table" << endl;
+ return NDBT_FAILED;
+ }
+
+ UtilTransactions utilTrans(* tab);
+ HugoTransactions hugoTrans(* tab);
+
+ // Check that there are as many records as we expected
+ if(utilTrans.selectCount(pNdb, 64, &count) != 0) {
+ g_err << "Can't get records count" << endl;
+ return NDBT_FAILED;
+ }
+
+ g_err << "count = " << count;
+ g_err << " records = " << records;
+ g_err << endl;
+
+ if (count != records) {
+ g_err << "The records count is not correct" << endl;
+ return NDBT_FAILED;
+ }
+
+ // make sure all the update data is there
+ NdbTransaction *pTransaction= pNdb->startTransaction();
+ if (pTransaction == NULL) {
+ g_err << "Can't get transaction pointer" << endl;
+ return NDBT_FAILED;
+ }
+ if(hugoTrans.setTransaction(pTransaction) != 0) {
+ g_err << "Set transaction error" << endl;
+ pNdb->closeTransaction(pTransaction);
+ return NDBT_FAILED;
+ }
+ if(hugoTrans.pkReadRecord(pNdb, 0, records, NdbOperation::LM_Read) != 0) {
+ g_err << "Can't read record" << endl;
+ return NDBT_FAILED;
+ }
+ if(hugoTrans.verifyUpdatesValue(0, records) != 0) {
+ g_err << "The records restored with undo log is not correct" << endl;
+ return NDBT_FAILED;
+ }
+ hugoTrans.closeTransaction(pNdb);
+
+ return NDBT_OK;
+}
NDBT_TESTSUITE(testBackup);
TESTCASE("BackupOne",
@@ -539,6 +688,23 @@ TESTCASE("BackupBank",
VERIFIER(runRestoreBankAndVerify);
// FINALIZER(runDropBank);
}
+TESTCASE("BackupUndoLog",
+ "Test for backup happen at start time\n"
+ "1. Load table\n"
+ "2. Start backup with wait started\n"
+ "3. Insert, delete, update data during backup\n"
+ "4. Drop tables and restart \n"
+ "5. Restore\n"
+ "6. Verify records of table\n"
+ "7. Clear tables\n"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(runBackupUndoWaitStarted);
+ INITIALIZER(runChangeUndoDataDuringBackup);
+ INITIALIZER(runDropTablesRestart);
+ INITIALIZER(runRestoreOne);
+ VERIFIER(runVerifyUndoData);
+ FINALIZER(runClearTable);
+}
TESTCASE("NFMaster",
"Test that backup behaves during node failiure\n"){
INITIALIZER(setMaster);
=== modified file 'storage/ndb/test/src/NdbBackup.cpp'
--- a/storage/ndb/test/src/NdbBackup.cpp 2008-10-08 09:04:05 +0000
+++ b/storage/ndb/test/src/NdbBackup.cpp 2008-12-15 12:34:21 +0000
@@ -36,7 +36,10 @@
#include <mgmapi_configuration.hpp>
int
-NdbBackup::start(unsigned int & _backup_id){
+NdbBackup::start(unsigned int & _backup_id,
+ int flags,
+ unsigned int user_backup_id,
+ unsigned int logtype){
if (!isConnected())
@@ -45,10 +48,12 @@ NdbBackup::start(unsigned int & _backup_
ndb_mgm_reply reply;
reply.return_code = 0;
- if (ndb_mgm_start_backup(handle,
- 2, // wait until completed
+ if (ndb_mgm_start_backup3(handle,
+ flags,
&_backup_id,
- &reply) == -1) {
+ &reply,
+ user_backup_id,
+ logtype) == -1) {
g_err << "Error: " << ndb_mgm_get_latest_error(handle) << endl;
g_err << "Error msg: " << ndb_mgm_get_latest_error_msg(handle) << endl;
g_err << "Error desc: " << ndb_mgm_get_latest_error_desc(handle) << endl;
@@ -65,6 +70,50 @@ NdbBackup::start(unsigned int & _backup_
return 0;
}
+int
+NdbBackup::startLogEvent(){
+
+ if (!isConnected())
+ return -1;
+ log_handle= NULL;
+ int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0, 0 };
+ log_handle = ndb_mgm_create_logevent_handle(handle, filter);
+ if (!log_handle) {
+ g_err << "Can't create log event" << endl;
+ return -1;
+ }
+ return 0;
+}
+
+int
+NdbBackup::checkBackupStatus(){
+
+ struct ndb_logevent log_event;
+ int result = 0;
+ int res;
+ if(!log_handle) {
+ return -1;
+ }
+ if ((res= ndb_logevent_get_next(log_handle, &log_event, 3000)) > 0)
+ {
+ switch (log_event.type) {
+ case NDB_LE_BackupStarted:
+ result = 1;
+ break;
+ case NDB_LE_BackupCompleted:
+ result = 2;
+ break;
+ case NDB_LE_BackupAborted:
+ result = 3;
+ break;
+ default:
+ break;
+ }
+ }
+ ndb_mgm_destroy_logevent_handle(&log_handle);
+ return result;
+}
+
const char *
NdbBackup::getBackupDataDirForNode(int _node_id){
=== modified file 'storage/ndb/tools/restore/Restore.cpp'
--- a/storage/ndb/tools/restore/Restore.cpp 2008-10-22 10:23:13 +0000
+++ b/storage/ndb/tools/restore/Restore.cpp 2008-12-15 12:34:21 +0000
@@ -1120,6 +1120,7 @@ BackupFile::BackupFile(void (* _free_dat
m_file_size = 0;
m_file_pos = 0;
+ m_is_undolog = false;
}
BackupFile::~BackupFile(){
@@ -1176,21 +1177,104 @@ Uint32 BackupFile::buffer_get_ptr_ahead(
(*free_data_callback)();
reset_buffers();
- memcpy(m_buffer, m_buffer_ptr, m_buffer_data_left);
- int error;
- size_t r = azread(&m_file,
- ((char *)m_buffer) + m_buffer_data_left,
- m_buffer_sz - m_buffer_data_left, &error);
- m_file_pos += r;
- m_buffer_data_left += r;
- m_buffer_ptr = m_buffer;
+ if (m_is_undolog)
+ {
+ /* move the left data to the end of buffer
+ */
+ size_t r = 0;
+ int error;
+ /* move the left data to the end of buffer
+ * m_buffer_ptr point the end of the left data. buffer_data_start point the start of left data
+ * m_buffer_data_left is the length of left data.
+ */
+ Uint32 file_left_entry_data = 0;
+ Uint32 buffer_free_space = m_buffer_sz - m_buffer_data_left;
+ void * buffer_end = (char *)m_buffer + m_buffer_sz;
+ void * buffer_data_start = (char *)m_buffer_ptr - m_buffer_data_left;
+
+ memmove((char *)buffer_end - m_buffer_data_left, buffer_data_start, m_buffer_data_left);
+ buffer_data_start = (char *)buffer_end - m_buffer_data_left;
+ /*
+ * For undo log file we should read log entris backwards from log file.
+ * That mean the first entries should start at sizeof(m_fileHeader).
+ * The end of the last entries should be the end of log file(EOF-1).
+ * If ther are entries left in log file to read.
+ * m_file_pos should bigger than sizeof(m_fileHeader).
+ * If the length of left log entries less than the residual length of buffer,
+ * we just need to read all the left entries from log file into the buffer.
+ * and all the left entries in log file should been read into buffer. Or
+ * If the length of left entries is bigger than the residual length of buffer,
+ * we should fill the buffer because the current buffer can't contain
+ all the left log entries, we should read more times.
+ *
+ */
+ if (m_file_pos > sizeof(m_fileHeader))
+ {
+ /*
+ * We read(consume) data from the end of the buffer.
+ * If the left data is not enough for next read in buffer,
+ * we move the residual data to the end of buffer.
+ * Then we will fill the start of buffer with new data from log file.
+ * eg. If the buffer length is 10. "+" denotes useless content.
+ * top end
+ * Bytes in file abcdefgh0123456789
+ * Byte in buffer 0123456789 --after first read
+ * Consume datas... (6789) (2345)
+ * Bytes in buffer 01++++++++ --after several consumes
+ * Move data to end ++++++++01
+ * Bytes in buffer abcdefgh01 --after second read
+ */
+ file_left_entry_data = m_file_pos - sizeof(m_fileHeader);
+ if (file_left_entry_data <= buffer_free_space)
+ {
+ /* All remaining data fits in space available in buffer.
+ * Read data into buffer before existing data.
+ */
+ // Move to the start of data to be read
+ azseek(&m_file, sizeof(m_fileHeader), SEEK_SET);
+ r = azread(&m_file, (char *)buffer_data_start - file_left_entry_data, file_left_entry_data, &error);
+ //move back
+ azseek(&m_file, sizeof(m_fileHeader), SEEK_SET);
+ }
+ else
+ {
+ // Fill remaing space at start of buffer with data from file.
+ azseek(&m_file, m_file_pos-buffer_free_space, SEEK_SET);
+ r = azread(&m_file, ((char *)m_buffer), buffer_free_space, &error);
+ azseek(&m_file, m_file_pos-buffer_free_space, SEEK_SET);
+ }
+ }
+ m_file_pos -= r;
+ m_buffer_data_left += r;
+ //move to the end of buffer
+ m_buffer_ptr = buffer_end;
+ }
+ else
+ {
+ memmove(m_buffer, m_buffer_ptr, m_buffer_data_left);
+ int error;
+ size_t r = azread(&m_file,
+ ((char *)m_buffer) + m_buffer_data_left,
+ m_buffer_sz - m_buffer_data_left, &error);
+ m_file_pos += r;
+ m_buffer_data_left += r;
+ m_buffer_ptr = m_buffer;
+ }
if (sz > m_buffer_data_left)
sz = size * (m_buffer_data_left / size);
}
- *p_buf_ptr = m_buffer_ptr;
+ /*
+ * For undolog, the m_buffer_ptr points to the end of the left data.
+ * After we get data from the end of buffer, the data-end move forward.
+ * So we should move m_buffer_ptr to the right place.
+ */
+ if(m_is_undolog)
+ *p_buf_ptr = (char *)m_buffer_ptr - sz;
+ else
+ *p_buf_ptr = m_buffer_ptr;
return sz/size;
}
@@ -1198,8 +1282,19 @@ Uint32 BackupFile::buffer_get_ptr(void *
{
Uint32 r = buffer_get_ptr_ahead(p_buf_ptr, size, nmemb);
- m_buffer_ptr = ((char*)m_buffer_ptr)+(r*size);
- m_buffer_data_left -= (r*size);
+ if(m_is_undolog)
+ {
+ /* we read from end of buffer to start of buffer.
+ * m_buffer_ptr keep at the end of real data in buffer.
+ */
+ m_buffer_ptr = ((char*)m_buffer_ptr)-(r*size);
+ m_buffer_data_left -= (r*size);
+ }
+ else
+ {
+ m_buffer_ptr = ((char*)m_buffer_ptr)+(r*size);
+ m_buffer_data_left -= (r*size);
+ }
return r;
}
@@ -1333,10 +1428,30 @@ BackupFile::readHeader(){
debug << "ByteOrder is " << m_fileHeader.ByteOrder << endl;
debug << "magicByteOrder is " << magicByteOrder << endl;
- if (m_fileHeader.FileType != m_expectedFileHeader.FileType){
+
+ if (m_fileHeader.FileType != m_expectedFileHeader.FileType &&
+ !(m_expectedFileHeader.FileType == BackupFormat::LOG_FILE &&
+ m_fileHeader.FileType == BackupFormat::UNDO_FILE)){
+ // UNDO_FILE will do in case where we expect LOG_FILE
abort();
}
+ if(m_fileHeader.FileType == BackupFormat::UNDO_FILE){
+ m_is_undolog = true;
+ /* move pointer to end of data part.
+ move 4 bytes from the end of file
+ because footer contain 4 bytes 0 at the end of file.
+ we discard the remain data stored in m_buffer.
+ */
+ struct stat buf;
+ if (fstat(m_file.file, &buf) == 0)
+ m_file_size = (Uint64)buf.st_size;
+ azseek(&m_file, 4, SEEK_END);
+ m_file_pos = m_file_size - 4;
+ m_buffer_data_left = 0;
+ m_buffer_ptr = m_buffer;
+ }
+
// Check for BackupFormat::FileHeader::ByteOrder if swapping is needed
if (m_fileHeader.ByteOrder == magicByteOrder) {
m_hostByteOrder = true;
@@ -1558,9 +1673,24 @@ RestoreLogIterator::getNextLogEntry(int
do {
Uint32 len;
Uint32 *logEntryPtr;
- if (buffer_read_ahead(&len, sizeof(Uint32), 1) != 1){
- res= -1;
- return 0;
+ if(m_is_undolog){
+ int read_result = 0;
+ read_result = buffer_read(&len, sizeof(Uint32), 1);
+ //no more log data to read
+ if (read_result == 0 ) {
+ res = 0;
+ return 0;
+ }
+ if (read_result != 1) {
+ res= -1;
+ return 0;
+ }
+ }
+ else{
+ if (buffer_read_ahead(&len, sizeof(Uint32), 1) != 1){
+ res= -1;
+ return 0;
+ }
}
len= ntohl(len);
@@ -1615,15 +1745,27 @@ RestoreLogIterator::getNextLogEntry(int
} while(m_last_gci > stopGCP + 1);
m_logEntry.m_table = m_metaData.getTable(tableId);
+ /* We should 'invert' the operation type when we restore an Undo log.
+ * To undo an insert operation, a delete is required.
+ * To undo a delete operation, an insert is required.
+ * The backup have collected 'before values' for undoing 'delete+update' to make this work.
+ * To undo insert, we only need primary key.
+ */
switch(triggerEvent){
case TriggerEvent::TE_INSERT:
- m_logEntry.m_type = LogEntry::LE_INSERT;
+ if(m_is_undolog)
+ m_logEntry.m_type = LogEntry::LE_DELETE;
+ else
+ m_logEntry.m_type = LogEntry::LE_INSERT;
break;
case TriggerEvent::TE_UPDATE:
m_logEntry.m_type = LogEntry::LE_UPDATE;
break;
case TriggerEvent::TE_DELETE:
- m_logEntry.m_type = LogEntry::LE_DELETE;
+ if(m_is_undolog)
+ m_logEntry.m_type = LogEntry::LE_INSERT;
+ else
+ m_logEntry.m_type = LogEntry::LE_DELETE;
break;
default:
res = -1;
=== modified file 'storage/ndb/tools/restore/Restore.hpp'
--- a/storage/ndb/tools/restore/Restore.hpp 2008-10-08 13:42:33 +0000
+++ b/storage/ndb/tools/restore/Restore.hpp 2008-12-15 12:34:21 +0000
@@ -299,6 +299,8 @@ protected:
Uint64 m_file_size;
Uint64 m_file_pos;
+ bool m_is_undolog;
+
void (* free_data_callback)();
virtual void reset_buffers() {}
| Thread |
|---|
| • bzr commit into mysql-5.1 branch (zhou.li:3072) WL#4397 | Leonard Zhou | 15 Dec |