List:Commits« Previous MessageNext Message »
From:Leonard Zhou Date:December 15 2008 12:37pm
Subject:bzr commit into mysql-5.1 branch (zhou.li:3072) WL#4397
View as plain text  
#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#4397Leonard Zhou15 Dec