#At file:///localhome/jl208045/mysql/mysql-6.0-backup-41012/
2756 Jorgen Loland 2009-02-03
Bug#41012 - Error checks when reading backup image not covered by tests.
Previously, there were no tests of RESTORE when errors occured. This patch adds debug hooks that can be used to inject error into the RESTORE code.
modified:
mysql-test/suite/backup/r/backup_errors.result
mysql-test/suite/backup/t/backup_errors.test
sql/backup/be_default.cc
sql/backup/data_backup.cc
sql/backup/kernel.cc
sql/backup/stream.h
per-file messages:
mysql-test/suite/backup/r/backup_errors.result
Add tests that inject errors into RESTORE code
mysql-test/suite/backup/t/backup_errors.test
Add tests that inject errors into RESTORE code
sql/backup/be_default.cc
Add debug hook for testing purposes that can be used to inject error into Restore::send_data
sql/backup/data_backup.cc
Add debug hook for testing purposes that can be used to inject error into RESTORE method restore_table_data
sql/backup/kernel.cc
Add debug hook for testing purposes that can be used to inject error into various RESTORE methods
sql/backup/stream.h
Add debug hook for testing purposes that can be used to inject errors into various restore methods
=== modified file 'mysql-test/suite/backup/r/backup_errors.result'
--- a/mysql-test/suite/backup/r/backup_errors.result 2009-01-08 14:57:41 +0000
+++ b/mysql-test/suite/backup/r/backup_errors.result 2009-02-03 07:48:09 +0000
@@ -323,6 +323,7 @@ trigger metadata
SET SESSION DEBUG='+d,backup_fail_add_trigger';
BACKUP DATABASE db1 TO 'bup_db1.bak';
ERROR HY000: Failed to obtain meta-data for trigger `db1`.`trg`
+SET SESSION DEBUG='-d';
Get last backup_id
SELECT MAX(backup_id) INTO @bup_id FROM mysql.backup_history
WHERE command LIKE "BACKUP DATABASE db1 TO%";
@@ -438,4 +439,109 @@ backup_id
SHOW WARNINGS;
Level Code Message
+#
+# Test error handling by injecting errors into RESTORE
+#
+# Make backup image with objects necessary for error injection
+CREATE TABLE table2 (i int NOT NULL) ENGINE=CSV;
+INSERT INTO table2 values (1),(2);
+CREATE TRIGGER db1.trg AFTER INSERT ON db1.table2 FOR EACH ROW
+BEGIN
+INSERT INTO db1.table1(v) VALUES ('Test trigger fired');
+END;||
+BACKUP DATABASE db1 TO 'errorinject.bak';
+backup_id
+#
+DROP DATABASE db1;
+#
+# Backup image created. Start RESTORE with error injection
+#
+# Error injection in RESTORE: Read header
+#
+SET SESSION DEBUG='+d,restore_read_header';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Can't read backup archive preamble
+SET SESSION DEBUG='-d';
+#
+# Error injection in RESTORE: Get next chunk;
+# Called from prepare_for_restore, after read_header
+#
+SET SESSION DEBUG='+d,restore_prepare_next_chunk_1';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Can't go to the next chunk in backup stream
+SET SESSION DEBUG='-d';
+#
+# Error injection in RESTORE: Read catalog
+#
+SET SESSION DEBUG='+d,restore_read_catalog';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Can't read backup archive preamble
+SET SESSION DEBUG='-d';
+#
+# Error injection in RESTORE: Get next chunk;
+# Called from prepare_for_restore, after read_catalog
+#
+SET SESSION DEBUG='+d,restore_prepare_next_chunk_2';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Can't go to the next chunk in backup stream
+SET SESSION DEBUG='-d';
+#
+# Error injection in RESTORE: Read metadata from stream
+#
+SET SESSION DEBUG='+d,restore_read_meta_data';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Error when reading meta-data
+SET SESSION DEBUG='-d';
+DROP DATABASE db1;
+#
+# Error injection in RESTORE: Get next chunk;
+# Called from do_restore
+#
+SET SESSION DEBUG='+d,restore_stream_next_chunk';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Can't go to the next chunk in backup stream
+SET SESSION DEBUG='-d';
+DROP DATABASE db1;
+#
+# Error injection in RESTORE: Lock tables
+#
+SET SESSION DEBUG='+d,restore_lock_tables_for_restore';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Open and lock tables failed in RESTORE
+SET SESSION DEBUG='-d';
+DROP DATABASE db1;
+#
+# Error injection in RESTORE: Restore table data
+#
+SET SESSION DEBUG='+d,restore_tbl_data_read';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Error when reading data from backup stream
+SET SESSION DEBUG='-d';
+DROP DATABASE db1;
+#
+# Error injection in RESTORE: Send data (default driver)
+#
+SET SESSION DEBUG='+d,restore_default_send_data';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Error when sending data (for table #1) to Default restore driver
+SET SESSION DEBUG='-d';
+DROP DATABASE db1;
+#
+# Error injection in RESTORE: Restore trigger
+#
+SET SESSION DEBUG='+d,restore_trigger';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Could not restore trigger `db1`.`trg`
+SET SESSION DEBUG='-d';
+DROP DATABASE db1;
+#
+# Error injection in RESTORE: Read summary
+#
+SET SESSION DEBUG='+d,restore_read_summary';
+RESTORE FROM 'errorinject.bak';
+ERROR HY000: Error when reading summary section of backup image
+SET SESSION DEBUG='-d';
+#
+# Cleanup
+#
DROP DATABASE db1;
=== modified file 'mysql-test/suite/backup/t/backup_errors.test'
--- a/mysql-test/suite/backup/t/backup_errors.test 2009-01-08 14:57:41 +0000
+++ b/mysql-test/suite/backup/t/backup_errors.test 2009-02-03 07:48:09 +0000
@@ -417,6 +417,7 @@ SET DEBUG_SYNC= 'reset';
SET SESSION DEBUG='+d,backup_fail_add_trigger';
--error ER_BACKUP_GET_META_TRIGGER
BACKUP DATABASE db1 TO 'bup_db1.bak';
+SET SESSION DEBUG='-d';
--echo Get last backup_id
SELECT MAX(backup_id) INTO @bup_id FROM mysql.backup_history
@@ -543,5 +544,148 @@ SHOW WARNINGS;
--remove_file $MYSQLTEST_VARDIR/master-data/newtest.bak
--echo
+
+--echo #
+--echo # Test error handling by injecting errors into RESTORE
+--echo #
+
+--echo # Make backup image with objects necessary for error injection
+
+# A MyISAM table (table1) already exists in db1
+
+# A table that uses default backup driver is required
+CREATE TABLE table2 (i int NOT NULL) ENGINE=CSV;
+INSERT INTO table2 values (1),(2);
+
+# A trigger is required
+DELIMITER ||;
+CREATE TRIGGER db1.trg AFTER INSERT ON db1.table2 FOR EACH ROW
+BEGIN
+ INSERT INTO db1.table1(v) VALUES ('Test trigger fired');
+END;||
+DELIMITER ;||
+
+--replace_column 1 #
+BACKUP DATABASE db1 TO 'errorinject.bak';
+
+DROP DATABASE db1;
+
+--echo #
+--echo # Backup image created. Start RESTORE with error injection
+
+--echo #
+--echo # Error injection in RESTORE: Read header
+--echo #
+SET SESSION DEBUG='+d,restore_read_header';
+--error ER_BACKUP_READ_HEADER
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+--echo #
+--echo # Error injection in RESTORE: Get next chunk;
+--echo # Called from prepare_for_restore, after read_header
+--echo #
+SET SESSION DEBUG='+d,restore_prepare_next_chunk_1';
+--error ER_BACKUP_NEXT_CHUNK
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+--echo #
+--echo # Error injection in RESTORE: Read catalog
+--echo #
+SET SESSION DEBUG='+d,restore_read_catalog';
+--error ER_BACKUP_READ_HEADER
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+--echo #
+--echo # Error injection in RESTORE: Get next chunk;
+--echo # Called from prepare_for_restore, after read_catalog
+--echo #
+SET SESSION DEBUG='+d,restore_prepare_next_chunk_2';
+--error ER_BACKUP_NEXT_CHUNK
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+--echo #
+--echo # Error injection in RESTORE: Read metadata from stream
+--echo #
+SET SESSION DEBUG='+d,restore_read_meta_data';
+--error ER_BACKUP_READ_META
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+# Database partially created by the failing restore
+DROP DATABASE db1;
+
+--echo #
+--echo # Error injection in RESTORE: Get next chunk;
+--echo # Called from do_restore
+--echo #
+SET SESSION DEBUG='+d,restore_stream_next_chunk';
+--error ER_BACKUP_NEXT_CHUNK
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+# Database partially created by the failing restore
+DROP DATABASE db1;
+
+--echo #
+--echo # Error injection in RESTORE: Lock tables
+--echo #
+SET SESSION DEBUG='+d,restore_lock_tables_for_restore';
+--error ER_BACKUP_OPEN_TABLES
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+# Database partially created by the failing restore
DROP DATABASE db1;
+--echo #
+--echo # Error injection in RESTORE: Restore table data
+--echo #
+SET SESSION DEBUG='+d,restore_tbl_data_read';
+--error ER_BACKUP_READ_DATA
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+# Database partially created by the failing restore
+DROP DATABASE db1;
+
+--echo #
+--echo # Error injection in RESTORE: Send data (default driver)
+--echo #
+SET SESSION DEBUG='+d,restore_default_send_data';
+--error ER_BACKUP_SEND_DATA
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+DROP DATABASE db1;
+
+--echo #
+--echo # Error injection in RESTORE: Restore trigger
+--echo #
+SET SESSION DEBUG='+d,restore_trigger';
+--error ER_BACKUP_CANT_RESTORE_TRIGGER
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+DROP DATABASE db1;
+
+--echo #
+--echo # Error injection in RESTORE: Read summary
+--echo #
+SET SESSION DEBUG='+d,restore_read_summary';
+--error ER_BACKUP_READ_SUMMARY
+RESTORE FROM 'errorinject.bak';
+SET SESSION DEBUG='-d';
+
+--echo #
+--echo # Cleanup
+--echo #
+
+DROP DATABASE db1;
+
+--remove_file $MYSQLTEST_VARDIR/master-data/overwrite.bak
+--remove_file $MYSQLTEST_VARDIR/master-data/errorinject.bak
+
=== modified file 'sql/backup/be_default.cc'
--- a/sql/backup/be_default.cc 2009-01-21 15:00:23 +0000
+++ b/sql/backup/be_default.cc 2009-02-03 07:48:09 +0000
@@ -699,6 +699,8 @@ result_t Restore::send_data(Buffer &buf)
DBUG_PRINT("default_restore",("Got packet with %lu bytes from stream %u",
(unsigned long)buf.size, buf.table_num));
+ DBUG_EXECUTE_IF("restore_default_send_data", DBUG_RETURN(ERROR););
+
/*
get_data() should not be called after cancel has been called.
*/
=== modified file 'sql/backup/data_backup.cc'
--- a/sql/backup/data_backup.cc 2009-01-21 15:06:10 +0000
+++ b/sql/backup/data_backup.cc 2009-02-03 07:48:09 +0000
@@ -1542,6 +1542,9 @@ int restore_table_data(THD *thd, Restore
bzero(&chunk_info, sizeof(chunk_info));
ret= bstream_rd_data_chunk(&s, &chunk_info);
+ /* Mimic error in bstream_rd_data_chunk */
+ DBUG_EXECUTE_IF("restore_tbl_data_read", ret= BSTREAM_ERROR;);
+
switch (ret) {
case BSTREAM_EOS:
@@ -1595,6 +1598,10 @@ int restore_table_data(THD *thd, Restore
*/
DBUG_ASSERT(snap && drvr);
+ /*
+ Note: For testing, error can be injected in default driver
+ send_data by using dbug hook 'backup_default_send_data'
+ */
ret= drvr->send_data(buf);
switch (ret) {
=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc 2009-01-21 15:06:10 +0000
+++ b/sql/backup/kernel.cc 2009-02-03 07:48:09 +0000
@@ -791,7 +791,10 @@ Backup_restore_ctx::prepare_for_restore(
return NULL;
}
- if (s->next_chunk() != BSTREAM_OK)
+ ret= s->next_chunk();
+ /* Mimic error in next_chunk */
+ DBUG_EXECUTE_IF("restore_prepare_next_chunk_1", ret= BSTREAM_ERROR; );
+ if (ret != BSTREAM_OK)
{
fatal_error(report_error(ER_BACKUP_NEXT_CHUNK));
return NULL;
@@ -806,7 +809,10 @@ Backup_restore_ctx::prepare_for_restore(
return NULL;
}
- if (s->next_chunk() != BSTREAM_OK)
+ ret= s->next_chunk();
+ /* Mimic error in next_chunk */
+ DBUG_EXECUTE_IF("restore_prepare_next_chunk_2", ret= BSTREAM_ERROR; );
+ if (ret != BSTREAM_OK)
{
fatal_error(report_error(ER_BACKUP_NEXT_CHUNK));
return NULL;
@@ -887,6 +893,15 @@ int Backup_restore_ctx::lock_tables_for_
}
}
+ DBUG_EXECUTE_IF("restore_lock_tables_for_restore",
+ /*
+ Mimic error in opening tables. Cannot be done by setting ret=1
+ after open_and_lock_tables_derived becase that method is
+ supposed to release the lock before returning error.
+ */
+ return fatal_error(report_error(ER_BACKUP_OPEN_TABLES,"RESTORE"));
+ );
+
/*
Open and lock the tables.
@@ -1182,10 +1197,15 @@ int Backup_restore_ctx::restore_triggers
break;
case BSTREAM_IT_TRIGGER:
+ {
DBUG_ASSERT(obj->m_obj_ptr);
// Mark that data is being changed.
info->m_data_changed= TRUE;
- if (obj->m_obj_ptr->create(m_thd))
+
+ bool ret= obj->m_obj_ptr->create(m_thd);
+ /* Mimic error in restore of trigger */
+ DBUG_EXECUTE_IF("restore_trigger", ret= TRUE;);
+ if (ret)
{
delete it;
delete dbit;
@@ -1194,7 +1214,7 @@ int Backup_restore_ctx::restore_triggers
DBUG_RETURN(fatal_error(err));
}
break;
-
+ }
default: break;
}
@@ -1285,7 +1305,10 @@ int Backup_restore_ctx::do_restore(bool
DBUG_RETURN(fatal_error(err));
}
- if (s.next_chunk() == BSTREAM_ERROR)
+ err= s.next_chunk();
+ /* Mimic error in next_chunk */
+ DBUG_EXECUTE_IF("restore_stream_next_chunk", err= BSTREAM_ERROR; );
+ if (err == BSTREAM_ERROR)
{
DBUG_RETURN(fatal_error(report_error(ER_BACKUP_NEXT_CHUNK)));
}
=== modified file 'sql/backup/stream.h'
--- a/sql/backup/stream.h 2008-12-18 21:46:36 +0000
+++ b/sql/backup/stream.h 2009-02-03 07:48:09 +0000
@@ -220,6 +220,7 @@ result_t
read_header(Image_info &info, Input_stream &s)
{
int ret= bstream_rd_header(&s, static_cast<st_bstream_image_header*>(&info));
+ DBUG_EXECUTE_IF("restore_read_header", ret= BSTREAM_ERROR;);
return ret == BSTREAM_ERROR ? ERROR : OK;
}
@@ -236,6 +237,7 @@ result_t
read_catalog(Image_info &info, Input_stream &s)
{
int ret= bstream_rd_catalogue(&s, static_cast<st_bstream_image_header*>(&info));
+ DBUG_EXECUTE_IF("restore_read_catalog", ret= BSTREAM_ERROR;);
return ret == BSTREAM_ERROR ? ERROR : OK;
}
@@ -252,6 +254,7 @@ result_t
read_meta_data(Image_info &info, Input_stream &s)
{
int ret= bstream_rd_meta_data(&s, static_cast<st_bstream_image_header*>(&info));
+ DBUG_EXECUTE_IF("restore_read_meta_data", ret= BSTREAM_ERROR;);
return ret == BSTREAM_ERROR ? ERROR : OK;
}
@@ -268,6 +271,7 @@ result_t
read_summary(Image_info &info, Input_stream &s)
{
int ret= bstream_rd_summary(&s, static_cast<st_bstream_image_header*>(&info));
+ DBUG_EXECUTE_IF("restore_read_summary",ret= BSTREAM_ERROR;);
return ret == BSTREAM_ERROR ? ERROR : OK;
}
| Thread |
|---|
| • bzr commit into mysql-6.0-backup branch (jorgen.loland:2756) Bug#41012 | Jorgen Loland | 3 Feb |