#At file:///ext/mysql/bzr/backup/bug40303/
2731 Rafal Somla 2008-11-19
BUG#40303 (Backup: Wrong error send to client if several errors reported)
BUG#40304 (Backup: Errors reported during BACKUP show as warnings on the
error stack)
Before: Errors reported using backup::Logger class could be saved and in
case several errors are reported, the last one was sent to client as an
error reply from BACKUP/RESTORE command.
After: Errors reported with backup::Logger are reported to the server
using my_printf_error(..) function. This function pushes error on the
error stack (unles told otherwise) and stores the first reported error
so that it is send to the client.
Additionally.
- Function log_error(..) is moved to the Logger class.
- Code is changed to consistently use Logger::report/log_error() for error
reporting.
- Semantics of Backup_restore_ctx::fatal_error() has been changed to
discourage its use as an error reporting facility. Now it is an internal helper
method which moves the context object into error state. It is used only by the
class methods and it is made private. The idea is that context object should
move into error state only as a result of executing one of its methods (not
externally).
- Improved error reporting in few places.
modified:
mysql-test/suite/backup/r/backup_errors.result
mysql-test/suite/backup/r/backup_views.result
mysql-test/suite/backup/t/backup_errors.test
mysql-test/suite/backup/t/backup_myisam1.test
mysql-test/suite/backup/t/backup_views.test
sql/backup/backup_info.cc
sql/backup/backup_info.h
sql/backup/backup_kernel.h
sql/backup/data_backup.cc
sql/backup/image_info.cc
sql/backup/image_info.h
sql/backup/kernel.cc
sql/backup/logger.cc
sql/backup/logger.h
sql/backup/restore_info.h
sql/share/errmsg.txt
per-file messages:
mysql-test/suite/backup/t/backup_errors.test
Add SHOW WARNINGS to see what is pushed on the error stack in case of errors.
mysql-test/suite/backup/t/backup_myisam1.test
Update the test, taking into account that after this patch failed BACKUP does not
leave the unfinished backup image file around.
mysql-test/suite/backup/t/backup_views.test
Update the test taking into account that now RESTORE returns the first
error reported.
sql/backup/backup_info.cc
- Use m_log.report_error(...) for error reporting.
- Use the m_thd member instead of refering to a context class instance.
sql/backup/backup_info.h
- Instead of storing a reference to a complete Backup_restore_ctx instance,
store only what is needed: a Logger instance and a THD handle.
- Make constructor private.
sql/backup/backup_kernel.h
- Move log_error(..) method to the Logger class.
- Make fatal_error(...) private and change its semantics. Now it only moves context
object to an error state, but it does not report any errors - Logger methods should
be used for reporting them.
sql/backup/data_backup.cc
- Use Logger instance for reporting errors.
- Report few errors not logged previously (e.g. when (un)block_commits(..) fails).
- Remove cancel_backup() calls as this is done in Backup_restore_ctx::close()
called from destructor.
- Inside Backup_pump class: log errors only if logger is set.
- Fix the shutdown logic in restore_table_data(..). Drivers need to be correctly
de-initialized by a call to ->end() during normal operation or ->cacnel() in
case
of interruption.
sql/backup/image_info.h
Introduced MAX_SNAP_COUNT symbolic constant.
sql/backup/kernel.cc
- Use explicit calls to report/log_error(..) for error logging - now fatal_error(..)
does not log anything.
- Simplified send_error(..) implementation - now it does not have to look for the
last error reported. The first reported error is automatically stored by the
server and send to the client.
- Move error reporting context preparations to Logger::init(..).
- To clarify the code, calls to s->next_chunk() have been moved to wrapper
functions read_header(..), read_catalog(..) and read_meta_data(..) where they
really belong.
sql/backup/logger.cc
- Remove code saving reported errors.
- Use my_printf_error(..) instead of push_warning_printf(..) for
reporting errors to the server core. This has the side effect of
storing the first reported error so that it is sent to the client.
sql/backup/logger.h
- Add log_error(..) method moved here from Backup_restore_ctx.
- Remove methods for saving reported errors - not needed any more because the
first reported error is remembered by the server core.
- Add error_reported() method.
- Add error context cleanup (on server level) to init() method, instead of doing
it inside Backup_restore_ctx class.
sql/backup/restore_info.h
- Only store what is needed: reference to Logger and THD handle.
- Made constructor private.
sql/share/errmsg.txt
Add error message for reporting problems during validity point
creation.
=== modified file 'mysql-test/suite/backup/r/backup_errors.result'
--- a/mysql-test/suite/backup/r/backup_errors.result 2008-11-05 09:41:15 +0000
+++ b/mysql-test/suite/backup/r/backup_errors.result 2008-11-19 10:18:41 +0000
@@ -7,19 +7,36 @@ CREATE DATABASE bdb;
CREATE TABLE bdb.t1(a int) ENGINE=MEMORY;
BACKUP DATABASE adb TO '';
ERROR HY000: Malformed file path ''
+SHOW WARNINGS;
+Level Code Message
+Error # Malformed file path ''
BACKUP DATABASE adb TO "bdb/t1.frm";
ERROR HY000: Can't write to backup location 'bdb/t1.frm' (file already exists?)
+SHOW WARNINGS;
+Level Code Message
+Error # Can't write to backup location 'bdb/t1.frm' (file already exists?)
BACKUP DATABASE adb TO "test.bak";
backup_id
#
+SHOW WARNINGS;
+Level Code Message
BACKUP DATABASE adb TO "test.bak";
ERROR HY000: Can't write to backup location 'test.bak' (file already exists?)
+SHOW WARNINGS;
+Level Code Message
+Error # Can't write to backup location 'test.bak' (file already exists?)
DROP DATABASE IF EXISTS foo;
DROP DATABASE IF EXISTS bar;
BACKUP DATABASE foo TO 'test.bak';
ERROR 42000: Unknown database 'foo'
+SHOW WARNINGS;
+Level Code Message
+Error 1049 Unknown database 'foo'
BACKUP DATABASE test,foo,bdb,bar TO 'test.bak';
ERROR 42000: Unknown database 'foo,bar'
+SHOW WARNINGS;
+Level Code Message
+Error # Unknown database 'foo,bar'
BACKUP DATABASE foo,test,bar,foo TO 'test.bak';
ERROR 42000: Not unique database: 'foo'
use adb;
@@ -49,21 +66,39 @@ DROP DATABASE bdb;
Backup of mysql, information_schema scenario 1
BACKUP DATABASE mysql TO 't.bak';
ERROR HY000: Database 'mysql' cannot be included in a backup
+SHOW WARNINGS;
+Level Code Message
+Error # Database 'mysql' cannot be included in a backup
Backup of mysql, information_schema scenario 2
BACKUP DATABASE information_schema TO 't.bak';
ERROR HY000: Database 'information_schema' cannot be included in a backup
+SHOW WARNINGS;
+Level Code Message
+Error # Database 'information_schema' cannot be included in a backup
Backup of mysql, information_schema scenario 3
BACKUP DATABASE mysql, information_schema TO 't.bak';
ERROR HY000: Database 'mysql' cannot be included in a backup
+SHOW WARNINGS;
+Level Code Message
+Error # Database 'mysql' cannot be included in a backup
Backup of mysql, information_schema scenario 4
BACKUP DATABASE mysql, test TO 't.bak';
ERROR HY000: Database 'mysql' cannot be included in a backup
+SHOW WARNINGS;
+Level Code Message
+Error # Database 'mysql' cannot be included in a backup
Backup of mysql, information_schema scenario 5
BACKUP DATABASE information_schema, test TO 't.bak';
ERROR HY000: Database 'information_schema' cannot be included in a backup
+SHOW WARNINGS;
+Level Code Message
+Error # Database 'information_schema' cannot be included in a backup
Backup of mysql, information_schema scenario 6
BACKUP DATABASE mysql, information_schema, test TO 't.bak';
ERROR HY000: Database 'mysql' cannot be included in a backup
+SHOW WARNINGS;
+Level Code Message
+Error # Database 'mysql' cannot be included in a backup
Making copies of progress tables.
CREATE TABLE IF NOT EXISTS test.ob_copy LIKE mysql.backup_history;
CREATE TABLE IF NOT EXISTS test.obp_copy LIKE mysql.backup_progress;
@@ -78,7 +113,7 @@ DROP TABLE mysql.backup_history;
Backup the database;
BACKUP DATABASE test_ob_error TO 'ob_err.bak';
ERROR HY000: Can't open the backup logs as tables. Check 'mysql.backup_history' and
'mysql.backup_progress' or run mysql_upgrade to repair.
-SHOW ERRORS;
+SHOW WARNINGS;
Level Code Message
Error # Table 'mysql.backup_history' doesn't exist
Error # Cannot create backup/restore execution context
@@ -89,7 +124,7 @@ DROP TABLE mysql.backup_progress;
Backup the database;
BACKUP DATABASE test_ob_error TO 'ob_err.bak';
ERROR HY000: Can't open the backup logs as tables. Check 'mysql.backup_history' and
'mysql.backup_progress' or run mysql_upgrade to repair.
-SHOW ERRORS;
+SHOW WARNINGS;
Level Code Message
Error # Table 'mysql.backup_progress' doesn't exist
Error # Cannot create backup/restore execution context
=== modified file 'mysql-test/suite/backup/r/backup_views.result'
--- a/mysql-test/suite/backup/r/backup_views.result 2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/r/backup_views.result 2008-11-19 10:18:41 +0000
@@ -277,10 +277,10 @@ DROP DATABASE bup_db2;
Restore database.
restore database with view dependency to other, non-existing db
RESTORE FROM 'bup_objectview1.bak';
-ERROR HY000: Could not restore view `bup_db1`.`v5`. Please check the view definition for
possible missing dependencies.
+ERROR 42S02: Table 'bup_db2.t2' doesn't exist
DROP DATABASE bup_db1;
RESTORE FROM 'bup_objectview2.bak';
-ERROR HY000: Could not restore view `bup_db2`.`student_details`. Please check the view
definition for possible missing dependencies.
+ERROR 42S02: Table 'bup_db1.t3' doesn't exist
DROP DATABASE bup_db2;
RESTORE FROM 'bup_objectview.bak';
backup_id
=== modified file 'mysql-test/suite/backup/t/backup_errors.test'
--- a/mysql-test/suite/backup/t/backup_errors.test 2008-11-05 09:41:15 +0000
+++ b/mysql-test/suite/backup/t/backup_errors.test 2008-11-19 10:18:41 +0000
@@ -25,17 +25,25 @@ CREATE TABLE bdb.t1(a int) ENGINE=MEMORY
# invalid location
--error ER_BAD_PATH
BACKUP DATABASE adb TO '';
+--replace_column 2 #
+SHOW WARNINGS;
# don't overwrite existing files
--error ER_BACKUP_WRITE_LOC
BACKUP DATABASE adb TO "bdb/t1.frm";
+--replace_column 2 #
+SHOW WARNINGS;
--replace_column 1 #
BACKUP DATABASE adb TO "test.bak";
+--replace_column 2 #
+SHOW WARNINGS;
# don't overwrite existing backup image
--error ER_BACKUP_WRITE_LOC
BACKUP DATABASE adb TO "test.bak";
+--replace_column 2 #
+SHOW WARNINGS;
--remove_file $MYSQLTEST_VARDIR/master-data/test.bak
@@ -47,8 +55,11 @@ DROP DATABASE IF EXISTS bar;
-- error ER_BAD_DB_ERROR
BACKUP DATABASE foo TO 'test.bak';
+SHOW WARNINGS;
-- error ER_BAD_DB_ERROR
BACKUP DATABASE test,foo,bdb,bar TO 'test.bak';
+--replace_column 2 #
+SHOW WARNINGS;
# repeated database
-- error ER_NONUNIQ_DB
@@ -117,6 +128,8 @@ DROP DATABASE bdb;
--echo Backup of mysql, information_schema scenario 1
--error ER_BACKUP_CANNOT_INCLUDE_DB
BACKUP DATABASE mysql TO 't.bak';
+--replace_column 2 #
+SHOW WARNINGS;
--error 0, 1
--remove_file $MYSQLTEST_VARDIR/master-data/t.bak
@@ -125,6 +138,8 @@ BACKUP DATABASE mysql TO 't.bak';
--echo Backup of mysql, information_schema scenario 2
--error ER_BACKUP_CANNOT_INCLUDE_DB
BACKUP DATABASE information_schema TO 't.bak';
+--replace_column 2 #
+SHOW WARNINGS;
--error 0, 1
--remove_file $MYSQLTEST_VARDIR/master-data/t.bak
@@ -133,6 +148,8 @@ BACKUP DATABASE information_schema TO 't
--echo Backup of mysql, information_schema scenario 3
--error ER_BACKUP_CANNOT_INCLUDE_DB
BACKUP DATABASE mysql, information_schema TO 't.bak';
+--replace_column 2 #
+SHOW WARNINGS;
--error 0, 1
--remove_file $MYSQLTEST_VARDIR/master-data/t.bak
@@ -141,6 +158,8 @@ BACKUP DATABASE mysql, information_schem
--echo Backup of mysql, information_schema scenario 4
--error ER_BACKUP_CANNOT_INCLUDE_DB
BACKUP DATABASE mysql, test TO 't.bak';
+--replace_column 2 #
+SHOW WARNINGS;
--error 0, 1
--remove_file $MYSQLTEST_VARDIR/master-data/t.bak
@@ -149,6 +168,8 @@ BACKUP DATABASE mysql, test TO 't.bak';
--echo Backup of mysql, information_schema scenario 5
--error ER_BACKUP_CANNOT_INCLUDE_DB
BACKUP DATABASE information_schema, test TO 't.bak';
+--replace_column 2 #
+SHOW WARNINGS;
--error 0, 1
--remove_file $MYSQLTEST_VARDIR/master-data/t.bak
@@ -157,6 +178,8 @@ BACKUP DATABASE information_schema, test
--echo Backup of mysql, information_schema scenario 6
--error ER_BACKUP_CANNOT_INCLUDE_DB
BACKUP DATABASE mysql, information_schema, test TO 't.bak';
+--replace_column 2 #
+SHOW WARNINGS;
--error 0, 1
--remove_file $MYSQLTEST_VARDIR/master-data/t.bak
@@ -190,7 +213,7 @@ BACKUP DATABASE test_ob_error TO 'ob_err
--error 0,1
--remove_file $MYSQLTEST_VARDIR/master-data/ob_err.bak
--replace_column 2 #
-SHOW ERRORS;
+SHOW WARNINGS;
# Restore the table
--echo Restoring the table
@@ -207,7 +230,7 @@ BACKUP DATABASE test_ob_error TO 'ob_err
--error 0,1
--remove_file $MYSQLTEST_VARDIR/master-data/ob_err.bak
--replace_column 2 #
-SHOW ERRORS;
+SHOW WARNINGS;
# Restore the table
--echo Restoring the table
=== modified file 'mysql-test/suite/backup/t/backup_myisam1.test'
--- a/mysql-test/suite/backup/t/backup_myisam1.test 2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/t/backup_myisam1.test 2008-11-19 10:18:41 +0000
@@ -24,5 +24,7 @@ BACKUP DATABASE mysqltest TO 'test.ba';
# Cleanup from this test case
#
DROP DATABASE mysqltest;
+# Note: The backup file should not exist as BACKUP command failed.
+--error 1
--remove_file $MYSQLTEST_VARDIR/master-data/test.ba
=== modified file 'mysql-test/suite/backup/t/backup_views.test'
--- a/mysql-test/suite/backup/t/backup_views.test 2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/t/backup_views.test 2008-11-19 10:18:41 +0000
@@ -205,14 +205,14 @@ DROP DATABASE bup_db2;
--echo restore database with view dependency to other, non-existing db
---error ER_BACKUP_CANT_RESTORE_VIEW
+--error ER_NO_SUCH_TABLE
RESTORE FROM 'bup_objectview1.bak';
# An incomplete bup_db1 was created by the failing restore operation.
# Remove it before trying restore of bup_db2.
DROP DATABASE bup_db1;
---error ER_BACKUP_CANT_RESTORE_VIEW
+--error ER_NO_SUCH_TABLE
RESTORE FROM 'bup_objectview2.bak';
# An incomplete bup_db2 was created by the failing restore operation.
=== modified file 'sql/backup/backup_info.cc'
--- a/sql/backup/backup_info.cc 2008-11-05 09:41:15 +0000
+++ b/sql/backup/backup_info.cc 2008-11-19 10:18:41 +0000
@@ -87,11 +87,11 @@ Backup_info::find_backup_engine(const ba
// See if table has native backup engine
- storage_engine_ref se= get_storage_engine(m_ctx.m_thd, tbl);
+ storage_engine_ref se= get_storage_engine(m_thd, tbl);
if (!se)
{
- m_ctx.fatal_error(ER_NO_STORAGE_ENGINE, tbl.describe(buf));
+ m_log.report_error(ER_NO_STORAGE_ENGINE, tbl.describe(buf));
DBUG_RETURN(NULL);
}
@@ -126,7 +126,7 @@ Backup_info::find_backup_engine(const ba
if (!snap)
if (has_native_backup(se))
{
- Native_snapshot *nsnap= new Native_snapshot(m_ctx, se);
+ Native_snapshot *nsnap= new Native_snapshot(m_log, se);
/*
Check if the snapshot object is valid - in particular has successfully
@@ -175,7 +175,7 @@ Backup_info::find_backup_engine(const ba
}
if (!snap)
- m_ctx.fatal_error(ER_BACKUP_NO_BACKUP_DRIVER,tbl.describe(buf));
+ m_log.report_error(ER_BACKUP_NO_BACKUP_DRIVER,tbl.describe(buf));
DBUG_RETURN(snap);
}
@@ -295,13 +295,16 @@ Backup_info::Dep_node::get_key(const uch
/**
Create @c Backup_info instance and prepare it for populating with objects.
-
+
+ @param[in] log A logger used to report errors
+ @param[in] thd THD handle
+
Snapshots created by the built-in backup engines are added to @c snapshots
list to be used in the backup engine selection algorithm in
@c find_backup_engine().
*/
-Backup_info::Backup_info(Backup_restore_ctx &ctx)
- :m_ctx(ctx), m_state(Backup_info::ERROR), native_snapshots(8),
+Backup_info::Backup_info(backup::Logger &log, THD *thd)
+ :m_log(log), m_thd(thd), m_state(Backup_info::ERROR), native_snapshots(8),
m_dep_list(NULL), m_dep_end(NULL),
m_srout_end(NULL), m_view_end(NULL), m_trigger_end(NULL), m_event_end(NULL)
{
@@ -318,7 +321,7 @@ Backup_info::Backup_info(Backup_restore_
Dep_node::get_key, Dep_node::free, MYF(0)))
{
// Allocation failed. Error has been reported, but not logged to backup logs
- m_ctx.log_error(ER_OUT_OF_RESOURCES);
+ m_log.log_error(ER_OUT_OF_RESOURCES);
return;
}
@@ -328,10 +331,10 @@ Backup_info::Backup_info(Backup_restore_
element on that list, as a "catch all" entry.
*/
- snap= new Nodata_snapshot(m_ctx); // logs errors
+ snap= new Nodata_snapshot(m_log); // logs errors
if (!snap)
{
- m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ m_log.report_error(ER_OUT_OF_RESOURCES);
return;
}
@@ -341,14 +344,14 @@ Backup_info::Backup_info(Backup_restore_
if (snapshots.push_back(snap))
{
// Allocation failed. Error has been reported, but not logged to backup logs
- m_ctx.log_error(ER_OUT_OF_RESOURCES);
+ m_log.log_error(ER_OUT_OF_RESOURCES);
return;
}
- snap= new CS_snapshot(m_ctx); // logs errors
+ snap= new CS_snapshot(m_log); // logs errors
if (!snap)
{
- m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ m_log.report_error(ER_OUT_OF_RESOURCES);
return;
}
@@ -358,14 +361,14 @@ Backup_info::Backup_info(Backup_restore_
if (snapshots.push_back(snap))
{
// Allocation failed. Error has been reported, but not logged to backup logs
- m_ctx.log_error(ER_OUT_OF_RESOURCES);
+ m_log.log_error(ER_OUT_OF_RESOURCES);
return; // Error has been logged
}
- snap= new Default_snapshot(m_ctx); // logs errors
+ snap= new Default_snapshot(m_log); // logs errors
if (!snap)
{
- m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ m_log.report_error(ER_OUT_OF_RESOURCES);
return;
}
@@ -375,7 +378,7 @@ Backup_info::Backup_info(Backup_restore_
if (snapshots.push_back(snap))
{
// Allocation failed. Error has been reported, but not logged to backup logs
- m_ctx.log_error(ER_OUT_OF_RESOURCES);
+ m_log.log_error(ER_OUT_OF_RESOURCES);
return; // Error has been logged
}
@@ -417,7 +420,7 @@ int Backup_info::close()
// report backup drivers used in the image
for (ushort n=0; n < snap_count(); ++n)
- m_ctx.report_driver(m_snap[n]->name());
+ m_log.report_driver(m_snap[n]->name());
m_state= CLOSED;
return 0;
@@ -465,7 +468,7 @@ backup::Image_info::Ts* Backup_info::add
if (!ts)
{
- m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_TS, name);
+ m_log.report_error(ER_BACKUP_CATALOG_ADD_TS, name);
return NULL;
}
@@ -479,7 +482,7 @@ backup::Image_info::Ts* Backup_info::add
if (!n1)
{
- m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ m_log.report_error(ER_OUT_OF_RESOURCES);
return NULL;
}
@@ -513,7 +516,7 @@ backup::Image_info::Db* Backup_info::add
if (!db)
{
- m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_DB, name->ptr());
+ m_log.report_error(ER_BACKUP_CATALOG_ADD_DB, name->ptr());
return NULL;
}
@@ -550,7 +553,7 @@ int Backup_info::add_dbs(List< ::LEX_STR
if (is_internal_db_name(&db_name))
{
- m_ctx.fatal_error(ER_BACKUP_CANNOT_INCLUDE_DB, db_name.c_ptr());
+ m_log.report_error(ER_BACKUP_CANNOT_INCLUDE_DB, db_name.c_ptr());
goto error;
}
@@ -589,7 +592,7 @@ int Backup_info::add_dbs(List< ::LEX_STR
if (!unknown_dbs.is_empty())
{
- m_ctx.fatal_error(ER_BAD_DB_ERROR, unknown_dbs.c_ptr());
+ m_log.report_error(ER_BAD_DB_ERROR, unknown_dbs.c_ptr());
goto error;
}
@@ -614,11 +617,11 @@ int Backup_info::add_all_dbs()
using namespace obs;
int res= 0;
- Obj_iterator *dbit= get_databases(m_ctx.m_thd);
+ Obj_iterator *dbit= get_databases(m_thd);
if (!dbit)
{
- m_ctx.fatal_error(ER_BACKUP_LIST_DBS);
+ m_log.report_error(ER_BACKUP_LIST_DBS);
return ERROR;
}
@@ -701,11 +704,11 @@ int Backup_info::add_db_items(Db &db)
// Add tables.
- Obj_iterator *it= get_db_tables(m_ctx.m_thd, &db.name());
+ Obj_iterator *it= get_db_tables(m_thd, &db.name());
if (!it)
{
- m_ctx.fatal_error(ER_BACKUP_LIST_DB_TABLES, db.name().ptr());
+ m_log.report_error(ER_BACKUP_LIST_DB_TABLES, db.name().ptr());
return ERROR;
}
@@ -731,7 +734,7 @@ int Backup_info::add_db_items(Db &db)
// If this table uses a tablespace, add this tablespace to the catalogue.
- obj= get_tablespace_for_table(m_ctx.m_thd, &db.name(), &tbl->name());
+ obj= get_tablespace_for_table(m_thd, &db.name(), &tbl->name());
if (obj)
{
@@ -748,11 +751,11 @@ int Backup_info::add_db_items(Db &db)
// Add other objects.
delete it;
- it= get_db_stored_procedures(m_ctx.m_thd, &db.name());
+ it= get_db_stored_procedures(m_thd, &db.name());
if (!it)
{
- m_ctx.fatal_error(ER_BACKUP_LIST_DB_SROUT, db.name().ptr());
+ m_log.report_error(ER_BACKUP_LIST_DB_SROUT, db.name().ptr());
goto error;
}
@@ -760,11 +763,11 @@ int Backup_info::add_db_items(Db &db)
goto error;
delete it;
- it= get_db_stored_functions(m_ctx.m_thd, &db.name());
+ it= get_db_stored_functions(m_thd, &db.name());
if (!it)
{
- m_ctx.fatal_error(ER_BACKUP_LIST_DB_SROUT, db.name().ptr());
+ m_log.report_error(ER_BACKUP_LIST_DB_SROUT, db.name().ptr());
goto error;
}
@@ -772,11 +775,11 @@ int Backup_info::add_db_items(Db &db)
goto error;
delete it;
- it= get_db_views(m_ctx.m_thd, &db.name());
+ it= get_db_views(m_thd, &db.name());
if (!it)
{
- m_ctx.fatal_error(ER_BACKUP_LIST_DB_VIEWS, db.name().ptr());
+ m_log.report_error(ER_BACKUP_LIST_DB_VIEWS, db.name().ptr());
goto error;
}
@@ -784,11 +787,11 @@ int Backup_info::add_db_items(Db &db)
goto error;
delete it;
- it= get_db_events(m_ctx.m_thd, &db.name());
+ it= get_db_events(m_thd, &db.name());
if (!it)
{
- m_ctx.fatal_error(ER_BACKUP_LIST_DB_EVENTS, db.name().ptr());
+ m_log.report_error(ER_BACKUP_LIST_DB_EVENTS, db.name().ptr());
goto error;
}
@@ -796,11 +799,11 @@ int Backup_info::add_db_items(Db &db)
goto error;
delete it;
- it= get_db_triggers(m_ctx.m_thd, &db.name());
+ it= get_db_triggers(m_thd, &db.name());
if (!it)
{
- m_ctx.fatal_error(ER_BACKUP_LIST_DB_TRIGGERS, db.name().ptr());
+ m_log.report_error(ER_BACKUP_LIST_DB_TRIGGERS, db.name().ptr());
goto error;
}
@@ -808,11 +811,11 @@ int Backup_info::add_db_items(Db &db)
goto error;
delete it;
- it= get_all_db_grants(m_ctx.m_thd, &db.name());
+ it= get_all_db_grants(m_thd, &db.name());
if (!it)
{
- m_ctx.fatal_error(ER_BACKUP_LIST_DB_PRIV, db.name().ptr());
+ m_log.report_error(ER_BACKUP_LIST_DB_PRIV, db.name().ptr());
goto error;
}
@@ -889,8 +892,8 @@ backup::Image_info::Table* Backup_info::
if (!tbl)
{
- m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_TABLE,
- dbi.name().ptr(), t.name().ptr());
+ m_log.report_error(ER_BACKUP_CATALOG_ADD_TABLE,
+ dbi.name().ptr(), t.name().ptr());
return NULL;
}
@@ -943,7 +946,7 @@ int Backup_info::add_view_deps(obs::Obj
// Get an iterator to iterate over base views of the given one.
- obs::Obj_iterator *it= obs::get_view_base_views(m_ctx.m_thd, db_name, name);
+ obs::Obj_iterator *it= obs::get_view_base_views(m_thd, db_name, name);
if (!it)
return ERROR;
@@ -1086,7 +1089,7 @@ Backup_info::add_db_object(Db &db, const
if (res == get_dep_node_res::ERROR)
{
- m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
+ m_log.report_error(error, db.name().ptr(), name->ptr());
return NULL;
}
@@ -1101,7 +1104,7 @@ Backup_info::add_db_object(Db &db, const
if (type == BSTREAM_IT_VIEW)
if (add_view_deps(*obj))
{
- m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
+ m_log.report_error(error, db.name().ptr(), name->ptr());
return NULL;
}
@@ -1122,7 +1125,7 @@ Backup_info::add_db_object(Db &db, const
if (!o)
{
- m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
+ m_log.report_error(error, db.name().ptr(), name->ptr());
return NULL;
}
@@ -1342,7 +1345,7 @@ int Backup_info::Global_iterator::init()
if (!m_it)
{
const Backup_info* info= static_cast<const Backup_info*>(&m_info);
- return info->m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ return info->m_log.report_error(ER_OUT_OF_RESOURCES);
}
next(); // Never errors
@@ -1388,7 +1391,7 @@ Backup_info::Global_iterator::next()
if (!m_it)
{
const Backup_info* info= static_cast<const Backup_info*>(&m_info);
- info->m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ info->m_log.report_error(ER_OUT_OF_RESOURCES);
mode= DONE;
return FALSE;
}
@@ -1471,7 +1474,7 @@ backup::Image_info::Iterator* Backup_inf
Global_iterator* it = new Global_iterator(*this);
if (it == NULL)
{
- m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ m_log.report_error(ER_OUT_OF_RESOURCES);
return NULL;
}
if (it->init()) // Error has been logged
@@ -1488,7 +1491,7 @@ backup::Image_info::Iterator* Backup_inf
Perdb_iterator* it = new Perdb_iterator(*this);
if (it == NULL)
{
- m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ m_log.report_error(ER_OUT_OF_RESOURCES);
return NULL;
}
if (it->init()) // Error has been logged
=== modified file 'sql/backup/backup_info.h'
--- a/sql/backup/backup_info.h 2008-10-27 13:06:21 +0000
+++ b/sql/backup/backup_info.h 2008-11-19 10:18:41 +0000
@@ -31,9 +31,8 @@ class Backup_info: public backup::Image_
{
public:
- Backup_restore_ctx &m_ctx;
+ backup::Logger &m_log;
- Backup_info(Backup_restore_ctx&);
~Backup_info();
bool is_valid();
@@ -48,6 +47,14 @@ class Backup_info: public backup::Image_
private:
+ /*
+ Note: constructor is private because instances of this class are supposed
+ to be created only with Backup_restore_ctx::prepare_for_backup() method.
+ */
+ Backup_info(backup::Logger&, THD*);
+
+ THD *m_thd;
+
class Global_iterator; ///< Iterates over global items (for which meta-data is
stored).
class Perdb_iterator; ///< Iterates over all per-database objects (except tables).
@@ -165,6 +172,7 @@ class Backup_info: public backup::Image_
friend int ::bcat_get_item_create_query(st_bstream_image_header *catalogue,
struct st_bstream_item_info *item,
bstream_blob *stmt);
+ friend class Backup_restore_ctx;
};
/// Check if instance is correctly created.
=== modified file 'sql/backup/backup_kernel.h'
--- a/sql/backup/backup_kernel.h 2008-10-30 17:53:24 +0000
+++ b/sql/backup/backup_kernel.h 2008-11-19 10:18:41 +0000
@@ -75,8 +75,6 @@ class Backup_restore_ctx: public backup:
int do_backup();
int do_restore();
- int fatal_error(int, ...);
- int log_error(int, ...);
int close();
@@ -98,7 +96,8 @@ class Backup_restore_ctx: public backup:
/**
@brief State of a context object.
- Backup/restore can be performed only if object is prepared for that operation.
+ Backup/restore can be performed only if object is prepared for that
+ operation.
*/
enum { CREATED,
PREPARED_FOR_BACKUP,
@@ -107,10 +106,22 @@ class Backup_restore_ctx: public backup:
ulonglong m_thd_options; ///< For saving thd->options.
/**
- If backup/restore was interrupted by an error, this member stores the error
- number.
- */
+ @brief Tells if context object is in error state.
+
+ In case of fatal error, the context object is put into an error state
+ by setting @m_error to non-zero value. This can be the code of
+ the detected error but currently the exact value is not used.
+
+ When in error state, public methods of Backup_restore_ctx do not try
+ to perform their operations but report an error instead. @c Is_valid()
+ will return FALSE for an object in error state.
+
+ @note The error state is an internal state of the context object. The
+ object can enter this state only as a result of executing one of its
+ methods.
+ */
int m_error;
+ int fatal_error(int);
::String m_path; ///< Path to where the backup image file is located.
@@ -145,8 +156,6 @@ class Backup_restore_ctx: public backup:
int report_stream_open_failure(int open_error, const LEX_STRING *location);
- friend class Backup_info;
- friend class Restore_info;
friend int backup_init();
friend void backup_shutdown();
friend bstream_byte* bstream_alloc(unsigned long int);
@@ -175,32 +184,31 @@ void Backup_restore_ctx::disable_fkey_co
}
/**
- Report error and move context object into error state.
+ Move context object into error state.
After this method is called the context object is in error state and
- cannot be normally used. It still can be examined for saved error messages.
- The code of the error reported here is saved in m_error member.
+ cannot be normally used. The provided error code is saved in m_error
+ member.
Only one fatal error can be reported. If context is already in error
state when this method is called, it does nothing.
+
+ @note Context object should enter error state only as a result of executing
+ one of its methods. Thus this private helper method is intended to be used
+ only from within Backup_restore_ctx class.
@return error code given as input or stored in the context object if
- a fatal error was reported before.
+ it is already in error state.
*/
inline
-int Backup_restore_ctx::fatal_error(int error_code, ...)
+int Backup_restore_ctx::fatal_error(int error_code)
{
+ m_remove_loc= TRUE;
+
if (m_error)
return m_error;
- va_list args;
-
m_error= error_code;
- m_remove_loc= TRUE;
-
- va_start(args,error_code);
- v_report_error(backup::log_level::ERROR, error_code, args);
- va_end(args);
return error_code;
}
=== modified file 'sql/backup/data_backup.cc'
--- a/sql/backup/data_backup.cc 2008-10-30 20:02:15 +0000
+++ b/sql/backup/data_backup.cc 2008-11-19 10:18:41 +0000
@@ -248,7 +248,7 @@ class Scheduler
private:
LIST *m_pumps, *m_last;
- Logger *m_log; ///< used to report errors if not NULL
+ Logger &m_log; ///< for reporting errors
uint m_count; ///< current number of pumps
size_t m_total; ///< accumulated position of all drivers
size_t m_init_left; ///< how much of init data is left (estimate)
@@ -256,7 +256,7 @@ class Scheduler
Output_stream &m_str; ///< stream to which we write
bool cancelled; ///< true if backup process was cancelled
- Scheduler(Output_stream &s, Logger *log)
+ Scheduler(Output_stream &s, Logger &log)
:init_count(0), prepare_count(0), finish_count(0),
m_pumps(NULL), m_last(NULL), m_log(log),
m_count(0), m_total(0), m_init_left(0), m_known_count(0),
@@ -427,7 +427,8 @@ int write_table_data(THD* thd, Backup_in
if (info.snap_count() == 0 || info.table_count() == 0) // nothing to backup
DBUG_RETURN(0);
- Scheduler sch(s, &info.m_ctx); // scheduler instance
+ Logger &log= info.m_log;
+ Scheduler sch(s, log); // scheduler instance
List<Scheduler::Pump> inactive; // list of images not yet being created
// keeps maximal init size for images in inactive list
@@ -448,9 +449,15 @@ int write_table_data(THD* thd, Backup_in
Scheduler::Pump *p= new Scheduler::Pump(*i, s);
- if (!p || !p->is_valid())
+ if (!p)
{
- info.m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ log.report_error(ER_OUT_OF_RESOURCES);
+ goto error;
+ }
+ if (!p->is_valid())
+ {
+ log.report_error(ER_BACKUP_CREATE_BACKUP_DRIVER,p->m_name);
+ delete p;
goto error;
}
@@ -458,7 +465,7 @@ int write_table_data(THD* thd, Backup_in
if (init_size == Driver::UNKNOWN_SIZE)
{
- if (sch.add(p))
+ if (sch.add(p)) // logs errors
goto error;
}
else
@@ -471,7 +478,7 @@ int write_table_data(THD* thd, Backup_in
/* Allocation failed.
Error has been reported, but not logged to backup logs.
*/
- info.m_ctx.log_error(ER_OUT_OF_RESOURCES);
+ log.log_error(ER_OUT_OF_RESOURCES);
goto error;
}
}
@@ -529,7 +536,7 @@ int write_table_data(THD* thd, Backup_in
// poll drivers
- if (sch.step())
+ if (sch.step()) // logs errors
goto error;
}
@@ -569,9 +576,12 @@ int write_table_data(THD* thd, Backup_in
int error= 0;
error= block_commits(thd, NULL);
if (error)
+ {
+ log.report_error(ER_BACKUP_VP_FAILED);
goto error;
+ }
- if (sch.prepare())
+ if (sch.prepare()) // logs errors
goto error;
while (sch.prepare_count > 0)
@@ -584,7 +594,7 @@ int write_table_data(THD* thd, Backup_in
LOG_INFO binlog_pos;
- info.m_ctx.report_state(BUP_VALIDITY_POINT);
+ log.report_state(BUP_VALIDITY_POINT);
/*
This breakpoint is used to assist in testing state changes for
the backup progress. It is not to be used to indicate actual
@@ -597,7 +607,7 @@ int write_table_data(THD* thd, Backup_in
*/
DEBUG_SYNC(thd, "before_backup_data_lock");
- if (sch.lock())
+ if (sch.lock()) // logs errors
goto error;
/*
@@ -606,7 +616,7 @@ int write_table_data(THD* thd, Backup_in
if (mysql_bin_log.is_open())
if (mysql_bin_log.get_current_log(&binlog_pos))
{
- info.m_ctx.fatal_error(ER_BACKUP_BINLOG);
+ log.report_error(ER_BACKUP_BINLOG);
goto error;
}
@@ -629,7 +639,7 @@ int write_table_data(THD* thd, Backup_in
vp_time= my_time(0);
DEBUG_SYNC(thd, "before_backup_data_unlock");
- if (sch.unlock())
+ if (sch.unlock()) // logs errors
goto error;
/*
@@ -638,17 +648,20 @@ int write_table_data(THD* thd, Backup_in
DEBUG_SYNC(thd, "before_backup_unblock_commit");
error= unblock_commits(thd);
if (error)
+ {
+ log.report_error(ER_BACKUP_VP_FAILED);
goto error;
+ }
// Report and save information about VP
info.save_vp_time(vp_time);
- info.m_ctx.report_vp_time(vp_time, TRUE); // TRUE = also write to progress log
+ log.report_vp_time(vp_time, TRUE); // TRUE = also write to progress log
if (mysql_bin_log.is_open())
{
info.save_binlog_pos(binlog_pos);
- info.m_ctx.report_binlog_pos(info.binlog_pos);
+ log.report_binlog_pos(info.binlog_pos);
}
/*
@@ -656,9 +669,10 @@ int write_table_data(THD* thd, Backup_in
write it to the log.
*/
if (obs::is_slave() && master_pos.pos)
- info.m_ctx.report_master_binlog_pos(master_pos);
+ log.report_master_binlog_pos(master_pos);
+
+ log.report_state(BUP_RUNNING);
- info.m_ctx.report_state(BUP_RUNNING);
DEBUG_SYNC(thd, "after_backup_binlog");
/**** VP creation (end) ********************************************/
@@ -819,9 +833,6 @@ int Scheduler::step()
case backup_state::ERROR:
remove_pump(p); // Note: never errors.
- if (res)
- cancel_backup(); // we hit an error - bail out
- // Note: cancel_backup() never errors.
break;
default: break;
@@ -846,11 +857,14 @@ int Scheduler::add(Pump *p)
if (!p) // no pump to add
return 0;
- p->set_logger(m_log);
+ p->set_logger(&m_log);
p->start_pos= avg;
- if (p->begin())
- goto error;
+ if (p->begin()) // logs errors
+ {
+ delete p;
+ return ERROR;
+ }
// in case of error, above call should return non-zero code (and report error)
DBUG_ASSERT(p->state != backup_state::ERROR);
@@ -894,12 +908,6 @@ int Scheduler::add(Pump *p)
(unsigned long)m_init_left));
return 0;
-
- error:
-
- delete p;
- cancel_backup();
- return ERROR;
}
/// Move backup pump to the end of scheduler's list.
@@ -971,9 +979,9 @@ int Scheduler::prepare()
for (Pump_iterator it(*this); it; ++it)
{
- if (it->prepare())
+ if (it->prepare()) // logs errors
{
- cancel_backup(); // Note: never errors.
+ remove_pump(it); // Note: never errors.
return ERROR;
}
if (it->state == backup_state::PREPARING)
@@ -994,9 +1002,9 @@ int Scheduler::lock()
DBUG_PRINT("backup_data",("calling lock() for all drivers"));
for (Pump_iterator it(*this); it; ++it)
- if (it->lock())
+ if (it->lock()) // logs errors
{
- cancel_backup(); // Note: never errors.
+ remove_pump(it); // Note: never errors.
return ERROR;
}
@@ -1013,9 +1021,9 @@ int Scheduler::unlock()
for(Pump_iterator it(*this); it; ++it)
{
- if (it->unlock())
+ if (it->unlock()) // logs errors
{
- cancel_backup(); // Note: never errors.
+ remove_pump(it); // Note: never errors.
return ERROR;
}
if (it->state == backup_state::FINISHING)
@@ -1072,9 +1080,7 @@ int Backup_pump::begin()
if (ERROR == m_drv->begin(m_bw.buf_size))
{
state= backup_state::ERROR;
- // We check if logger is always setup. Later the assertion can
- // be replaced with "if (m_log)"
- DBUG_ASSERT(m_log);
+ if (m_log)
m_log->report_error(ER_BACKUP_INIT_BACKUP_DRIVER, m_name);
return ERROR;
}
@@ -1092,7 +1098,7 @@ int Backup_pump::end()
if (ERROR == m_drv->end())
{
state= backup_state::ERROR;
- DBUG_ASSERT(m_log);
+ if (m_log)
m_log->report_error(ER_BACKUP_STOP_BACKUP_DRIVER, m_name);
return ERROR;
}
@@ -1121,9 +1127,9 @@ int Backup_pump::prepare()
case ERROR:
default:
state= backup_state::ERROR;
- DBUG_ASSERT(m_log);
+ if (m_log)
m_log->report_error(ER_BACKUP_PREPARE_DRIVER, m_name);
- return ERROR;
+ return ERROR;
}
DBUG_PRINT("backup_data",(" preparing %s, goes to %s state",
@@ -1138,7 +1144,7 @@ int Backup_pump::lock()
if (ERROR == m_drv->lock())
{
state= backup_state::ERROR;
- DBUG_ASSERT(m_log);
+ if (m_log)
m_log->report_error(ER_BACKUP_CREATE_VP, m_name);
return ERROR;
}
@@ -1154,7 +1160,7 @@ int Backup_pump::unlock()
if (ERROR == m_drv->unlock())
{
state= backup_state::ERROR;
- DBUG_ASSERT(m_log);
+ if (m_log)
m_log->report_error(ER_BACKUP_UNLOCK_DRIVER, m_name);
return ERROR;
}
@@ -1167,7 +1173,7 @@ int Backup_pump::cancel()
if (ERROR == m_drv->cancel())
{
state= backup_state::ERROR;
- DBUG_ASSERT(m_log);
+ if (m_log)
m_log->report_error(ER_BACKUP_CANCEL_BACKUP, m_name);
return ERROR;
}
@@ -1248,7 +1254,7 @@ int Backup_pump::pump(size_t *howmuch)
case Block_writer::ERROR:
default:
- DBUG_ASSERT(m_log);
+ if (m_log)
m_log->report_error(ER_BACKUP_GET_BUF);
state= backup_state::ERROR;
return ERROR;
@@ -1293,7 +1299,7 @@ int Backup_pump::pump(size_t *howmuch)
case ERROR:
default:
- DBUG_ASSERT(m_log);
+ if (m_log)
m_log->report_error(ER_BACKUP_GET_DATA, m_name);
state= backup_state::ERROR;
return ERROR;
@@ -1328,7 +1334,7 @@ int Backup_pump::pump(size_t *howmuch)
case Block_writer::ERROR:
- DBUG_ASSERT(m_log);
+ if (m_log)
m_log->report_error(ER_BACKUP_WRITE_DATA, m_name, m_buf.table_num);
state= backup_state::ERROR;
return ERROR;
@@ -1371,11 +1377,26 @@ int restore_table_data(THD *thd, Restore
if (info.snap_count() == 0 || info.table_count() == 0) // nothing to restore
DBUG_RETURN(0);
- Restore_driver* drv[256];
+ Logger &log= info.m_log;
+
+ /* Drv[n] points at restore driver used to process snapshot n. */
+ Restore_driver* drv[MAX_SNAP_COUNT];
+ /*
+ Active[n] is not NULL if driver drv[n] has been activated. Such driver needs
+ an end() or cancel() call to shut it down properly.
+ */
+ Restore_driver* active[MAX_SNAP_COUNT];
+ /*
+ Bad_drivers string for holding comma separated list of drivers which
+ signalled errors during shutdown. If non-empty, an error will be logged
+ at the end of the function (finish: label).
+ */
+ String bad_drivers;
- if (info.snap_count() > 256)
+ if (info.snap_count() > MAX_SNAP_COUNT)
{
- info.m_ctx.fatal_error(ER_BACKUP_TOO_MANY_IMAGES, info.snap_count(), 256);
+ log.report_error(ER_BACKUP_TOO_MANY_IMAGES,
+ info.snap_count(), MAX_SNAP_COUNT);
DBUG_RETURN(ERROR);
}
@@ -1384,7 +1405,7 @@ int restore_table_data(THD *thd, Restore
for (uint n=0; n < info.snap_count(); ++n)
{
- drv[n]= NULL;
+ active[n]= drv[n]= NULL;
Snapshot_info *snap= info.m_snap[n];
@@ -1395,7 +1416,7 @@ int restore_table_data(THD *thd, Restore
res= snap->get_restore_driver(drv[n]);
if (res == backup::ERROR)
{
- info.m_ctx.fatal_error(ER_BACKUP_CREATE_RESTORE_DRIVER, snap->name());
+ log.report_error(ER_BACKUP_CREATE_RESTORE_DRIVER, snap->name());
goto error;
};
}
@@ -1406,9 +1427,11 @@ int restore_table_data(THD *thd, Restore
res= drv[n]->begin(0);
if (res == backup::ERROR)
{
- info.m_ctx.fatal_error(ER_BACKUP_INIT_RESTORE_DRIVER, info.m_snap[n]->name());
+ log.report_error(ER_BACKUP_INIT_RESTORE_DRIVER, info.m_snap[n]->name());
goto error;
}
+
+ active[n]= drv[n];
}
DEBUG_SYNC(thd, "restore_in_progress");
@@ -1449,9 +1472,8 @@ int restore_table_data(THD *thd, Restore
break;
case BSTREAM_ERROR:
- info.m_ctx.fatal_error(ER_BACKUP_READ_DATA);
+ log.report_error(ER_BACKUP_READ_DATA);
default:
- state= ERROR;
goto error;
}
@@ -1491,7 +1513,8 @@ int restore_table_data(THD *thd, Restore
*/
DBUG_ASSERT(snap && drvr);
- switch( drvr->send_data(buf) ) {
+ ret= drvr->send_data(buf);
+ switch (ret) {
case backup::OK:
info.data_size += buf.size;
@@ -1504,8 +1527,13 @@ int restore_table_data(THD *thd, Restore
case backup::ERROR:
if( errors > MAX_ERRORS )
{
- info.m_ctx.fatal_error(ER_BACKUP_SEND_DATA, buf.table_num, snap->name());
- state= ERROR;
+ log.report_error(ER_BACKUP_SEND_DATA, buf.table_num, snap->name());
+ /*
+ If driver signals error then it is not active any longer - neither
+ ->end() nor ->cancel() should be called on it, only ->free().
+ This is why we need to remove it from active[] array.
+ */
+ active[snap_num]= NULL;
goto error;
}
errors++;
@@ -1516,8 +1544,7 @@ int restore_table_data(THD *thd, Restore
default:
if( repeats > MAX_REPEATS )
{
- info.m_ctx.fatal_error(ER_BACKUP_SEND_DATA_RETRY, repeats, snap->name());
- state= ERROR;
+ log.report_error(ER_BACKUP_SEND_DATA_RETRY, repeats, snap->name());
goto error;
}
repeats++;
@@ -1526,7 +1553,7 @@ int restore_table_data(THD *thd, Restore
default:
break;
- } // switch(state)
+ } // switch(ret)
} // main reading loop
@@ -1536,49 +1563,69 @@ int restore_table_data(THD *thd, Restore
}
DEBUG_SYNC(::current_thd, "restore_table_data_before_end");
-
- { // Shutting down drivers
- String bad_drivers;
+ // Call end() for all active drivers.
- for (uint n=0; n < info.snap_count(); ++n)
- {
- if (!drv[n])
- continue;
+ for (uint n=0; n < info.snap_count(); ++n)
+ {
+ if (!active[n])
+ continue;
- DBUG_PRINT("restore",("Shutting down restore driver %s",
- info.m_snap[n]->name()));
- res= drv[n]->end();
- if (res == backup::ERROR)
- {
- state= ERROR;
+ DBUG_PRINT("restore",("Shutting down restore driver %s",
+ info.m_snap[n]->name()));
+ res= active[n]->end();
+ if (res == backup::ERROR)
+ {
+ state= ERROR;
- if (!bad_drivers.is_empty())
- bad_drivers.append(",");
- bad_drivers.append(info.m_snap[n]->name());
- }
- drv[n]->free(); // Never errors
+ if (!bad_drivers.is_empty())
+ bad_drivers.append(",");
+ bad_drivers.append(info.m_snap[n]->name());
}
-
- if (!bad_drivers.is_empty())
- info.m_ctx.report_error(ER_BACKUP_STOP_RESTORE_DRIVERS, bad_drivers.c_ptr());
}
- DBUG_RETURN(state == ERROR ? backup::ERROR : 0);
+ goto finish;
- error:
+error:
+
+ state= ERROR;
DBUG_PRINT("restore",("Cancelling restore process"));
+ // Call cancel() for all active drivers
+
for (uint n=0; n < info.snap_count(); ++n)
{
- if (!drv[n])
+ if (!active[n])
continue;
+ DBUG_PRINT("restore",("Cancelling restore driver %s",
+ info.m_snap[n]->name()));
+ res= active[n]->cancel();
+
+ if (res)
+ {
+ if (!bad_drivers.is_empty())
+ bad_drivers.append(",");
+ bad_drivers.append(info.m_snap[n]->name());
+ }
+ }
+
+finish:
+
+ if (!bad_drivers.is_empty())
+ log.report_error(ER_BACKUP_STOP_RESTORE_DRIVERS, bad_drivers.c_ptr());
+
+ // Call free() for all existing drivers
+
+ for (uint n=0; n < info.snap_count(); ++n)
+ {
+ if (!drv[n])
+ continue;
drv[n]->free(); // Never errors
}
- DBUG_RETURN(backup::ERROR);
+ DBUG_RETURN(state == ERROR ? backup::ERROR : 0);
}
=== modified file 'sql/backup/image_info.cc'
--- a/sql/backup/image_info.cc 2008-11-05 09:41:15 +0000
+++ b/sql/backup/image_info.cc 2008-11-19 10:18:41 +0000
@@ -169,8 +169,7 @@ int Image_info::add_snapshot(Snapshot_in
{
uint num= st_bstream_image_header::snap_count++;
- // The limit of 256 snapshots is imposed by backup stream format.
- if (num > 256)
+ if (num > MAX_SNAP_COUNT)
return -1;
m_snap[num]= &snap;
=== modified file 'sql/backup/image_info.h'
--- a/sql/backup/image_info.h 2008-11-05 09:41:15 +0000
+++ b/sql/backup/image_info.h 2008-11-19 10:18:41 +0000
@@ -10,6 +10,16 @@
#include <backup_stream.h> // for st_bstream_* types
#include <backup/backup_aux.h> // for Map template
+/**
+ @brief The maximal number of table data snapshots per backup image.
+
+ @note This limit is determined by the backup image format used and can
+ not be changed. Currently we use version 1 of the image format in which
+ one byte is used to store snapshot numbers, hence the limit is 256.
+*/
+#define MAX_SNAP_COUNT 256
+
+
class Backup_restore_ctx;
namespace backup {
@@ -101,12 +111,8 @@ public: // public interface
/**
Pointers to @c Snapshot_info objects corresponding to the snapshots
present in the image.
-
- We can have at most 256 different snapshots which is a limitation imposed
- by the backup stream library (the number of snapshots is stored inside
- backup image using one byte field).
*/
- Snapshot_info *m_snap[256];
+ Snapshot_info *m_snap[MAX_SNAP_COUNT];
// save timing & binlog info
=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc 2008-10-30 20:02:15 +0000
+++ b/sql/backup/kernel.cc 2008-11-19 10:18:41 +0000
@@ -154,11 +154,8 @@ execute_backup_command(THD *thd, LEX *le
folders in the path could have been moved, deleted, etc.
*/
if (backupdir->length() && my_access(backupdir->c_ptr(), (F_OK|W_OK)))
- {
- context.fatal_error(ER_BACKUP_BACKUPDIR, backupdir->c_ptr());
DBUG_RETURN(send_error(context, ER_BACKUP_BACKUPDIR, backupdir->c_ptr()));
- }
-
+
switch (lex->sql_command) {
case SQLCOM_BACKUP:
@@ -195,7 +192,7 @@ execute_backup_command(THD *thd, LEX *le
if (info->db_count() == 0)
{
- context.fatal_error(ER_BACKUP_NOTHING_TO_BACKUP);
+ context.report_error(ER_BACKUP_NOTHING_TO_BACKUP);
DBUG_RETURN(send_error(context, ER_BACKUP_NOTHING_TO_BACKUP));
}
@@ -254,23 +251,21 @@ execute_backup_command(THD *thd, LEX *le
}
/**
- Report errors.
+ Sends error notification after failed backup/restore operation.
- Current implementation reports the last error saved in the logger if it exist.
- Otherwise it reports error given by @c error_code.
+ @param[in] ctx The context of the backup/restore operation.
+ @param[in] error_code Error to be reported if no errors reported yet.
- @returns 0 on success, error code otherwise.
- */
-int send_error(Backup_restore_ctx &log, int error_code, ...)
+ If an error has been already reported then nothing is done - the first
+ logged error will be send to the client. Otherwise, if no errors were
+ reported yet, the given error is sent to the client (but not reported).
+
+ @returns The error code given as argument.
+*/
+static
+int send_error(Backup_restore_ctx &context, int error_code, ...)
{
- util::SAVED_MYSQL_ERROR *error= log.last_saved_error();
-
- if (error && !util::report_mysql_error(log.thd(), error, error_code))
- {
- if (error->code)
- error_code= error->code;
- }
- else // there are no error information in the logger - report error_code
+ if (!context.error_reported())
{
char buf[ERRMSGSIZE + 20];
va_list args;
@@ -282,8 +277,8 @@ int send_error(Backup_restore_ctx &log,
va_end(args);
}
- if (log.backup::Logger::m_state == backup::Logger::RUNNING)
- log.report_stop(my_time(0), FALSE); // FASLE = no success
+ if (context.backup::Logger::m_state == backup::Logger::RUNNING)
+ context.report_stop(my_time(0), FALSE); // FASLE = no success
return error_code;
}
@@ -294,6 +289,8 @@ int send_error(Backup_restore_ctx &log,
Currently the id of the operation is returned to the client. It can
be used to select correct entries from the backup progress tables.
+ @note If an error has been reported, send_error() is invoked instead.
+
@returns 0 on success, error code otherwise.
*/
int send_reply(Backup_restore_ctx &context)
@@ -304,6 +301,9 @@ int send_reply(Backup_restore_ctx &conte
DBUG_ENTER("send_reply");
+ if (context.error_reported())
+ return send_error(context, ER_UNKNOWN_ERROR);
+
/*
Send field list.
*/
@@ -335,9 +335,9 @@ int send_reply(Backup_restore_ctx &conte
DBUG_RETURN(0);
err:
- DBUG_RETURN(context.fatal_error(ER_BACKUP_SEND_REPLY,
- context.m_type == backup::Logger::BACKUP
- ? "BACKUP" : "RESTORE"));
+ DBUG_RETURN(context.report_error(ER_BACKUP_SEND_REPLY,
+ context.m_type == backup::Logger::BACKUP
+ ? "BACKUP" : "RESTORE"));
}
@@ -496,22 +496,17 @@ int Backup_restore_ctx::prepare(String *
if (m_error)
return m_error;
- // Prepare error reporting context.
-
- mysql_reset_errors(m_thd, 0); // Never errors
- m_thd->no_warnings_for_error= FALSE;
-
- save_errors(); // Never errors
-
+ int ret= 0;
/*
Check access for SUPER rights. If user does not have SUPER, fail with error.
+
+ In case of error, we write only to backup logs, because check_global_access()
+ pushes the same error on the error stack.
*/
- if (check_global_access(m_thd, SUPER_ACL))
- {
- fatal_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, "SUPER");
- return m_error;
- }
+ ret= check_global_access(m_thd, SUPER_ACL);
+ if (ret)
+ return fatal_error(log_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, "SUPER"));
/*
Check if another BACKUP/RESTORE is running and if not, register
@@ -528,7 +523,10 @@ int Backup_restore_ctx::prepare(String *
pthread_mutex_unlock(&run_lock);
if (m_error)
+ {
+ report_error(ER_BACKUP_RUNNING);
return m_error;
+ }
// check if location is valid (we assume it is a file path)
@@ -550,10 +548,7 @@ int Backup_restore_ctx::prepare(String *
#endif
if (bad_filename)
- {
- fatal_error(ER_BAD_PATH, location.str);
- return m_error;
- }
+ return fatal_error(report_error(ER_BAD_PATH, location.str));
/*
Computer full path to backup file.
@@ -568,18 +563,13 @@ int Backup_restore_ctx::prepare(String *
mem_alloc= new Mem_allocator();
if (!mem_alloc)
- {
- fatal_error(ER_OUT_OF_RESOURCES);
- return m_error;
- }
+ return fatal_error(report_error(ER_OUT_OF_RESOURCES));
// Freeze all meta-data.
- if (obs::ddl_blocker_enable(m_thd))
- {
- fatal_error(ER_DDL_BLOCK);
- return m_error;
- }
+ ret= obs::ddl_blocker_enable(m_thd);
+ if (ret)
+ return fatal_error(report_error(ER_DDL_BLOCK));
return 0;
}
@@ -613,7 +603,7 @@ Backup_restore_ctx::prepare_for_backup(S
if (m_error)
return NULL;
- if (Logger::init(BACKUP, query))
+ if (Logger::init(BACKUP, query)) // Logs errors
{
fatal_error(ER_BACKUP_LOGGER_INIT);
return NULL;
@@ -639,10 +629,13 @@ Backup_restore_ctx::prepare_for_backup(S
if (!s)
{
- fatal_error(ER_OUT_OF_RESOURCES);
+ fatal_error(report_error(ER_OUT_OF_RESOURCES));
return NULL;
}
-
+
+ // Mark that the file should be removed unless operation completes successfuly
+ m_remove_loc= TRUE;
+
int my_open_status= s->open();
if (my_open_status != 0)
{
@@ -654,16 +647,20 @@ Backup_restore_ctx::prepare_for_backup(S
Create backup catalogue.
*/
- Backup_info *info= new Backup_info(*this); // Logs errors
+ Backup_info *info= new Backup_info(*this, m_thd); // Logs errors
if (!info)
{
- fatal_error(ER_OUT_OF_RESOURCES);
+ fatal_error(report_error(ER_OUT_OF_RESOURCES));
return NULL;
}
if (!info->is_valid())
- return NULL; // Error has been logged by Backup_Info constructor
+ {
+ // Error has been logged by Backup_info constructor
+ fatal_error(ER_BACKUP_BACKUP_PREPARE);
+ return NULL;
+ }
/*
If binlog is enabled, set BSTREAM_FLAG_BINLOG in the header to indicate
@@ -734,7 +731,7 @@ Backup_restore_ctx::prepare_for_restore(
if (!s)
{
- fatal_error(ER_OUT_OF_RESOURCES);
+ fatal_error(report_error(ER_OUT_OF_RESOURCES));
return NULL;
}
@@ -749,45 +746,57 @@ Backup_restore_ctx::prepare_for_restore(
Create restore catalogue.
*/
- Restore_info *info= new Restore_info(*this); // reports errors
+ Restore_info *info= new Restore_info(*this, m_thd); // reports errors
if (!info)
{
- fatal_error(ER_OUT_OF_RESOURCES);
+ fatal_error(report_error(ER_OUT_OF_RESOURCES));
return NULL;
}
if (!info->is_valid())
+ {
+ // Errors are logged by Restore_info constructor.
+ fatal_error(ER_BACKUP_RESTORE_PREPARE);
return NULL;
+ }
info->save_start_time(when);
m_catalog= info;
+ int ret;
+
/*
- Read catalogue from the input stream.
+ Read header and catalogue from the input stream.
*/
- if (read_header(*info, *s))
+ ret= read_header(*info, *s); // Can log errors via callback functions.
+ if (ret)
{
- fatal_error(ER_BACKUP_READ_HEADER);
+ if (!error_reported())
+ report_error(ER_BACKUP_READ_HEADER);
+ fatal_error(ret);
return NULL;
}
if (s->next_chunk() != BSTREAM_OK)
{
- fatal_error(ER_BACKUP_NEXT_CHUNK);
+ fatal_error(report_error(ER_BACKUP_NEXT_CHUNK));
return NULL;
}
- if (read_catalog(*info, *s))
+ ret= read_catalog(*info, *s); // Can log errors via callback functions.
+ if (ret)
{
- fatal_error(ER_BACKUP_READ_HEADER);
+ if (!error_reported())
+ report_error(ER_BACKUP_READ_HEADER);
+ fatal_error(ret);
return NULL;
}
if (s->next_chunk() != BSTREAM_OK)
{
- fatal_error(ER_BACKUP_NEXT_CHUNK);
+ fatal_error(report_error(ER_BACKUP_NEXT_CHUNK));
return NULL;
}
@@ -834,6 +843,7 @@ Backup_restore_ctx::prepare_for_restore(
int Backup_restore_ctx::lock_tables_for_restore()
{
TABLE_LIST *tables= NULL;
+ int ret;
/*
Iterate over all tables in all snapshots and create a linked TABLE_LIST
@@ -854,7 +864,7 @@ int Backup_restore_ctx::lock_tables_for_
if (!ptr)
{
// Error has been reported, but not logged to backup logs
- return log_error(ER_OUT_OF_RESOURCES);
+ return fatal_error(log_error(ER_OUT_OF_RESOURCES));
}
tables= backup::link_table_list(*ptr, tables); // Never errors
@@ -871,16 +881,13 @@ int Backup_restore_ctx::lock_tables_for_
Note 2: Skiping tmp tables is also important because otherwise a tmp table
can occlude a regular table with the same name (BUG#33574).
*/
- if (open_and_lock_tables_derived(m_thd, tables,
- FALSE, /* do not process derived tables */
- MYSQL_OPEN_SKIP_TEMPORARY
+ ret= open_and_lock_tables_derived(m_thd, tables,
+ FALSE, /* do not process derived tables */
+ MYSQL_OPEN_SKIP_TEMPORARY
/* do not open tmp tables */
- )
- )
- {
- fatal_error(ER_BACKUP_OPEN_TABLES,"RESTORE");
- return m_error;
- }
+ );
+ if (ret)
+ return fatal_error(report_error(ER_BACKUP_OPEN_TABLES,"RESTORE"));
m_tables_locked= TRUE;
return 0;
@@ -905,39 +912,6 @@ void Backup_restore_ctx::unlock_tables()
/**
- Report error and move context object into error state without pushing the
- error on the server's warning stack.
-
- Similar to @c fatal_error, but does not push the error on the
- server's warning stack. To be used when an error is reported from a
- server function that has already pushed the error on the warning stack.
-
- @return error code given as input or stored in the context object if
- a fatal error was reported before.
- */
-inline
-int Backup_restore_ctx::log_error(int error_code, ...)
-{
- if (m_error)
- return m_error;
-
- bool saved = push_errors(FALSE); // Do not use warning stack
-
- m_error= error_code;
- m_remove_loc= TRUE;
-
- va_list args;
- va_start(args,error_code);
- v_report_error(backup::log_level::ERROR, error_code, args);
- va_end(args);
-
- push_errors(saved); // Reset
-
- return error_code;
-}
-
-
-/**
Destroy a backup/restore context.
This should reverse all settings made when context was created and prepared.
@@ -951,7 +925,6 @@ int Backup_restore_ctx::log_error(int er
*/
int Backup_restore_ctx::close()
{
- int error= 0;
if (m_state == CLOSED)
return 0;
@@ -985,7 +958,7 @@ int Backup_restore_ctx::close()
if (m_stream && !m_stream->close())
{
// Note error, but complete clean-up
- error= ER_BACKUP_CLOSE;
+ fatal_error(report_error(ER_BACKUP_CLOSE));
}
if (m_catalog)
@@ -999,31 +972,25 @@ int Backup_restore_ctx::close()
*/
if (m_remove_loc && m_state == PREPARED_FOR_BACKUP)
{
- int res= my_delete(m_path.c_ptr(), MYF(0));
+ int ret= my_delete(m_path.c_ptr(), MYF(0));
/*
Ignore ENOENT error since it is ok if the file doesn't exist.
*/
- if (res && my_errno != ENOENT)
- {
- error= ER_CANT_DELETE_FILE;
- }
+ if (ret && my_errno != ENOENT)
+ fatal_error(report_error(ER_CANT_DELETE_FILE, m_path.c_ptr(), my_errno));
}
/* We report completion of the operation only if no errors were detected,
and logger has been initialized.
*/
- if (!error)
+ if (!m_error)
{
if (backup::Logger::m_state == backup::Logger::RUNNING)
{
report_stop(when, TRUE);
}
}
- else
- {
- fatal_error(error); // Log error
- }
/*
Destroy backup stream's memory allocator (this frees memory)
@@ -1044,7 +1011,7 @@ int Backup_restore_ctx::close()
pthread_mutex_unlock(&run_lock);
m_state= CLOSED;
- return error;
+ return m_error;
}
/**
@@ -1067,6 +1034,7 @@ int Backup_restore_ctx::do_backup()
using namespace backup;
+ int ret;
Output_stream &s= *static_cast<Output_stream*>(m_stream);
Backup_info &info= *static_cast<Backup_info*>(m_catalog);
@@ -1077,27 +1045,33 @@ int Backup_restore_ctx::do_backup()
DBUG_PRINT("backup",("Writing preamble"));
DEBUG_SYNC(m_thd, "backup_before_write_preamble");
- if (write_preamble(info, s))
+ ret= write_preamble(info, s); // Can Log errors via callback functions.
+ if (ret)
{
- fatal_error(ER_BACKUP_WRITE_HEADER);
- DBUG_RETURN(m_error);
+ if (!error_reported())
+ report_error(ER_BACKUP_WRITE_HEADER);
+ DBUG_RETURN(fatal_error(ret));
}
DBUG_PRINT("backup",("Writing table data"));
DEBUG_SYNC(m_thd, "before_backup_data");
- if (write_table_data(m_thd, info, s)) // logs errors
- DBUG_RETURN(send_error(*this, ER_BACKUP_BACKUP));
+ ret= write_table_data(m_thd, info, s); // logs errors
+ if (ret)
+ DBUG_RETURN(fatal_error(ret));
DBUG_PRINT("backup",("Writing summary"));
- if (write_summary(info, s))
- {
- fatal_error(ER_BACKUP_WRITE_SUMMARY);
- DBUG_RETURN(m_error);
- }
+ ret= write_summary(info, s);
+ if (ret)
+ DBUG_RETURN(fatal_error(report_error(ER_BACKUP_WRITE_SUMMARY)));
+ /*
+ Now backup image has been written. Set m_remove_loc to FALSE, so that the
+ backup file is not removed in Backup_restore_ctx::close().
+ */
+ m_remove_loc= FALSE;
report_stats_post(info); // Never errors
DBUG_PRINT("backup",("Backup done."));
@@ -1134,9 +1108,7 @@ int Backup_restore_ctx::restore_triggers
Image_info::Iterator *dbit= m_catalog->get_dbs();
if (!dbit)
- {
- DBUG_RETURN(fatal_error(ER_OUT_OF_RESOURCES));
- }
+ DBUG_RETURN(fatal_error(report_error(ER_OUT_OF_RESOURCES)));
// create all trigers and collect events in the events list
@@ -1145,9 +1117,8 @@ int Backup_restore_ctx::restore_triggers
Image_info::Iterator *it=
m_catalog->get_db_objects(*static_cast<Image_info::Db*>(obj));
if (!it)
- {
- DBUG_RETURN(fatal_error(ER_OUT_OF_RESOURCES));
- }
+ DBUG_RETURN(fatal_error(report_error(ER_OUT_OF_RESOURCES)));
+
while ((obj= (*it)++))
switch (obj->type()) {
@@ -1156,7 +1127,7 @@ int Backup_restore_ctx::restore_triggers
if (events.push_back(obj))
{
// Error has been reported, but not logged to backup logs
- DBUG_RETURN(log_error(ER_OUT_OF_RESOURCES));
+ DBUG_RETURN(fatal_error(log_error(ER_OUT_OF_RESOURCES)));
}
break;
@@ -1166,8 +1137,9 @@ int Backup_restore_ctx::restore_triggers
{
delete it;
delete dbit;
- fatal_error(ER_BACKUP_CANT_RESTORE_TRIGGER,obj->describe(buf));
- DBUG_RETURN(m_error);
+ int err= report_error(ER_BACKUP_CANT_RESTORE_TRIGGER,
+ obj->describe(buf));
+ DBUG_RETURN(fatal_error(err));
}
break;
@@ -1187,8 +1159,8 @@ int Backup_restore_ctx::restore_triggers
while ((ev= it++))
if (ev->m_obj_ptr->execute(m_thd))
{
- fatal_error(ER_BACKUP_CANT_RESTORE_EVENT,ev->describe(buf));
- DBUG_RETURN(m_error);
+ int ret= report_error(ER_BACKUP_CANT_RESTORE_EVENT,ev->describe(buf));
+ DBUG_RETURN(fatal_error(ret));
};
DBUG_RETURN(0);
@@ -1225,17 +1197,17 @@ int Backup_restore_ctx::do_restore()
disable_fkey_constraints(); // Never errors
- if (read_meta_data(info, s))
+ err= read_meta_data(info, s); // Can log errors via callback functions.
+ if (err)
{
- m_thd->main_da.reset_diagnostics_area(); // Never errors
-
- fatal_error(ER_BACKUP_READ_META);
- DBUG_RETURN(m_error);
+ if (!error_reported())
+ report_error(ER_BACKUP_READ_META);
+ DBUG_RETURN(fatal_error(err));
}
if (s.next_chunk() == BSTREAM_ERROR)
{
- DBUG_RETURN(fatal_error(ER_BACKUP_NEXT_CHUNK));
+ DBUG_RETURN(fatal_error(report_error(ER_BACKUP_NEXT_CHUNK)));
}
DBUG_PRINT("restore",("Restoring table data"));
@@ -1249,16 +1221,17 @@ int Backup_restore_ctx::do_restore()
close_thread_tables(m_thd); // Never errors
m_thd->main_da.reset_diagnostics_area(); // Never errors
- if (lock_tables_for_restore()) // logs errors
- DBUG_RETURN(m_error);
+ err= lock_tables_for_restore(); // logs errors
+ if (err)
+ DBUG_RETURN(fatal_error(err));
// Here restore drivers are created to restore table data
- err= restore_table_data(m_thd, info, s); // reports errors
+ err= restore_table_data(m_thd, info, s); // logs errors
unlock_tables(); // Never errors
if (err)
- DBUG_RETURN(ER_BACKUP_RESTORE);
+ DBUG_RETURN(fatal_error(err));
/*
Re-create all triggers and events (it was not done in @c bcat_create_item()).
@@ -1267,16 +1240,9 @@ int Backup_restore_ctx::do_restore()
creation of these objects will fail.
*/
- if (restore_triggers_and_events()) // reports errors
- DBUG_RETURN(ER_BACKUP_RESTORE);
-
- DBUG_PRINT("restore",("Done."));
-
- if (read_summary(info, s))
- {
- fatal_error(ER_BACKUP_READ_SUMMARY);
- DBUG_RETURN(m_error);
- }
+ err= restore_triggers_and_events(); // logs errors
+ if (err)
+ DBUG_RETURN(fatal_error(err));
/*
FIXME: this call is here because object services doesn't clean the
@@ -1287,6 +1253,12 @@ int Backup_restore_ctx::do_restore()
close_thread_tables(m_thd); // Never errors
m_thd->main_da.reset_diagnostics_area(); // Never errors
+ DBUG_PRINT("restore",("Done."));
+
+ err= read_summary(info, s);
+ if (err)
+ DBUG_RETURN(fatal_error(report_error(ER_BACKUP_READ_SUMMARY)));
+
/*
Report validity point time and binlog position stored in the backup image
(in the summary section).
@@ -1304,8 +1276,7 @@ int Backup_restore_ctx::do_restore()
}
/**
- Report stream open error by calling fatal_error, effectively moving
- context object into error state.
+ Report stream open error and move context object into error state.
@return error code given as input or the one stored in the context
object if a fatal error has already been reported.
@@ -1316,26 +1287,26 @@ int Backup_restore_ctx::report_stream_op
int error= 0;
switch (my_open_status) {
case ER_OPTION_PREVENTS_STATEMENT:
- error= fatal_error(ER_OPTION_PREVENTS_STATEMENT, "--secure-file-priv");
+ error= report_error(ER_OPTION_PREVENTS_STATEMENT, "--secure-file-priv");
break;
case ER_BACKUP_WRITE_LOC:
/*
For this error, use the actual value returned instead of the
path complimented with backupdir.
*/
- error= fatal_error(ER_BACKUP_WRITE_LOC, location->str);
+ error= report_error(ER_BACKUP_WRITE_LOC, location->str);
break;
case ER_BACKUP_READ_LOC:
/*
For this error, use the actual value returned instead of the
path complimented with backupdir.
*/
- error= fatal_error(ER_BACKUP_READ_LOC, location->str);
+ error= report_error(ER_BACKUP_READ_LOC, location->str);
break;
default:
DBUG_ASSERT(FALSE);
}
- return error;
+ return fatal_error(error);
}
namespace backup {
@@ -1480,6 +1451,7 @@ int bcat_reset(st_bstream_image_header *
DBUG_ASSERT(catalogue);
Restore_info *info= static_cast<Restore_info*>(catalogue);
+ Logger &log= info->m_log;
/*
Iterate over the list of snapshots read from the backup image (and stored
@@ -1504,50 +1476,50 @@ int bcat_reset(st_bstream_image_header *
if (!se || !hton)
{
- info->m_ctx.fatal_error(ER_BACKUP_CANT_FIND_SE, name_lex.str);
+ log.report_error(ER_BACKUP_CANT_FIND_SE, name_lex.str);
return BSTREAM_ERROR;
}
if (!hton->get_backup_engine)
{
- info->m_ctx.fatal_error(ER_BACKUP_NO_NATIVE_BE, name_lex.str);
+ log.report_error(ER_BACKUP_NO_NATIVE_BE, name_lex.str);
return BSTREAM_ERROR;
}
- info->m_snap[n]= new Native_snapshot(info->m_ctx, snap->version, se);
+ info->m_snap[n]= new Native_snapshot(log, snap->version, se);
// reports errors
break;
}
case BI_NODATA:
- info->m_snap[n]= new Nodata_snapshot(info->m_ctx, snap->version);
+ info->m_snap[n]= new Nodata_snapshot(log, snap->version);
// reports errors
break;
case BI_CS:
- info->m_snap[n]= new CS_snapshot(info->m_ctx, snap->version);
+ info->m_snap[n]= new CS_snapshot(log, snap->version);
// reports errors
break;
case BI_DEFAULT:
- info->m_snap[n]= new Default_snapshot(info->m_ctx, snap->version);
+ info->m_snap[n]= new Default_snapshot(log, snap->version);
// reports errors
break;
default:
// note: we use convention that snapshots are counted starting from 1.
- info->m_ctx.fatal_error(ER_BACKUP_UNKNOWN_BE, n + 1);
+ log.report_error(ER_BACKUP_UNKNOWN_BE, n + 1);
return BSTREAM_ERROR;
}
if (!info->m_snap[n])
{
- info->m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ log.report_error(ER_OUT_OF_RESOURCES);
return BSTREAM_ERROR;
}
info->m_snap[n]->m_num= n + 1;
- info->m_ctx.report_driver(info->m_snap[n]->name());
+ log.report_driver(info->m_snap[n]->name());
}
return BSTREAM_OK;
@@ -1577,6 +1549,7 @@ int bcat_add_item(st_bstream_image_heade
using namespace backup;
Restore_info *info= static_cast<Restore_info*>(catalogue);
+ Logger &log= info->m_log;
backup::String name_str(item->name.begin, item->name.end);
@@ -1617,7 +1590,7 @@ int bcat_add_item(st_bstream_image_heade
with error earlier.
*/
DBUG_ASSERT(it->snap_num >= info->snap_count());
- info->m_ctx.fatal_error(ER_BACKUP_WRONG_TABLE_BE, it->snap_num + 1);
+ log.report_error(ER_BACKUP_WRONG_TABLE_BE, it->snap_num + 1);
return BSTREAM_ERROR;
}
@@ -1681,6 +1654,7 @@ void* bcat_iterator_get(st_bstream_image
DBUG_ASSERT(catalogue);
Backup_info *info= static_cast<Backup_info*>(catalogue);
+ backup::Logger &log= info->m_log;
switch (type) {
@@ -1699,7 +1673,7 @@ void* bcat_iterator_get(st_bstream_image
Iterator *it= info->get_tablespaces();
if (!it)
{
- info->m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ log.report_error(ER_OUT_OF_RESOURCES);
return NULL;
}
@@ -1711,7 +1685,7 @@ void* bcat_iterator_get(st_bstream_image
Iterator *it= info->get_dbs();
if (!it)
{
- info->m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ log.report_error(ER_OUT_OF_RESOURCES);
return NULL;
}
@@ -1724,7 +1698,7 @@ void* bcat_iterator_get(st_bstream_image
if (!it)
{
- info->m_ctx.fatal_error(ER_BACKUP_CAT_ENUM);
+ log.report_error(ER_BACKUP_CAT_ENUM);
return NULL;
}
@@ -1815,18 +1789,19 @@ void* bcat_db_iterator_get(st_bstream_im
DBUG_ASSERT(dbi);
Backup_info *info= static_cast<Backup_info*>(catalogue);
+ backup::Logger &log= info->m_log;
Backup_info::Db *db = info->get_db(dbi->base.pos);
if (!db)
{
- info->m_ctx.fatal_error(ER_BACKUP_UNKNOWN_OBJECT);
+ log.report_error(ER_BACKUP_UNKNOWN_OBJECT);
return NULL;
}
backup::Image_info::Iterator *it= info->get_db_objects(*db);
if (!it)
{
- info->m_ctx.fatal_error(ER_OUT_OF_RESOURCES);
+ log.report_error(ER_OUT_OF_RESOURCES);
return NULL;
}
@@ -1879,7 +1854,8 @@ int bcat_create_item(st_bstream_image_he
DBUG_ASSERT(item);
Restore_info *info= static_cast<Restore_info*>(catalogue);
- THD *thd= info->m_ctx.thd();
+ Logger &log= info->m_log;
+ THD *thd= info->m_thd;
int create_err= 0;
switch (item->type) {
@@ -1901,7 +1877,7 @@ int bcat_create_item(st_bstream_image_he
*/
default:
- info->m_ctx.fatal_error(ER_BACKUP_UNKNOWN_OBJECT_TYPE);
+ log.report_error(ER_BACKUP_UNKNOWN_OBJECT_TYPE);
return BSTREAM_ERROR;
}
@@ -1909,7 +1885,7 @@ int bcat_create_item(st_bstream_image_he
if (!obj)
{
- info->m_ctx.fatal_error(ER_BACKUP_UNKNOWN_OBJECT);
+ log.report_error(ER_BACKUP_UNKNOWN_OBJECT);
return BSTREAM_ERROR;
}
@@ -1928,7 +1904,7 @@ int bcat_create_item(st_bstream_image_he
if (!sobj)
{
- info->m_ctx.fatal_error(create_err, desc);
+ log.report_error(create_err, desc);
return BSTREAM_ERROR;
}
@@ -1970,7 +1946,7 @@ int bcat_create_item(st_bstream_image_he
if (ts)
{
DBUG_PRINT("restore",(" tablespace has changed on the server - aborting"));
- info->m_ctx.fatal_error(ER_BACKUP_TS_CHANGE, desc);
+ log.report_error(ER_BACKUP_TS_CHANGE, desc);
return BSTREAM_ERROR;
}
}
@@ -1992,9 +1968,8 @@ int bcat_create_item(st_bstream_image_he
*/
if (!obs::check_user_existence(thd, sobj->get_name()))
{
- info->m_ctx.write_message(log_level::WARNING,
- ER(ER_BACKUP_GRANT_SKIPPED),
- create_stmt);
+ log.report_error(log_level::WARNING, ER_BACKUP_GRANT_SKIPPED,
+ create_stmt);
return BSTREAM_OK;
}
/*
@@ -2014,14 +1989,14 @@ int bcat_create_item(st_bstream_image_he
db_name.append(start, size);
if (!info->has_db(db_name))
{
- info->m_ctx.fatal_error(ER_BACKUP_GRANT_WRONG_DB, create_stmt);
+ log.report_error(ER_BACKUP_GRANT_WRONG_DB, create_stmt);
return BSTREAM_ERROR;
}
}
if (sobj->execute(thd))
{
- info->m_ctx.fatal_error(create_err, desc);
+ log.report_error(create_err, desc);
return BSTREAM_ERROR;
}
@@ -2092,11 +2067,12 @@ int bcat_get_item_create_query(st_bstrea
::String *buf= &(info->serialization_buf);
buf->length(0);
- if (obj->m_obj_ptr->serialize(info->m_ctx.thd(), buf))
+ if (obj->m_obj_ptr->serialize(info->m_thd, buf))
{
Image_info::Obj::describe_buf dbuf;
- info->m_ctx.fatal_error(meta_err, obj->describe(dbuf));
+ info->m_log.report_error(meta_err, obj->describe(dbuf));
+
return BSTREAM_ERROR;
}
=== modified file 'sql/backup/logger.cc'
--- a/sql/backup/logger.cc 2008-10-27 13:06:21 +0000
+++ b/sql/backup/logger.cc 2008-11-19 10:18:41 +0000
@@ -28,15 +28,25 @@ namespace backup {
the moment. Destinations which are not ready/initialized yet should be
silently ignored.
- @returns 0 on success.
+ @returns Reported error code.
*/
int Logger::write_message(log_level::value level, int error_code,
const char *msg)
{
char buf[ERRMSGSIZE + 30];
+ /*
+ When logging to server's error log, the msg will be prefixed with
+ "Backup:"/"Restore:" if the operation has been initialized. In that case
+ out points at the output string with the prefix added, otherwise out
+ points at msg (without any prefixes).
+ */
const char *out= msg;
- if (m_state == READY || m_state == RUNNING)
+ /*
+ Note: m_type is meaningful only after a call to init() i.e.,
+ if m_state != CREATED.
+ */
+ if (m_state != CREATED)
{
my_snprintf(buf, sizeof(buf), "%s: %s",
m_type == BACKUP ? "Backup" : "Restore" , msg);
@@ -45,43 +55,61 @@ int Logger::write_message(log_level::val
switch (level) {
case log_level::ERROR:
- if (m_save_errors)
- {
- error.code= error_code;
- error.level= MYSQL_ERROR::WARN_LEVEL_ERROR;
- error.msg= sql_strdup(msg);
- }
+ {
+ // Report to server's error log
sql_print_error(out);
- if (m_push_errors)
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- error_code, msg);
- DBUG_PRINT("backup_log",("[ERROR] %s", out));
-
+
+ // Report to the client
+
+ bool saved_value= m_thd->no_warnings_for_error;
+ m_thd->no_warnings_for_error= m_push_errors ? FALSE : TRUE;
+ my_printf_error(error_code, msg, MYF(0));
+ m_thd->no_warnings_for_error= saved_value;
+
+ m_error_reported= TRUE;
+
+ // Report to backup logs
+
if (m_state == READY || m_state == RUNNING)
{
time_t ts = my_time(0);
backup_log->error_num(error_code);
- backup_log->write_progress(0, ts, ts, 0, 0, error_code, out);
+ backup_log->write_progress(0, ts, ts, 0, 0, error_code, msg);
}
- return 0;
+ // Report in the debug trace
+
+ DBUG_PRINT("backup_log",("[ERROR] %s", out));
+
+ return error_code;
+ }
case log_level::WARNING:
+ // Report to server's error log
sql_print_warning(out);
+
+ // Report to the client (push on warning stack)
if (m_push_errors)
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
error_code, msg);
+
+ // Report to the debug trace
DBUG_PRINT("backup_log",("[Warning] %s", out));
- return 0;
+
+ return error_code;
case log_level::INFO:
+ // Report to server's error log
sql_print_information(out);
+
+ // Report to the debug trace
DBUG_PRINT("backup_log",("[Info] %s", out));
- return 0;
- default: return ERROR;
+ return error_code;
+
+ default: DBUG_ASSERT(0); return ERROR;
}
}
@@ -94,7 +122,7 @@ int Logger::write_message(log_level::val
If the message contains placeholders, additional arguments provide
values to be put there.
- @returns 0 on success.
+ @returns Reported error code.
*/
int Logger::v_report_error(log_level::value level, int error_code, va_list args)
{
=== modified file 'sql/backup/logger.h'
--- a/sql/backup/logger.h 2008-10-30 17:53:24 +0000
+++ b/sql/backup/logger.h 2008-11-19 10:18:41 +0000
@@ -51,6 +51,7 @@ class Logger
int report_error(log_level::value level, int error_code, ...);
int report_error(const char *format, ...);
int write_message(log_level::value level, const char *msg, ...);
+ int log_error(int error_code, ...);
void report_start(time_t);
void report_stop(time_t, bool);
@@ -69,11 +70,8 @@ class Logger
}
void report_cleanup() { delete backup_log; }
- void save_errors();
- void stop_save_errors();
- void clear_saved_errors();
- util::SAVED_MYSQL_ERROR *last_saved_error();
bool push_errors(bool);
+ bool error_reported() const;
protected:
@@ -85,24 +83,22 @@ class Logger
int write_message(log_level::value level , int error_code, const char *msg);
private:
- util::SAVED_MYSQL_ERROR error; ///< Used to store saved errors.
- bool m_save_errors; ///< Flag telling if errors should be saved.
+
bool m_push_errors; ///< Should errors be pushed on warning stack?
+ bool m_error_reported; ///< Has any error been reported?
Backup_log *backup_log; ///< Backup log interface class.
};
inline
Logger::Logger(THD *thd)
- :m_type(BACKUP), m_state(CREATED),
- m_thd(thd), m_save_errors(FALSE), m_push_errors(TRUE), backup_log(0)
+ :m_type(BACKUP), m_state(CREATED), m_thd(thd), m_push_errors(TRUE),
+ m_error_reported(FALSE), backup_log(0)
{}
inline
Logger::~Logger()
-{
- clear_saved_errors();
-}
+{}
inline
int Logger::write_message(log_level::value level, const char *msg, ...)
@@ -155,37 +151,20 @@ int Logger::report_error(const char *for
return res;
}
-/// Request that all reported errors are saved in the logger.
-inline
-void Logger::save_errors()
-{
- if (m_save_errors)
- return;
- clear_saved_errors();
- m_save_errors= TRUE;
-}
-
-/// Stop saving errors.
+/// Reports error without pushing it on server's error stack.
inline
-void Logger::stop_save_errors()
+int Logger::log_error(int error_code, ...)
{
- if (!m_save_errors)
- return;
- m_save_errors= FALSE;
-}
+ va_list args;
+ bool saved= push_errors(FALSE);
+
+ va_start(args, error_code);
+ int res= v_report_error(log_level::ERROR, error_code, args);
+ va_end(args);
-/// Delete all saved errors to free resources.
-inline
-void Logger::clear_saved_errors()
-{
- memset(&error, 0, sizeof(error));
-}
+ push_errors(saved);
-/// Return a pointer to most recent saved error.
-inline
-util::SAVED_MYSQL_ERROR *Logger::last_saved_error()
-{
- return error.code ? &error : NULL;
+ return res;
}
/// Report start of an operation.
@@ -320,7 +299,7 @@ void Logger::report_backup_file(char *pa
@returns 0 on success, error code otherwise.
- @todo Decide what to do if @c initialize() signals errors.
+ @todo Detect, log and report errors to the caller.
@todo Add code to get the user comment from command.
*/
inline
@@ -330,13 +309,20 @@ int Logger::init(enum_type type, const c
return 0;
m_type= type;
- m_state= READY;
+ mysql_reset_errors(m_thd, 0); // Never errors
backup_log = new Backup_log(m_thd, (enum_backup_operation)type, query);
backup_log->state(BUP_STARTING);
+ m_state= READY;
DEBUG_SYNC(m_thd, "after_backup_log_init");
return 0;
}
+inline
+bool Logger::error_reported() const
+{
+ return m_error_reported;
+}
+
} // backup namespace
#endif
=== modified file 'sql/backup/restore_info.h'
--- a/sql/backup/restore_info.h 2008-05-05 15:06:40 +0000
+++ b/sql/backup/restore_info.h 2008-11-19 10:18:41 +0000
@@ -33,9 +33,8 @@ class Restore_info: public backup::Image
{
public:
- Backup_restore_ctx &m_ctx;
+ backup::Logger &m_log;
- Restore_info(Backup_restore_ctx&);
~Restore_info();
bool is_valid() const;
@@ -47,15 +46,28 @@ class Restore_info: public backup::Image
private:
+ /*
+ Note: constructor is private because instances of this class are supposed
+ to be created only with Backup_restore_ctx::prepare_for_restore() method.
+ */
+ Restore_info(backup::Logger&, THD*);
+
+ THD *m_thd;
+
friend int backup::restore_table_data(THD*, Restore_info&,
backup::Input_stream&);
friend int ::bcat_add_item(st_bstream_image_header*,
struct st_bstream_item_info*);
+ friend int ::bcat_create_item(st_bstream_image_header *catalogue,
+ struct st_bstream_item_info *item,
+ bstream_blob create_stmt,
+ bstream_blob other_meta_data);
+ friend class Backup_restore_ctx;
};
inline
-Restore_info::Restore_info(Backup_restore_ctx &ctx)
- :m_ctx(ctx)
+Restore_info::Restore_info(backup::Logger &log, THD *thd)
+ :m_log(log), m_thd(thd)
{}
inline
@@ -82,7 +94,7 @@ Restore_info::add_ts(const ::String &nam
Ts *ts= Image_info::add_ts(name, pos);
if (!ts)
- m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_TS, name.ptr());
+ m_log.report_error(ER_BACKUP_CATALOG_ADD_TS, name.ptr());
return ts;
}
@@ -95,7 +107,7 @@ Restore_info::add_db(const ::String &nam
Db *db= Image_info::add_db(name, pos);
if (!db)
- m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_DB, name.ptr());
+ m_log.report_error(ER_BACKUP_CATALOG_ADD_DB, name.ptr());
return db;
}
@@ -109,7 +121,7 @@ Restore_info::add_table(Image_info::Db &
Table *t= Image_info::add_table(db, name, snap, pos);
if (!t)
- m_ctx.fatal_error(ER_BACKUP_CATALOG_ADD_TABLE, db.name().ptr(), name.ptr());
+ m_log.report_error(ER_BACKUP_CATALOG_ADD_TABLE, db.name().ptr(), name.ptr());
return t;
}
=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt 2008-11-05 15:07:40 +0000
+++ b/sql/share/errmsg.txt 2008-11-19 10:18:41 +0000
@@ -6414,3 +6414,5 @@ ER_RESTORE_ON_SLAVE
eng "A restore operation was attempted on a slave during replication. You must stop the
slave prior to running a restore."
ER_NONUNIQ_DB 42000 S1009
eng "Not unique database: '%-.192s'"
+ER_BACKUP_VP_FAILED
+ eng "Could not create the validity point"
| Thread |
|---|
| • bzr commit into mysql-6.0-backup branch (Rafal.Somla:2731) Bug#40303Bug#40304 | Rafal Somla | 19 Nov |