MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Rafal Somla Date:June 30 2008 10:57am
Subject:Re: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364,
Bug#35230, WL#4296
View as plain text  
Hi Chuck,

This is quite a patch! And it must have been a lot of work to figure out the 
details of server's logging infrastructure...

I looked at the patch mainly from the perspective of the separation of backup 
kernel from the server and the changes made to the backup kernel code and Logger 
class. I put my comments inlined in your patch, as usual, but here is a summary 
of main points.

Backup kernel/server separation
-------------------------------

Each time a server variable or function is referenced in the backup kernel code, 
it creates an implicit dependency between the two. As you know, we are trying to 
remove all such implicit dependencies and replace them by explicit ones via the 
si_objects API. Your patch introduces few new implicit dependencies and I don't 
like it. If you need to use a server variable or function it is a sign that our 
explicit interface to the server functionality should be extended or changed. 
Or, it is a sign that a different approach should be used to solve the problem 
at hand.


The backupdir option
--------------------

I don't like that you included implementation of that option as part of WL#4296. 
Creating a monster task which includes several loosely related subtasks makes 
implementing and reviewing the changes much harder. I think "divide and conquer" 
is the best strategy here.

I know that backupdir would give the default location of the logs, but it is a 
more general concept which can be implemented independently. Before --backupdir 
is implemented, the default location of backup logs can be the same as default 
location of backup images, i.e., the --datadir directory.

There is one good reason for implementing --backupdir in a separate patch with 
proper design. This option is the first case of an option which must be passed 
to the backup kernel (as it influences its behaviour). Note that it is different 
from options like --log_backup_output which influence behaviour of the backup 
logging service implemented in the server, not in the backup module.

But the default backup location must be known to the backup kernel and thus this 
option must be processed by the backup module, not by the server. This touches a 
non-trivial issue of passing options between the server and modules loaded into 
it. While for 6.0 we could use some simplistic approach to the issue, I still 
would like to see a proper design of how we are going to handle this.

For the above reasons, I assume --backupdir is a separate task and in my review 
I concentrate on the backup logging code only.

Server instalation
------------------

When new server is installed, the backup logging tables should be created inside 
mysql database. I don't see that your patch provides code for that.

The backup logging service and API
----------------------------------

When we think about backup logging service provided by the server, we must realize:

a) What tasks would be implemented by the server as part of this service and 
which must be implemented by a client of the service?
b) What is the API to the service (exact set of functions and datatypes to be 
exported in a header file).

Wrt. a) there are two tasks missing from the service as you defined it. These are:
- checking if backup logs are present in the server,
- generating a new backup_id based on the contents of the logs.

It is wrong to try to implement these tasks in a client (backup kernel in this 
case). They should be rather part of the service, because implementing them 
requires knowing internals of the backup logging implementation.

Wrt b) I'd like to see a clear documentation of the API in the WL. Currently, in 
the LLD you mix elements of implementation and interface.

In my opinion the API consists of:

   - enums enum_backup_state and enum_backup_operation
   - struct st_backup_history
   - functions backup_{history,progress}_log_write()

Thus, for example, class MYSQL_BACKUP_LOG is not a part of the interface but of 
the implementation.

I propose to add 2 more functions to implement the missing functionality:

   - ulonglong generate_backup_id();
   - my_bool check_backup_logs(THD *thd);


Memory allocation
-----------------

When writing your code, please consider these guidelines.

1. Don't allocate memory on heap (alloc, new, etc) unless necessary.

Dynamic memory allocation creates risk for a memory leak since we must remember 
to free memory which was allocated. Usually, one can create an "automatic" 
instance of an object or variable and its memory will be freed when code goes 
out of current scope. The same goes for class members - declaring a member as 
"Foo memeber" instead of "Foo *member" ensures that "member" is properly 
destroyed and memory freed when the parent is removed. An object needs to be 
allocated explicitly only if it is supposed to live longer than its container.

2. When setting char* pointers don't copy the string if not needed.

Doing things like:

 > +    m_op_hist->binlog_file= new char[strlen(pos.file)+1];
 > +    strcpy(m_op_hist->binlog_file, pos.file);

is justified only if we expect that pos.file string will be removed before 
m_op_hist, so that m_op_hist->binlog_file becomes a dangling pointer. But if 
lifetime of pos.file is longer than that of m_op_hist it is enough to do:

   m_op_hist->binlog_file= pos.file;

without wasting time and memory on copying the string:

3. If you need a dynamic string, use String instance for that.

The advantege is that for String objects the memory is managed automatically. 
For instance the above string copying code could be written as:

   String buf;

   buf.append(pos.file);
   m_op_hist->binlog_file= buf.ptr();

When buf is deleted, memory is automatically freed.

4. If you need static strings (like names of states), use string constants, not
dynamically allocated String instances.

Like in the method get_state_string() where you can simply do:

   return "complete";

instead of doing:

   String str;
   str->append("complete");

The latter option allocates new memory each time you call get_state_string() and 
for no reason.

My patches
----------

I have prepared my version of the patch as I believe it would best illustrate 
few of the points I made. I attach a patch against my local copy of 
mysql-6.0-backup and also another patch showing differences between my and your 
version.

Apart from implementing the suggestions mentioned above, I redesigned the Logger 
class interface a bit.

My thinking about Logger class is as follows:

- Logger supports several destinations where errors and other info can be 
reported. These destinations are:
   -- server's error log,
   -- server's debug trace,
   -- clients error/warning stack,
   -- backup logs.

- Logger should be ready for reporting errors as soon as it is created. But not 
all destinations can be used from the beginning. Thus initially no destinations 
are selected and reported errors are only stored inside Logger instance. When 
additional initialziation is done, more and more destinations can be activated.

- In order to output to the backup logs, the backup_id must be known. This is 
set by a separate initialization method.

- Logger can be additionaly initialized to become a BACKUP or RESTORE logger. 
Among other things it means that "Backup:" or "Restore:" prefix is added to each 
error/warning/info message.

I changed the public interface of Logger as follows:

- added methods for managing logging destinations,
- added methods for initializing the logger with backup_id and operation type.

Some other changes in my patches:

- mysql_priv.h:
   -- move backup logging API from here to si_objects.h,
   -- move backup log tables column definitions from here to log.cc,

- log.{h,cc}:
   -- Added new method MYSQL_BACKUP_LOG::generate_backup_id(),
   -- move implementations of backup_*_log_write() functions to si_objects.cc.

- set_var.{h,cc}:
  -- make sys_var_log_backup_output to inherit from sys_var_log_output.

- si_objects.{h,cc}:
  -- move implementations of Obj::execute() and Obj::serialize() to the .cc file
     to reduce header dependencies.
  -- move backup logging API from mysql_priv.h to si_objects.h
  -- Implement API functions in si_objects.cc instead of log.cc.

- backup/kernel.cc:
  -- revert the backupdir changes


Chuck Bell wrote:
> #At file:///C:/source/bzr/mysql-6.0-wl-4296/
> 
>  2638 Chuck Bell	2008-06-25
>       WL#4296 : Online Backup : Refine backup progress mechanism
>       
>       This worklog changes the existing backup progress mechanism from MyISAM
>       tables to logging capability similar to the query log. The new mechanism
>       allows users to specify the destination of the log as a file, table, both,
>       and allows users to turn the logs on or off.
> removed:
>   sql/backup/backup_progress.cc
>   sql/backup/backup_progress.h
> added:
>   mysql-test/r/backup_log_output.result
>   mysql-test/t/backup_log_output.test
> renamed:
>   mysql-test/r/backup_progress.result => mysql-test/r/backup_log.result
>   mysql-test/t/backup_progress.test => mysql-test/t/backup_log.test
> modified:
>   client/mysqldump.c
>   include/config-netware.h
>   include/config-win.h
>   include/mysql_com.h
>   mysql-test/mysql-test-run.pl
>   mysql-test/r/1st.result
>   mysql-test/r/backup_errors.result
>   mysql-test/r/backup_no_be.result
>   mysql-test/r/connect.result
>   mysql-test/r/information_schema.result
>   mysql-test/r/mysql_upgrade.result
>   mysql-test/r/mysqlcheck.result
>   mysql-test/r/system_mysql_db.result
>   mysql-test/suite/funcs_1/r/is_columns_mysql.result
>   mysql-test/suite/funcs_1/r/is_statistics_mysql.result
>   mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result
>   mysql-test/suite/funcs_1/r/is_tables_mysql.result
>   mysql-test/t/backup_errors.test
>   mysql-test/t/backup_no_be.test
>   mysql-test/t/disabled.def
>   mysql-test/t/mysqldump.test
>   mysql-test/t/system_mysql_db_fix30020.test
>   mysql-test/t/system_mysql_db_fix40123.test
>   mysql-test/t/system_mysql_db_fix50030.test
>   mysql-test/t/system_mysql_db_fix50117.test
>   scripts/mysql_system_tables.sql
>   sql/backup/CMakeLists.txt
>   sql/backup/Makefile.am
>   sql/backup/backup_info.cc
>   sql/backup/backup_kernel.h
>   sql/backup/data_backup.cc
>   sql/backup/kernel.cc
>   sql/backup/logger.cc
>   sql/backup/logger.h
>   sql/log.cc
>   sql/log.h
>   sql/mysql_priv.h
>   sql/mysqld.cc
>   sql/set_var.cc
>   sql/set_var.h
>   sql/share/errmsg.txt
>   sql/sql_parse.cc
>   sql/sql_yacc.yy
>   sql/table.cc
>   sql/unireg.h
>   mysql-test/r/backup_log.result
>   mysql-test/t/backup_log.test
> 
> per-file messages:
>   client/mysqldump.c
>     Changed names of backup tables to the new names for backup logs.
>   include/config-netware.h
>     Added #define for BACKUPDIR.
>   include/config-win.h
>     Added #define for BACKUPDIR.
>   include/mysql_com.h
>     Added #define for BACKUPDIR.
>   mysql-test/mysql-test-run.pl
>     Added --backupdir to command that launches the server during test runs.
>   mysql-test/r/1st.result
>     New result file.
>   mysql-test/r/backup_errors.result
>     New result file.
>   mysql-test/r/backup_log.result
>     Changed name of backup_progress test to backup_log.
>   mysql-test/r/backup_log_output.result
>     New result file.
>   mysql-test/r/backup_no_be.result
>     New result file.
>   mysql-test/r/connect.result
>     New result file.
>   mysql-test/r/information_schema.result
>     New result file.
>   mysql-test/r/mysql_upgrade.result
>     New result file.
>   mysql-test/r/mysqlcheck.result
>     New result file.
>   mysql-test/r/system_mysql_db.result
>     New result file.
>   mysql-test/suite/funcs_1/r/is_columns_mysql.result
>     New result file.
>   mysql-test/suite/funcs_1/r/is_statistics_mysql.result
>     New result file.
>   mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result
>     New result file.
>   mysql-test/suite/funcs_1/r/is_tables_mysql.result
>     New result file.
>   mysql-test/t/backup_errors.test
>     New result file.
>   mysql-test/t/backup_log.test
>     Changed name of backup_progress test to backup_log.
>   mysql-test/t/backup_log_output.test
>     New test to test the backup log output options.
>   mysql-test/t/backup_no_be.test
>     Changed names of backup tables to the new names for backup logs.
>   mysql-test/t/disabled.def
>     Changed names of backup tables to the new names for backup logs.
>   mysql-test/t/mysqldump.test
>     Changed names of backup tables to the new names for backup logs.
>   mysql-test/t/system_mysql_db_fix30020.test
>     Changed names of backup tables to the new names for backup logs.
>   mysql-test/t/system_mysql_db_fix40123.test
>     Changed names of backup tables to the new names for backup logs.
>   mysql-test/t/system_mysql_db_fix50030.test
>     Changed names of backup tables to the new names for backup logs.
>   mysql-test/t/system_mysql_db_fix50117.test
>     Changed names of backup tables to the new names for backup logs.
>   scripts/mysql_system_tables.sql
>     Added create statements for the new logs replacing the existing create 
>     statements for old progress tables.
>   sql/backup/CMakeLists.txt
>     Changed backup_progress to backup_log.
>   sql/backup/Makefile.am
>     Changed backup_progress to backup_log.
>   sql/backup/backup_info.cc
>     Changed backup_progress to backup_log.
>   sql/backup/backup_kernel.h
>     Corrected comment to match new functionality.
>   sql/backup/backup_progress.cc
>     File removed. Functionality moved to logger.* and log.*.
>   sql/backup/backup_progress.h
>     File removed. Functionality moved to logger.* and log.*.
>   sql/backup/data_backup.cc
>     Removed unused reference.
>   sql/backup/kernel.cc
>     Added code to support the backupdir variable/command-line option. See BUG#35230.
>   sql/backup/logger.cc
>     Changed calls to old progress methods to new backup logging class.
>     Added log mechanism calls to logger class.
>   sql/backup/logger.h
>     Added variable for accessing the new backup log class.
>     Added call to initialize the backup log class.
>     Added log mechanism calls to logger class.
>   sql/log.cc
>     Added support for a backup log facility similar to the query log.
>   sql/log.h
>     Added method declarations and class definitions for backup log facility.
>   sql/mysql_priv.h
>     Added online backup definitions for use in logs.
>     Added a new structure for holding the backup history information.
>     Note: This information was originally in backup_progress files.
>   sql/mysqld.cc
>     Added support for the new command-line options and variables. This includes code
> to
>     set defaults and print warnings on misuse.
>   sql/set_var.cc
>     Added support for the following new command-line options:
>     
>     --backup_log_output        : Specifies log output as
> [NONE|FILE|TABLE|FILE,TABLE]
>                                  Default is TABLE.
>     --backup-history-log       : Turn history log on or off. 
>                                  Default is enabled (TRUE).
>     --backup-progress-log      : Turn progress log on or off. 
>                                  Default is enabled (TRUE).
>     --backupdir                : Specifies the location for backup logs and image
> files
>                                  included on the BACKUP and RESTORE commands where a
> path is
>                                  not specified. 
>                                  Default is backupdir == datadir == '.'.
>     --skip-backup-history-log  : Turn off history log.
>     --skip-backup-progress-log : Turn off progress log.
>   sql/set_var.h
>     Added new class definition for backup log output option.
>   sql/share/errmsg.txt
>     Corrected error message to match new names of the logs.
>   sql/sql_parse.cc
>     Added command to flush logs. Note: This is not a fix for bug 33364. (# omitted
> intentionally)
>   sql/sql_yacc.yy
>     Added command for flushing backup logs.
>   sql/table.cc
>     Added strings for table names for the backup logs when written to tables.
>   sql/unireg.h
>     Added #define for BACKUPDIR.
> === modified file 'client/mysqldump.c'
> --- a/client/mysqldump.c	2008-05-08 20:43:28 +0000
> +++ b/client/mysqldump.c	2008-06-25 21:29:44 +0000
> @@ -905,9 +905,9 @@ static int get_options(int *argc, char *
>        my_hash_insert(&ignore_table,
>                       (uchar*) my_strdup("mysql.slow_log", MYF(MY_WME))) ||
>        my_hash_insert(&ignore_table,
> -                     (uchar*) my_strdup("mysql.online_backup", MYF(MY_WME))) ||
> +                     (uchar*) my_strdup("mysql.backup_history", MYF(MY_WME))) ||
>        my_hash_insert(&ignore_table,
> -                     (uchar*) my_strdup("mysql.online_backup_progress",
> MYF(MY_WME))))
> +                     (uchar*) my_strdup("mysql.backup_progress", MYF(MY_WME))))
>      return(EX_EOM);
>  
>    if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
> 
> === modified file 'include/config-netware.h'
> --- a/include/config-netware.h	2007-07-23 21:54:55 +0000
> +++ b/include/config-netware.h	2008-06-25 21:29:44 +0000
> @@ -132,6 +132,7 @@ extern "C" {
>  #define SHAREDIR              "share/"
>  #define DEFAULT_CHARSET_HOME  "sys:/mysql/"
>  #define DATADIR               "data/"
> +#define BACKUPDIR             "data/"
>  
>  /* 64-bit file system calls */
>  #define SIZEOF_OFF_T          8
> 
> === modified file 'include/config-win.h'
> --- a/include/config-win.h	2008-05-22 18:40:15 +0000
> +++ b/include/config-win.h	2008-06-25 21:29:44 +0000
> @@ -336,6 +336,7 @@ inline double ulonglong2double(ulonglong
>  #else
>  #define DEFAULT_MYSQL_HOME	"c:\\mysql"
>  #define DATADIR         	"c:\\mysql\\data"
> +#define BACKUPDIR        	"c:\\mysql\\data"
>  #define PACKAGE			"mysql"
>  #define DEFAULT_BASEDIR		"C:\\"
>  #define SHAREDIR		"share"
> 
> === modified file 'include/mysql_com.h'
> --- a/include/mysql_com.h	2008-06-02 15:47:07 +0000
> +++ b/include/mysql_com.h	2008-06-25 21:29:44 +0000
> @@ -135,6 +135,7 @@ enum enum_server_command
>  #define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */
>  #define REFRESH_DES_KEY_FILE	0x40000L
>  #define REFRESH_USER_RESOURCES	0x80000L
> +#define REFRESH_BACKUP_LOG	0x200000L
>  
>  #define CLIENT_LONG_PASSWORD	1	/* new more secure passwords */
>  #define CLIENT_FOUND_ROWS	2	/* Found instead of affected rows */
> 
> === modified file 'mysql-test/mysql-test-run.pl'
> --- a/mysql-test/mysql-test-run.pl	2008-06-04 13:20:03 +0000
> +++ b/mysql-test/mysql-test-run.pl	2008-06-25 21:29:44 +0000
> @@ -3641,6 +3641,17 @@ sub mysqld_arguments ($$$$) {
>    mtr_add_arg($args, "%s--datadir=%s", $prefix,
>  	      $mysqld->{'path_myddir'});
>  
> +  #
> +  # Add the --backupdir parameter for running backup tests from MTR.
> +  # Note: In the future, this setting should be moved to an option
> +  # file located in the backup suite directory. The file should contain
> +  # the following and be named 'suite.opt':
> +  #
> +  # --backupdir=$MYSQLTEST_VARDIR/tmp
> +  #
> +  mtr_add_arg($args, "%s--backupdir=%s", $prefix,
> +	      $mysqld->{'path_myddir'});
> +
>  
>    if ( $mysql_version_id >= 50106 )
>    {
> 
> === modified file 'mysql-test/r/1st.result'
> --- a/mysql-test/r/1st.result	2007-11-30 06:04:31 +0000
> +++ b/mysql-test/r/1st.result	2008-06-25 21:29:44 +0000
> @@ -16,8 +16,8 @@ help_relation
>  help_topic
>  host
>  ndb_binlog_index
> -online_backup
> -online_backup_progress
> +backup_history
> +backup_progress
>  plugin
>  proc
>  procs_priv
> 
> === modified file 'mysql-test/r/backup_errors.result'
> --- a/mysql-test/r/backup_errors.result	2008-03-05 17:48:12 +0000
> +++ b/mysql-test/r/backup_errors.result	2008-06-25 21:29:44 +0000
> @@ -63,8 +63,8 @@ Backup of mysql, information_schema scen
>  BACKUP DATABASE mysql, information_schema, test TO 't.bak';
>  ERROR HY000: Database 'mysql' cannot be included in a backup
>  Making copies of progress tables.
> -CREATE TABLE IF NOT EXISTS test.ob_copy LIKE mysql.online_backup;
> -CREATE TABLE IF NOT EXISTS test.obp_copy LIKE mysql.online_backup_progress;
> +CREATE TABLE IF NOT EXISTS test.ob_copy LIKE mysql.backup_history;
> +CREATE TABLE IF NOT EXISTS test.obp_copy LIKE mysql.backup_progress;
>  CREATE DATABASE test_ob_error;
>  CREATE TABLE test_ob_error.t1 (col_a int);
>  INSERT INTO test_ob_error.t1 VALUES (1), (2), (3), (4), (5);
> @@ -72,26 +72,26 @@ Backup the database;
>  BACKUP DATABASE test_ob_error TO 'ob_err.bak';
>  backup_id
>  #
> -DROP TABLE mysql.online_backup;
> +DROP TABLE mysql.backup_history;
>  Backup the database;
>  BACKUP DATABASE test_ob_error TO 'ob_err.bak';
> -ERROR 42S02: Table 'mysql.online_backup' doesn't exist
> +ERROR 42S02: Table 'mysql.backup_history' doesn't exist
>  SHOW ERRORS;
>  Level	Code	Message
> -Error	#	Table 'mysql.online_backup' doesn't exist
> +Error	#	Table 'mysql.backup_history' doesn't exist
>  Error	#	Cannot create backup/restore execution context
>  Restoring the table
> -CREATE TABLE mysql.online_backup LIKE test.ob_copy;
> +CREATE TABLE mysql.backup_history LIKE test.ob_copy;
>  DROP TABLE test.ob_copy;
> -DROP TABLE mysql.online_backup_progress;
> +DROP TABLE mysql.backup_progress;
>  Backup the database;
>  BACKUP DATABASE test_ob_error TO 'ob_err.bak';
> -ERROR 42S02: Table 'mysql.online_backup_progress' doesn't exist
> +ERROR 42S02: Table 'mysql.backup_progress' doesn't exist
>  SHOW ERRORS;
>  Level	Code	Message
> -Error	#	Table 'mysql.online_backup_progress' doesn't exist
> +Error	#	Table 'mysql.backup_progress' doesn't exist
>  Error	#	Cannot create backup/restore execution context
>  Restoring the table
> -CREATE TABLE mysql.online_backup_progress LIKE test.obp_copy;
> +CREATE TABLE mysql.backup_progress LIKE test.obp_copy;
>  DROP TABLE test.obp_copy;
>  DROP DATABASE test_ob_error;
> 
> === renamed file 'mysql-test/r/backup_progress.result' =>
> 'mysql-test/r/backup_log.result'
> --- a/mysql-test/r/backup_progress.result	2008-03-20 14:53:16 +0000
> +++ b/mysql-test/r/backup_log.result	2008-06-25 21:29:44 +0000
> @@ -32,9 +32,9 @@ con2: Send backup command.
>  BACKUP DATABASE backup_progress to 'backup_progress_orig.bak';
>  con1: Checking locks.
>  con1: Checking progress.
> -SELECT MAX(backup_id) INTO @bup_id FROM mysql.online_backup WHERE command LIKE
> "BACKUP DATABASE backup_progress%";
> +SELECT MAX(backup_id) INTO @bup_id FROM mysql.backup_history WHERE command LIKE
> "BACKUP DATABASE backup_progress%";
>  INSERT INTO backup_progress.t1_res (id) VALUES (@bup_id);
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  backup_state
>  starting
>  con1: Advance the lock.
> @@ -43,7 +43,7 @@ get_lock("bp_running_state", 0)
>  1
>  con1: Checking locks.
>  con1: Checking progress.
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  backup_state
>  running
>  con1: Advance the lock.
> @@ -52,7 +52,7 @@ get_lock("bp_vp_state", 0)
>  1
>  con1: Checking locks.
>  con1: Checking progress.
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  backup_state
>  validity point
>  con1: Advance the lock.
> @@ -61,7 +61,7 @@ get_lock("bp_running_state", 0)
>  1
>  con1: Checking locks.
>  con1: Checking progress.
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  backup_state
>  running
>  con1: Advance the lock.
> @@ -71,7 +71,7 @@ release_lock("bp_running_state")
>  con2: Finish backup command
>  backup_id
>  #
> -SELECT ob.* FROM mysql.online_backup AS ob JOIN backup_progress.t1_res AS t1 ON
> ob.backup_id = t1.id;;
> +SELECT ob.* FROM mysql.backup_history AS ob JOIN backup_progress.t1_res AS t1 ON
> ob.backup_id = t1.id;;
>  backup_id	#
>  process_id	#
>  binlog_pos	#
> @@ -90,7 +90,7 @@ backup_file	backup_progress_orig.bak
>  user_comment	
>  command	BACKUP DATABASE backup_progress to 'backup_progress_orig.bak'
>  engines	Default, Snapshot
> -SELECT obp.* FROM mysql.online_backup_progress AS obp JOIN backup_progress.t1_res AS
> t1 ON obp.backup_id = t1.id;
> +SELECT obp.* FROM mysql.backup_progress AS obp JOIN backup_progress.t1_res AS t1 ON
> obp.backup_id = t1.id;
>  backup_id	object	start_time	stop_time	total_bytes	progress	error_num	notes
>  #	backup kernel	#	#	0	0	0	starting
>  #	backup kernel	#	#	0	0	0	running
> @@ -108,9 +108,9 @@ con1: Checking locks.
>  con1: Checking progress.
>  select * from backup_progress.t1_res;
>  id
> -SELECT MAX(backup_id) INTO @bup_id FROM mysql.online_backup WHERE command LIKE
> "RESTORE FROM%";
> +SELECT MAX(backup_id) INTO @bup_id FROM mysql.backup_history WHERE command LIKE
> "RESTORE FROM%";
>  INSERT INTO backup_progress.t1_res (id) VALUES (@bup_id);
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  backup_state
>  starting
>  con1: Advance the lock.
> @@ -119,7 +119,7 @@ get_lock("bp_running_state", 0)
>  1
>  con1: Checking locks.
>  con1: Checking progress.
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  backup_state
>  running
>  con1: Advance the lock.
> @@ -130,9 +130,9 @@ con2: Finish restore command
>  backup_id
>  #
>  DELETE FROM backup_progress.t1_res;
> -SELECT MAX(backup_id) INTO @bup_id FROM mysql.online_backup WHERE command LIKE
> "RESTORE FROM%";
> +SELECT MAX(backup_id) INTO @bup_id FROM mysql.backup_history WHERE command LIKE
> "RESTORE FROM%";
>  INSERT INTO backup_progress.t1_res (id) VALUES (@bup_id);
> -SELECT ob.* FROM mysql.online_backup AS ob JOIN backup_progress.t1_res AS t1 ON
> ob.backup_id = t1.id;;
> +SELECT ob.* FROM mysql.backup_history AS ob JOIN backup_progress.t1_res AS t1 ON
> ob.backup_id = t1.id;;
>  backup_id	#
>  process_id	#
>  binlog_pos	#
> @@ -151,7 +151,7 @@ backup_file	backup_progress_orig.bak
>  user_comment	
>  command	RESTORE FROM 'backup_progress_orig.bak'
>  engines	Default, Snapshot
> -SELECT obp.* FROM mysql.online_backup_progress AS obp JOIN backup_progress.t1_res AS
> t1 ON obp.backup_id = t1.id;
> +SELECT obp.* FROM mysql.backup_progress AS obp JOIN backup_progress.t1_res AS t1 ON
> obp.backup_id = t1.id;
>  backup_id	object	start_time	stop_time	total_bytes	progress	error_num	notes
>  #	backup kernel	#	#	0	0	0	starting
>  #	backup kernel	#	#	0	0	0	running
> 
> === added file 'mysql-test/r/backup_log_output.result'
> --- a/mysql-test/r/backup_log_output.result	1970-01-01 00:00:00 +0000
> +++ b/mysql-test/r/backup_log_output.result	2008-06-25 21:29:44 +0000
> @@ -0,0 +1,242 @@
> +Reset backupdir 
> +SET @@global.backupdir = @@global.datadir;
> +con1
> +Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +Variable_name	Value
> +backup_history_log	ON
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +Variable_name	Value
> +backup_progress_log	ON
> +SHOW VARIABLES LIKE 'log_backup_output';
> +Variable_name	Value
> +log_backup_output	TABLE
> +'---Checking backup logs when log_backup_output is NONE---'
> +'---and the backup logs are turned off                 ---'
> +SET @@global.log_backup_output = 'NONE';
> +SET @@global.backup_history_log = 'OFF';
> +SET @@global.backup_progress_log = 'OFF';
> +Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +Variable_name	Value
> +backup_history_log	OFF
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +Variable_name	Value
> +backup_progress_log	OFF
> +SHOW VARIABLES LIKE 'log_backup_output';
> +Variable_name	Value
> +log_backup_output	NONE
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +0
> +SELECT count(*) FROM mysql.backup_progress;
> +count(*)
> +0
> +DROP DATABASE IF EXISTS bup_log;
> +Create a database and back it up
> +CREATE DATABASE bup_log;
> +CREATE TABLE bup_log.t1(a INT);
> +INSERT INTO bup_log.t1 VALUES (1), (2), (3);
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +backup_id
> +#
> +Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +0
> +SELECT count(*) FROM mysql.backup_progress;
> +count(*)
> +0
> +FLUSH BACKUP LOGS;
> +'---Checking backup logs when log_backup_output is TABLE---'
> +SET @@global.log_backup_output = 'TABLE';
> +turning backup logs back on
> +SET @@global.backup_history_log = 'ON';
> +SET @@global.backup_progress_log = 'ON';
> +Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +Variable_name	Value
> +backup_history_log	ON
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +Variable_name	Value
> +backup_progress_log	ON
> +SHOW VARIABLES LIKE 'log_backup_output';
> +Variable_name	Value
> +log_backup_output	TABLE
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +backup_id
> +#
> +Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +1
> +SELECT count(*) FROM mysql.backup_progress;
> +count(*)
> +5
> +FLUSH BACKUP LOGS;
> +'---Checking backup logs when log_backup_output is TABLE---'
> +'---and the history log is turned off                   ---'
> +SET @@global.backup_history_log = 'ON';
> +SET @@global.backup_progress_log = 'OFF';
> +Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +Variable_name	Value
> +backup_history_log	ON
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +Variable_name	Value
> +backup_progress_log	OFF
> +SHOW VARIABLES LIKE 'log_backup_output';
> +Variable_name	Value
> +log_backup_output	TABLE
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +0
> +SELECT count(*) FROM mysql.backup_progress;
> +count(*)
> +0
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +backup_id
> +#
> +Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +1
> +SELECT count(*) FROM mysql.backup_progress;
> +count(*)
> +0
> +FLUSH BACKUP LOGS;
> +'---Checking backup logs when log_backup_output is TABLE---'
> +'---and the progress log is turned off                 ---'
> +SET @@global.backup_history_log = 'OFF';
> +SET @@global.backup_progress_log = 'ON';
> +Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +Variable_name	Value
> +backup_history_log	OFF
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +Variable_name	Value
> +backup_progress_log	ON
> +SHOW VARIABLES LIKE 'log_backup_output';
> +Variable_name	Value
> +log_backup_output	TABLE
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +0
> +SELECT count(*) FROM mysql.backup_progress;
> +count(*)
> +0
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +backup_id
> +#
> +Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +0
> +SELECT count(*) FROM mysql.backup_progress;
> +count(*)
> +5
> +FLUSH BACKUP LOGS;
> +'---Checking backup logs when log_backup_output is FILE---'
> +SET @@global.log_backup_output = 'FILE';
> +turning backup logs back on
> +SET @@global.backup_history_log = 'ON';
> +SET @@global.backup_progress_log = 'ON';
> +Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +Variable_name	Value
> +backup_history_log	ON
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +Variable_name	Value
> +backup_progress_log	ON
> +SHOW VARIABLES LIKE 'log_backup_output';
> +Variable_name	Value
> +log_backup_output	FILE
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +backup_id
> +#
> +Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +0
> +SELECT count(*) FROM mysql.backup_progress;
> +count(*)
> +0
> +FLUSH BACKUP LOGS;
> +'---Checking backup logs when log_backup_output is TABLE, FILE---'
> +SET @@global.log_backup_output = 'TABLE,FILE';
> +Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +Variable_name	Value
> +backup_history_log	ON
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +Variable_name	Value
> +backup_progress_log	ON
> +SHOW VARIABLES LIKE 'log_backup_output';
> +Variable_name	Value
> +log_backup_output	FILE,TABLE
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +backup_id
> +#
> +Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +count(*)
> +1
> +SELECT count(*) FROM mysql.backup_progress;
> +count(*)
> +5
> +FLUSH BACKUP LOGS;
> +SET @@global.log_backup_output = 'TABLE';
> +Examine the backupdir
> +SHOW VARIABLES LIKE 'backupdir%';
> +Variable_name	Value
> +backupdir	c:/source/bzr/mysql-6.0-wl-4296/mysql-test/var/master-data/
> +Create a directory for backup images
> +Reset backupdir 
> +SET @@global.backupdir = '../tmp/backup';
> +Examine the backupdir
> +SHOW VARIABLES LIKE 'backupdir%';
> +Variable_name	Value
> +backupdir	../tmp/backup
> +Perform backup
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +backup_id
> +#
> +Ensure backup image file went to the correct location
> +/backup/bup_log.bak
> +Perform restore
> +RESTORE FROM 'bup_log.bak';
> +backup_id
> +#
> +Now do the backup and restore by specifying a path.
> +Perform backup
> +BACKUP DATABASE bup_log TO '../tmp/bup_log.bak';
> +backup_id
> +#
> +Ensure backup image file went to the correct location
> +Perform restore
> +RESTORE FROM '../tmp/bup_log.bak';
> +backup_id
> +#
> +Reset backupdir 
> +SET @@global.backupdir = @@global.datadir;
> +Examine the backupdir
> +SHOW VARIABLES LIKE 'backupdir%';
> +Variable_name	Value
> +backupdir	c:/source/bzr/mysql-6.0-wl-4296/mysql-test/var/master-data/
> +Cleanup
> +DROP DATABASE bup_log;
> 
> === modified file 'mysql-test/r/backup_no_be.result'
> --- a/mysql-test/r/backup_no_be.result	2008-04-16 18:23:05 +0000
> +++ b/mysql-test/r/backup_no_be.result	2008-06-25 21:29:44 +0000
> @@ -12,10 +12,10 @@ backup_id
>  #
>  SHOW WARNINGS;
>  Level	Code	Message
> -SELECT max(backup_id) INTO @id FROM mysql.online_backup 
> +SELECT max(backup_id) INTO @id FROM mysql.backup_history 
>  WHERE command LIKE 'BACKUP DATABASE db1 %';
> -SELECT engines FROM mysql.online_backup WHERE backup_id=@id;
> -engines
> +SELECT drivers FROM mysql.backup_history WHERE backup_id=@id;
> +drivers
>  Default
>  SET SESSION debug="d,backup_test_dummy_be_factory";
>  SELECT @@debug;
> @@ -27,10 +27,10 @@ backup_id
>  SHOW WARNINGS;
>  Level	Code	Message
>  Warning	#	Cannot create backup engine for storage engine MyISAM
> -SELECT max(backup_id) INTO @id FROM mysql.online_backup 
> +SELECT max(backup_id) INTO @id FROM mysql.backup_history 
>  WHERE command LIKE 'BACKUP DATABASE db1 %';
> -SELECT engines FROM mysql.online_backup WHERE backup_id=@id;
> -engines
> +SELECT drivers FROM mysql.backup_history WHERE backup_id=@id;
> +drivers
>  Default
>  RESTORE FROM 'db1.bak';
>  backup_id
> 
> === modified file 'mysql-test/r/connect.result'
> --- a/mysql-test/r/connect.result	2008-03-27 19:02:15 +0000
> +++ b/mysql-test/r/connect.result	2008-06-25 21:29:44 +0000
> @@ -1,6 +1,8 @@
>  drop table if exists t1,t2;
>  show tables;
>  Tables_in_mysql
> +backup_history
> +backup_progress
>  columns_priv
>  db
>  event
> @@ -12,8 +14,6 @@ help_relation
>  help_topic
>  host
>  ndb_binlog_index
> -online_backup
> -online_backup_progress
>  plugin
>  proc
>  procs_priv
> @@ -36,6 +36,8 @@ grant ALL on *.* to test@localhost ident
>  grant ALL on *.* to test@stripped identified by "gambling";
>  show tables;
>  Tables_in_mysql
> +backup_history
> +backup_progress
>  columns_priv
>  db
>  event
> @@ -47,8 +49,6 @@ help_relation
>  help_topic
>  host
>  ndb_binlog_index
> -online_backup
> -online_backup_progress
>  plugin
>  proc
>  procs_priv
> @@ -79,6 +79,8 @@ ERROR HY000: Password hash should be a 4
>  set password=old_password('gambling3');
>  show tables;
>  Tables_in_mysql
> +backup_history
> +backup_progress
>  columns_priv
>  db
>  event
> @@ -90,8 +92,6 @@ help_relation
>  help_topic
>  host
>  ndb_binlog_index
> -online_backup
> -online_backup_progress
>  plugin
>  proc
>  procs_priv
> 
> === modified file 'mysql-test/r/information_schema.result'
> --- a/mysql-test/r/information_schema.result	2008-04-19 20:34:56 +0000
> +++ b/mysql-test/r/information_schema.result	2008-06-25 21:29:44 +0000
> @@ -68,6 +68,8 @@ TABLE_PRIVILEGES
>  TRIGGERS
>  USER_PRIVILEGES
>  VIEWS
> +backup_history
> +backup_progress
>  columns_priv
>  db
>  event
> @@ -78,8 +80,6 @@ help_keyword
>  help_relation
>  help_topic
>  host
> -online_backup
> -online_backup_progress
>  plugin
>  proc
>  procs_priv
> @@ -803,15 +803,15 @@ TABLES	CREATE_TIME	datetime
>  TABLES	UPDATE_TIME	datetime
>  TABLES	CHECK_TIME	datetime
>  TRIGGERS	CREATED	datetime
> +backup_history	validity_point_time	datetime
> +backup_history	start_time	datetime
> +backup_history	stop_time	datetime
> +backup_progress	start_time	datetime
> +backup_progress	stop_time	datetime
>  event	execute_at	datetime
>  event	last_executed	datetime
>  event	starts	datetime
>  event	ends	datetime
> -online_backup	validity_point_time	datetime
> -online_backup	start_time	datetime
> -online_backup	stop_time	datetime
> -online_backup_progress	start_time	datetime
> -online_backup_progress	stop_time	datetime
>  SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES A
>  WHERE NOT EXISTS 
>  (SELECT * FROM INFORMATION_SCHEMA.COLUMNS B
> @@ -1373,7 +1373,6 @@ select 1 as f1 from information_schema.t
>  (select cast(table_name as char)  from information_schema.tables
>  order by table_name limit 1) limit 1;
>  f1
> -1
>  select t.table_name, group_concat(t.table_schema, '.', t.table_name),
>  count(*) as num1
>  from information_schema.tables t
> 
> === modified file 'mysql-test/r/mysql_upgrade.result'
> --- a/mysql-test/r/mysql_upgrade.result	2008-03-21 01:59:35 +0000
> +++ b/mysql-test/r/mysql_upgrade.result	2008-06-25 21:29:44 +0000
> @@ -1,4 +1,10 @@
>  Run mysql_upgrade once
> +mysql.backup_history
> +Error    : You can't use locks with log tables.
> +status   : OK
> +mysql.backup_progress
> +Error    : You can't use locks with log tables.
> +status   : OK
>  mysql.columns_priv                                 OK
>  mysql.db                                           OK
>  mysql.event                                        OK
> @@ -12,12 +18,6 @@ mysql.help_relation                     
>  mysql.help_topic                                   OK
>  mysql.host                                         OK
>  mysql.ndb_binlog_index                             OK
> -mysql.online_backup
> -Error    : You can't use locks with log tables.
> -status   : OK
> -mysql.online_backup_progress
> -Error    : You can't use locks with log tables.
> -status   : OK
>  mysql.plugin                                       OK
>  mysql.proc                                         OK
>  mysql.procs_priv                                   OK
> @@ -35,6 +35,12 @@ mysql.user                              
>  Run it again - should say already completed
>  This installation of MySQL is already upgraded to VERSION, use --force if you still
> need to run mysql_upgrade
>  Force should run it regardless of wether it's been run before
> +mysql.backup_history
> +Error    : You can't use locks with log tables.
> +status   : OK
> +mysql.backup_progress
> +Error    : You can't use locks with log tables.
> +status   : OK
>  mysql.columns_priv                                 OK
>  mysql.db                                           OK
>  mysql.event                                        OK
> @@ -48,12 +54,6 @@ mysql.help_relation                     
>  mysql.help_topic                                   OK
>  mysql.host                                         OK
>  mysql.ndb_binlog_index                             OK
> -mysql.online_backup
> -Error    : You can't use locks with log tables.
> -status   : OK
> -mysql.online_backup_progress
> -Error    : You can't use locks with log tables.
> -status   : OK
>  mysql.plugin                                       OK
>  mysql.proc                                         OK
>  mysql.procs_priv                                   OK
> @@ -71,6 +71,12 @@ mysql.user                              
>  CREATE USER mysqltest1@'%' IDENTIFIED by 'sakila';
>  GRANT ALL ON *.* TO mysqltest1@'%';
>  Run mysql_upgrade with password protected account
> +mysql.backup_history
> +Error    : You can't use locks with log tables.
> +status   : OK
> +mysql.backup_progress
> +Error    : You can't use locks with log tables.
> +status   : OK
>  mysql.columns_priv                                 OK
>  mysql.db                                           OK
>  mysql.event                                        OK
> @@ -84,12 +90,6 @@ mysql.help_relation                     
>  mysql.help_topic                                   OK
>  mysql.host                                         OK
>  mysql.ndb_binlog_index                             OK
> -mysql.online_backup
> -Error    : You can't use locks with log tables.
> -status   : OK
> -mysql.online_backup_progress
> -Error    : You can't use locks with log tables.
> -status   : OK
>  mysql.plugin                                       OK
>  mysql.proc                                         OK
>  mysql.procs_priv                                   OK
> @@ -109,6 +109,12 @@ Run mysql_upgrade with a non existing se
>  mysqlcheck: Got error: 2005: Unknown MySQL server host 'not_existing_host' (errno)
> when trying to connect
>  FATAL ERROR: Upgrade failed
>  set GLOBAL sql_mode='STRICT_ALL_TABLES,ANSI_QUOTES,NO_ZERO_DATE';
> +mysql.backup_history
> +Error    : You can't use locks with log tables.
> +status   : OK
> +mysql.backup_progress
> +Error    : You can't use locks with log tables.
> +status   : OK
>  mysql.columns_priv                                 OK
>  mysql.db                                           OK
>  mysql.event                                        OK
> @@ -122,12 +128,6 @@ mysql.help_relation                     
>  mysql.help_topic                                   OK
>  mysql.host                                         OK
>  mysql.ndb_binlog_index                             OK
> -mysql.online_backup
> -Error    : You can't use locks with log tables.
> -status   : OK
> -mysql.online_backup_progress
> -Error    : You can't use locks with log tables.
> -status   : OK
>  mysql.plugin                                       OK
>  mysql.proc                                         OK
>  mysql.procs_priv                                   OK
> 
> === modified file 'mysql-test/r/mysqlcheck.result'
> --- a/mysql-test/r/mysqlcheck.result	2008-02-11 21:22:19 +0000
> +++ b/mysql-test/r/mysqlcheck.result	2008-06-25 21:29:44 +0000
> @@ -1,6 +1,10 @@
>  DROP TABLE IF EXISTS t1, `t``1`, `t 1`;
>  drop view if exists v1;
>  drop database if exists client_test_db;
> +mysql.backup_history
> +note     : The storage engine for the table doesn't support optimize
> +mysql.backup_progress
> +note     : The storage engine for the table doesn't support optimize
>  mysql.columns_priv                                 OK
>  mysql.db                                           OK
>  mysql.event                                        OK
> @@ -13,8 +17,6 @@ mysql.help_relation                     
>  mysql.help_topic                                   OK
>  mysql.host                                         OK
>  mysql.ndb_binlog_index                             OK
> -mysql.online_backup                                OK
> -mysql.online_backup_progress                       OK
>  mysql.plugin                                       OK
>  mysql.proc                                         OK
>  mysql.procs_priv                                   OK
> @@ -28,6 +30,10 @@ mysql.time_zone_name                    
>  mysql.time_zone_transition                         OK
>  mysql.time_zone_transition_type                    OK
>  mysql.user                                         OK
> +mysql.backup_history
> +note     : The storage engine for the table doesn't support optimize
> +mysql.backup_progress
> +note     : The storage engine for the table doesn't support optimize
>  mysql.columns_priv                                 OK
>  mysql.db                                           OK
>  mysql.event                                        OK
> @@ -40,8 +46,6 @@ mysql.help_relation                     
>  mysql.help_topic                                   OK
>  mysql.host                                         OK
>  mysql.ndb_binlog_index                             OK
> -mysql.online_backup                                OK
> -mysql.online_backup_progress                       OK
>  mysql.plugin                                       OK
>  mysql.proc                                         OK
>  mysql.procs_priv                                   OK
> 
> === modified file 'mysql-test/r/system_mysql_db.result'
> --- a/mysql-test/r/system_mysql_db.result	2008-02-11 21:22:19 +0000
> +++ b/mysql-test/r/system_mysql_db.result	2008-06-25 21:29:44 +0000
> @@ -1,6 +1,8 @@
>  drop table if exists t1,t1aa,t2aa;
>  show tables;
>  Tables_in_db
> +backup_history
> +backup_progress
>  columns_priv
>  db
>  event
> @@ -12,8 +14,6 @@ help_relation
>  help_topic
>  host
>  ndb_binlog_index
> -online_backup
> -online_backup_progress
>  plugin
>  proc
>  procs_priv
> 
> === modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql.result'
> --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result	2008-03-10 19:00:02 +0000
> +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result	2008-06-25 21:29:44 +0000
> @@ -2,6 +2,32 @@ SELECT * FROM information_schema.columns
>  WHERE table_schema = 'mysql'
>  ORDER BY table_schema, table_name, column_name;
> 
> TABLE_CATALOG	TABLE_SCHEMA	TABLE_NAME	COLUMN_NAME	ORDINAL_POSITION	COLUMN_DEFAULT	IS_NULLABLE	DATA_TYPE	CHARACTER_MAXIMUM_LENGTH	CHARACTER_OCTET_LENGTH	NUMERIC_PRECISION	NUMERIC_SCALE	CHARACTER_SET_NAME	COLLATION_NAME	COLUMN_TYPE	COLUMN_KEY	EXTRA	PRIVILEGES	COLUMN_COMMENT	STORAGE	FORMAT
>
> +NULL	mysql	backup_history	backup_file	15		NO	char	100	100	NULL	NULL	latin1	latin1_swedish_ci	char(100)			select,insert,update,references	The
> name of the file	Default	Default
>
> +NULL	mysql	backup_history	backup_id	1	NULL	NO	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)
> unsigned			select,insert,update,references	Surrogate key for (near) duplicate
> entries	Default	Default
>
> +NULL	mysql	backup_history	backup_state	5	NULL	NO	enum	14	14	NULL	NULL	latin1	latin1_swedish_ci	enum('complete','starting','validity
> point','running','error','cancel')			select,insert,update,references	Status of current
> operation	Default	Default
>
> +NULL	mysql	backup_history	binlog_file	4		NO	char	64	64	NULL	NULL	latin1	latin1_swedish_ci	char(64)			select,insert,update,references	The
> recorded binlog filename at time of backup/restore	Default	Default
> +NULL	mysql	backup_history	binlog_pos	3	0	NO	int	NULL	NULL	10	0	NULL	NULL	int(10)
> unsigned			select,insert,update,references	The recorded binlog position of
> backup/restore	Default	Default
>
> +NULL	mysql	backup_history	command	17		NO	varchar	512	512	NULL	NULL	latin1	latin1_swedish_ci	varchar(512)			select,insert,update,references	The
> command used to issue operation	Default	Default
>
> +NULL	mysql	backup_history	drivers	18		NO	varchar	100	100	NULL	NULL	latin1	latin1_swedish_ci	varchar(100)			select,insert,update,references	The
> name of the storage engines used in the operation	Default	Default
>
> +NULL	mysql	backup_history	error_num	7	0	NO	int	NULL	NULL	10	0	NULL	NULL	int(11)			select,insert,update,references	The
> error from this run 0 == none	Default	Default
>
> +NULL	mysql	backup_history	host_or_server_name	13		NO	char	30	30	NULL	NULL	latin1	latin1_swedish_ci	char(30)			select,insert,update,references	The
> server name where operation ran	Default	Default
> +NULL	mysql	backup_history	num_objects	8	0	NO	int	NULL	NULL	10	0	NULL	NULL	int(10)
> unsigned			select,insert,update,references	The number of objects in the
> backup	Default	Default
>
> +NULL	mysql	backup_history	operation	6	NULL	NO	enum	7	7	NULL	NULL	latin1	latin1_swedish_ci	enum('backup','restore')			select,insert,update,references	Type
> of operation	Default	Default
> +NULL	mysql	backup_history	process_id	2	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10)
> unsigned			select,insert,update,references	The process id that operation ran
> as	Default	Default
> +NULL	mysql	backup_history	start_time	11	0000-00-00
> 00:00:00	NO	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	The
> date/time of start of operation	Default	Default
> +NULL	mysql	backup_history	stop_time	12	0000-00-00
> 00:00:00	NO	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	The
> date/time of end of operation	Default	Default
>
> +NULL	mysql	backup_history	total_bytes	9	0	NO	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)
> unsigned			select,insert,update,references	The size of the backup repository in
> bytes	Default	Default
>
> +NULL	mysql	backup_history	username	14		NO	char	30	30	NULL	NULL	latin1	latin1_swedish_ci	char(30)			select,insert,update,references	The
> user name who ran the operation	Default	Default
>
> +NULL	mysql	backup_history	user_comment	16		NO	varchar	200	200	NULL	NULL	latin1	latin1_swedish_ci	varchar(200)			select,insert,update,references	The
> comment from user entered at command line	Default	Default
> +NULL	mysql	backup_history	validity_point_time	10	0000-00-00
> 00:00:00	NO	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	The
> time of the validity point.	Default	Default
>
> +NULL	mysql	backup_progress	backup_id	1	NULL	NO	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)
> unsigned			select,insert,update,references	Key for backup_history table
> entries	Default	Default
>
> +NULL	mysql	backup_progress	error_num	7	0	NO	int	NULL	NULL	10	0	NULL	NULL	int(11)			select,insert,update,references	The
> error from this run 0 == none	Default	Default
>
> +NULL	mysql	backup_progress	notes	8		NO	char	100	100	NULL	NULL	latin1	latin1_swedish_ci	char(100)			select,insert,update,references	Commentary
> from the backup engine	Default	Default
>
> +NULL	mysql	backup_progress	object	2		NO	char	30	30	NULL	NULL	latin1	latin1_swedish_ci	char(30)			select,insert,update,references	The
> object being operated on	Default	Default
>
> +NULL	mysql	backup_progress	progress	6	0	NO	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)
> unsigned			select,insert,update,references	The number of bytes processed	Default	Default
> +NULL	mysql	backup_progress	start_time	3	0000-00-00
> 00:00:00	NO	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	The
> date/time of start of operation	Default	Default
> +NULL	mysql	backup_progress	stop_time	4	0000-00-00
> 00:00:00	NO	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	The
> date/time of end of operation	Default	Default
>
> +NULL	mysql	backup_progress	total_bytes	5	0	NO	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)			select,insert,update,references	The
> size of the object in bytes	Default	Default
> 
> NULL	mysql	columns_priv	Column_name	5		NO	char	64	256	NULL	NULL	utf8	utf8_bin	char(64)	PRI		select,insert,update,references		Default	Default
> 
> NULL	mysql	columns_priv	Column_priv	7		NO	set	31	124	NULL	NULL	utf8	utf8_general_ci	set('Select','Insert','Update','References')			select,insert,update,references		Default	Default
> 
> NULL	mysql	columns_priv	Db	2		NO	char	64	256	NULL	NULL	utf8	utf8_bin	char(64)	PRI		select,insert,update,references		Default	Default
> @@ -107,32 +133,6 @@ NULL	mysql	ndb_binlog_index	orig_server_
> 
> NULL	mysql	ndb_binlog_index	Position	1	NULL	NO	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)
> unsigned			select,insert,update,references		Default	Default
>  NULL	mysql	ndb_binlog_index	schemaops	7	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10)
> unsigned			select,insert,update,references		Default	Default
>  NULL	mysql	ndb_binlog_index	updates	5	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10)
> unsigned			select,insert,update,references		Default	Default
>
> -NULL	mysql	online_backup	backup_file	15	NULL	YES	char	100	100	NULL	NULL	latin1	latin1_swedish_ci	char(100)			select,insert,update,references	The
> name of the file	Default	Default
>
> -NULL	mysql	online_backup	backup_id	1	NULL	NO	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)
> unsigned	PRI	auto_increment	select,insert,update,references	Surrogate key for (near)
> duplicate entries	Default	Default
>
> -NULL	mysql	online_backup	backup_state	5	NULL	NO	enum	14	14	NULL	NULL	latin1	latin1_swedish_ci	enum('complete','starting','validity
> point','running','error','cancel')			select,insert,update,references	Status of current
> operation	Default	Default
>
> -NULL	mysql	online_backup	binlog_file	4	NULL	YES	char	64	64	NULL	NULL	latin1	latin1_swedish_ci	char(64)			select,insert,update,references	The
> recorded binlog filename at time of backup/restore	Default	Default
> -NULL	mysql	online_backup	binlog_pos	3	0	YES	int	NULL	NULL	10	0	NULL	NULL	int(10)
> unsigned			select,insert,update,references	The recorded binlog position of
> backup/restore	Default	Default
>
> -NULL	mysql	online_backup	command	17	NULL	YES	varchar	512	512	NULL	NULL	latin1	latin1_swedish_ci	varchar(512)			select,insert,update,references	The
> command used to issue operation	Default	Default
>
> -NULL	mysql	online_backup	engines	18	NULL	YES	varchar	100	100	NULL	NULL	latin1	latin1_swedish_ci	varchar(100)			select,insert,update,references	The
> name of the storage engines used in the operation	Default	Default
>
> -NULL	mysql	online_backup	error_num	7	0	NO	int	NULL	NULL	10	0	NULL	NULL	int(11)			select,insert,update,references	The
> error from this run 0 == none	Default	Default
>
> -NULL	mysql	online_backup	host_or_server_name	13	NULL	YES	char	30	30	NULL	NULL	latin1	latin1_swedish_ci	char(30)			select,insert,update,references	The
> server name where operation ran	Default	Default
> -NULL	mysql	online_backup	num_objects	8	0	NO	int	NULL	NULL	10	0	NULL	NULL	int(10)
> unsigned			select,insert,update,references	The number of objects in the
> backup	Default	Default
>
> -NULL	mysql	online_backup	operation	6	NULL	NO	enum	7	7	NULL	NULL	latin1	latin1_swedish_ci	enum('backup','restore')			select,insert,update,references	Type
> of operation	Default	Default
> -NULL	mysql	online_backup	process_id	2	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10)
> unsigned			select,insert,update,references	The process id that operation ran
> as	Default	Default
>
> -NULL	mysql	online_backup	start_time	11	NULL	YES	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	The
> date/time of start of operation	Default	Default
>
> -NULL	mysql	online_backup	stop_time	12	NULL	YES	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	The
> date/time of end of operation	Default	Default
>
> -NULL	mysql	online_backup	total_bytes	9	NULL	YES	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)
> unsigned			select,insert,update,references	The size of the backup repository in
> bytes	Default	Default
>
> -NULL	mysql	online_backup	username	14	NULL	YES	char	30	30	NULL	NULL	latin1	latin1_swedish_ci	char(30)			select,insert,update,references	The
> user name who ran the operation	Default	Default
>
> -NULL	mysql	online_backup	user_comment	16	NULL	YES	varchar	200	200	NULL	NULL	latin1	latin1_swedish_ci	varchar(200)			select,insert,update,references	The
> comment from user entered at command line	Default	Default
>
> -NULL	mysql	online_backup	validity_point_time	10	NULL	YES	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	The
> time of the validity point.	Default	Default
>
> -NULL	mysql	online_backup_progress	backup_id	1	NULL	NO	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)
> unsigned			select,insert,update,references	Key for online_backup table
> entries	Default	Default
>
> -NULL	mysql	online_backup_progress	error_num	7	0	NO	int	NULL	NULL	10	0	NULL	NULL	int(11)			select,insert,update,references	The
> error from this run 0 == none	Default	Default
>
> -NULL	mysql	online_backup_progress	notes	8	NULL	YES	char	100	100	NULL	NULL	latin1	latin1_swedish_ci	char(100)			select,insert,update,references	Commentary
> from the backup engine	Default	Default
>
> -NULL	mysql	online_backup_progress	object	2	NULL	NO	char	30	30	NULL	NULL	latin1	latin1_swedish_ci	char(30)			select,insert,update,references	The
> object being operated on	Default	Default
>
> -NULL	mysql	online_backup_progress	progress	6	NULL	YES	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)
> unsigned			select,insert,update,references	The number of bytes processed	Default	Default
>
> -NULL	mysql	online_backup_progress	start_time	3	NULL	YES	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	The
> date/time of start of operation	Default	Default
>
> -NULL	mysql	online_backup_progress	stop_time	4	NULL	YES	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	The
> date/time of end of operation	Default	Default
>
> -NULL	mysql	online_backup_progress	total_bytes	5	NULL	YES	bigint	NULL	NULL	19	0	NULL	NULL	bigint(20)			select,insert,update,references	The
> size of the object in bytes	Default	Default
> 
> NULL	mysql	plugin	dl	2		NO	char	128	512	NULL	NULL	utf8	utf8_bin	char(128)			select,insert,update,references		Default	Default
> 
> NULL	mysql	plugin	name	1		NO	char	64	256	NULL	NULL	utf8	utf8_bin	char(64)	PRI		select,insert,update,references		Default	Default
> 
> NULL	mysql	proc	body	11	NULL	NO	longblob	4294967295	4294967295	NULL	NULL	NULL	NULL	longblob			select,insert,update,references		Default	Default
> @@ -314,6 +314,32 @@ FROM information_schema.columns
>  WHERE table_schema = 'mysql'
>  ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION;
> 
> COL_CML	TABLE_SCHEMA	TABLE_NAME	COLUMN_NAME	DATA_TYPE	CHARACTER_MAXIMUM_LENGTH	CHARACTER_OCTET_LENGTH	CHARACTER_SET_NAME	COLLATION_NAME	COLUMN_TYPE
> +NULL	mysql	backup_history	backup_id	bigint	NULL	NULL	NULL	NULL	bigint(20) unsigned
> +NULL	mysql	backup_history	process_id	int	NULL	NULL	NULL	NULL	int(10) unsigned
> +NULL	mysql	backup_history	binlog_pos	int	NULL	NULL	NULL	NULL	int(10) unsigned
>
> +1.0000	mysql	backup_history	binlog_file	char	64	64	latin1	latin1_swedish_ci	char(64)
>
> +1.0000	mysql	backup_history	backup_state	enum	14	14	latin1	latin1_swedish_ci	enum('complete','starting','validity
> point','running','error','cancel')
>
> +1.0000	mysql	backup_history	operation	enum	7	7	latin1	latin1_swedish_ci	enum('backup','restore')
> +NULL	mysql	backup_history	error_num	int	NULL	NULL	NULL	NULL	int(11)
> +NULL	mysql	backup_history	num_objects	int	NULL	NULL	NULL	NULL	int(10) unsigned
> +NULL	mysql	backup_history	total_bytes	bigint	NULL	NULL	NULL	NULL	bigint(20)
> unsigned
> +NULL	mysql	backup_history	validity_point_time	datetime	NULL	NULL	NULL	NULL	datetime
> +NULL	mysql	backup_history	start_time	datetime	NULL	NULL	NULL	NULL	datetime
> +NULL	mysql	backup_history	stop_time	datetime	NULL	NULL	NULL	NULL	datetime
>
> +1.0000	mysql	backup_history	host_or_server_name	char	30	30	latin1	latin1_swedish_ci	char(30)
> +1.0000	mysql	backup_history	username	char	30	30	latin1	latin1_swedish_ci	char(30)
>
> +1.0000	mysql	backup_history	backup_file	char	100	100	latin1	latin1_swedish_ci	char(100)
>
> +1.0000	mysql	backup_history	user_comment	varchar	200	200	latin1	latin1_swedish_ci	varchar(200)
>
> +1.0000	mysql	backup_history	command	varchar	512	512	latin1	latin1_swedish_ci	varchar(512)
>
> +1.0000	mysql	backup_history	drivers	varchar	100	100	latin1	latin1_swedish_ci	varchar(100)
> +NULL	mysql	backup_progress	backup_id	bigint	NULL	NULL	NULL	NULL	bigint(20) unsigned
> +1.0000	mysql	backup_progress	object	char	30	30	latin1	latin1_swedish_ci	char(30)
> +NULL	mysql	backup_progress	start_time	datetime	NULL	NULL	NULL	NULL	datetime
> +NULL	mysql	backup_progress	stop_time	datetime	NULL	NULL	NULL	NULL	datetime
> +NULL	mysql	backup_progress	total_bytes	bigint	NULL	NULL	NULL	NULL	bigint(20)
> +NULL	mysql	backup_progress	progress	bigint	NULL	NULL	NULL	NULL	bigint(20) unsigned
> +NULL	mysql	backup_progress	error_num	int	NULL	NULL	NULL	NULL	int(11)
> +1.0000	mysql	backup_progress	notes	char	100	100	latin1	latin1_swedish_ci	char(100)
>  4.0000	mysql	columns_priv	Host	char	60	240	utf8	utf8_bin	char(60)
>  4.0000	mysql	columns_priv	Db	char	64	256	utf8	utf8_bin	char(64)
>  4.0000	mysql	columns_priv	User	char	16	64	utf8	utf8_bin	char(16)
> @@ -419,32 +445,6 @@ NULL	mysql	ndb_binlog_index	schemaops	in
>  NULL	mysql	ndb_binlog_index	orig_server_id	int	NULL	NULL	NULL	NULL	int(10) unsigned
>  NULL	mysql	ndb_binlog_index	orig_epoch	bigint	NULL	NULL	NULL	NULL	bigint(20)
> unsigned
>  NULL	mysql	ndb_binlog_index	gci	int	NULL	NULL	NULL	NULL	int(10) unsigned
> -NULL	mysql	online_backup	backup_id	bigint	NULL	NULL	NULL	NULL	bigint(20) unsigned
> -NULL	mysql	online_backup	process_id	int	NULL	NULL	NULL	NULL	int(10) unsigned
> -NULL	mysql	online_backup	binlog_pos	int	NULL	NULL	NULL	NULL	int(10) unsigned
> -1.0000	mysql	online_backup	binlog_file	char	64	64	latin1	latin1_swedish_ci	char(64)
>
> -1.0000	mysql	online_backup	backup_state	enum	14	14	latin1	latin1_swedish_ci	enum('complete','starting','validity
> point','running','error','cancel')
>
> -1.0000	mysql	online_backup	operation	enum	7	7	latin1	latin1_swedish_ci	enum('backup','restore')
> -NULL	mysql	online_backup	error_num	int	NULL	NULL	NULL	NULL	int(11)
> -NULL	mysql	online_backup	num_objects	int	NULL	NULL	NULL	NULL	int(10) unsigned
> -NULL	mysql	online_backup	total_bytes	bigint	NULL	NULL	NULL	NULL	bigint(20) unsigned
> -NULL	mysql	online_backup	validity_point_time	datetime	NULL	NULL	NULL	NULL	datetime
> -NULL	mysql	online_backup	start_time	datetime	NULL	NULL	NULL	NULL	datetime
> -NULL	mysql	online_backup	stop_time	datetime	NULL	NULL	NULL	NULL	datetime
>
> -1.0000	mysql	online_backup	host_or_server_name	char	30	30	latin1	latin1_swedish_ci	char(30)
> -1.0000	mysql	online_backup	username	char	30	30	latin1	latin1_swedish_ci	char(30)
>
> -1.0000	mysql	online_backup	backup_file	char	100	100	latin1	latin1_swedish_ci	char(100)
>
> -1.0000	mysql	online_backup	user_comment	varchar	200	200	latin1	latin1_swedish_ci	varchar(200)
>
> -1.0000	mysql	online_backup	command	varchar	512	512	latin1	latin1_swedish_ci	varchar(512)
>
> -1.0000	mysql	online_backup	engines	varchar	100	100	latin1	latin1_swedish_ci	varchar(100)
> -NULL	mysql	online_backup_progress	backup_id	bigint	NULL	NULL	NULL	NULL	bigint(20)
> unsigned
>
> -1.0000	mysql	online_backup_progress	object	char	30	30	latin1	latin1_swedish_ci	char(30)
> -NULL	mysql	online_backup_progress	start_time	datetime	NULL	NULL	NULL	NULL	datetime
> -NULL	mysql	online_backup_progress	stop_time	datetime	NULL	NULL	NULL	NULL	datetime
> -NULL	mysql	online_backup_progress	total_bytes	bigint	NULL	NULL	NULL	NULL	bigint(20)
> -NULL	mysql	online_backup_progress	progress	bigint	NULL	NULL	NULL	NULL	bigint(20)
> unsigned
> -NULL	mysql	online_backup_progress	error_num	int	NULL	NULL	NULL	NULL	int(11)
>
> -1.0000	mysql	online_backup_progress	notes	char	100	100	latin1	latin1_swedish_ci	char(100)
>  4.0000	mysql	plugin	name	char	64	256	utf8	utf8_bin	char(64)
>  4.0000	mysql	plugin	dl	char	128	512	utf8	utf8_bin	char(128)
>  4.0000	mysql	proc	db	char	64	256	utf8	utf8_bin	char(64)
> 
> === modified file 'mysql-test/suite/funcs_1/r/is_statistics_mysql.result'
> --- a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result	2008-03-10 19:00:02
> +0000
> +++ b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result	2008-06-25 21:29:44
> +0000
> @@ -32,7 +32,6 @@ NULL	mysql	host	0	mysql	PRIMARY	2	Db	A	#
>  NULL	mysql	ndb_binlog_index	0	mysql	PRIMARY	1	epoch	A	#CARD#	NULL	NULL		BTREE		
> 
> NULL	mysql	ndb_binlog_index	0	mysql	PRIMARY	2	orig_server_id	A	#CARD#	NULL	NULL		BTREE		
> 
> NULL	mysql	ndb_binlog_index	0	mysql	PRIMARY	3	orig_epoch	A	#CARD#	NULL	NULL		BTREE		
> -NULL	mysql	online_backup	0	mysql	PRIMARY	1	backup_id	A	#CARD#	NULL	NULL		BTREE		
>  NULL	mysql	plugin	0	mysql	PRIMARY	1	name	A	#CARD#	NULL	NULL		BTREE		
>  NULL	mysql	proc	0	mysql	PRIMARY	1	db	A	#CARD#	NULL	NULL		BTREE		
>  NULL	mysql	proc	0	mysql	PRIMARY	2	name	A	#CARD#	NULL	NULL		BTREE		
> 
> === modified file 'mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result'
> --- a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result	2008-03-10
> 19:00:02 +0000
> +++ b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result	2008-06-25
> 21:29:44 +0000
> @@ -20,7 +20,6 @@ NULL	mysql	name	mysql	help_topic	UNIQUE
>  NULL	mysql	PRIMARY	mysql	help_topic	PRIMARY KEY
>  NULL	mysql	PRIMARY	mysql	host	PRIMARY KEY
>  NULL	mysql	PRIMARY	mysql	ndb_binlog_index	PRIMARY KEY
> -NULL	mysql	PRIMARY	mysql	online_backup	PRIMARY KEY
>  NULL	mysql	PRIMARY	mysql	plugin	PRIMARY KEY
>  NULL	mysql	PRIMARY	mysql	proc	PRIMARY KEY
>  NULL	mysql	PRIMARY	mysql	procs_priv	PRIMARY KEY
> 
> === modified file 'mysql-test/suite/funcs_1/r/is_tables_mysql.result'
> --- a/mysql-test/suite/funcs_1/r/is_tables_mysql.result	2008-03-10 19:00:02 +0000
> +++ b/mysql-test/suite/funcs_1/r/is_tables_mysql.result	2008-06-25 21:29:44 +0000
> @@ -14,11 +14,11 @@ WHERE table_schema = 'mysql'
>  ORDER BY table_schema,table_name;
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	columns_priv
> +TABLE_NAME	backup_history
>  TABLE_TYPE	BASE TABLE
> -ENGINE	MyISAM
> +ENGINE	CSV
>  VERSION	10
> -ROW_FORMAT	Fixed
> +ROW_FORMAT	Dynamic
>  TABLE_ROWS	#TBLR#
>  AVG_ROW_LENGTH	#ARL#
>  DATA_LENGTH	#DL#
> @@ -29,17 +29,17 @@ AUTO_INCREMENT	NULL
>  CREATE_TIME	#CRT#
>  UPDATE_TIME	#UT#
>  CHECK_TIME	#CT#
> -TABLE_COLLATION	utf8_bin
> +TABLE_COLLATION	latin1_swedish_ci
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	Column privileges
> +user_comment	
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	db
> +TABLE_NAME	backup_progress
>  TABLE_TYPE	BASE TABLE
> -ENGINE	MyISAM
> +ENGINE	CSV
>  VERSION	10
>  ROW_FORMAT	Fixed
>  TABLE_ROWS	#TBLR#
> @@ -52,19 +52,19 @@ AUTO_INCREMENT	NULL
>  CREATE_TIME	#CRT#
>  UPDATE_TIME	#UT#
>  CHECK_TIME	#CT#
> -TABLE_COLLATION	utf8_bin
> +TABLE_COLLATION	latin1_swedish_ci
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	Database privileges
> +user_comment	
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	event
> +TABLE_NAME	columns_priv
>  TABLE_TYPE	BASE TABLE
>  ENGINE	MyISAM
>  VERSION	10
> -ROW_FORMAT	Dynamic
> +ROW_FORMAT	Fixed
>  TABLE_ROWS	#TBLR#
>  AVG_ROW_LENGTH	#ARL#
>  DATA_LENGTH	#DL#
> @@ -75,15 +75,15 @@ AUTO_INCREMENT	NULL
>  CREATE_TIME	#CRT#
>  UPDATE_TIME	#UT#
>  CHECK_TIME	#CT#
> -TABLE_COLLATION	utf8_general_ci
> +TABLE_COLLATION	utf8_bin
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	Events
> +user_comment	Column privileges
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	func
> +TABLE_NAME	db
>  TABLE_TYPE	BASE TABLE
>  ENGINE	MyISAM
>  VERSION	10
> @@ -102,13 +102,13 @@ TABLE_COLLATION	utf8_bin
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	User defined functions
> +user_comment	Database privileges
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	general_log
> +TABLE_NAME	event
>  TABLE_TYPE	BASE TABLE
> -ENGINE	CSV
> +ENGINE	MyISAM
>  VERSION	10
>  ROW_FORMAT	Dynamic
>  TABLE_ROWS	#TBLR#
> @@ -125,11 +125,11 @@ TABLE_COLLATION	utf8_general_ci
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	General log
> +user_comment	Events
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	help_category
> +TABLE_NAME	func
>  TABLE_TYPE	BASE TABLE
>  ENGINE	MyISAM
>  VERSION	10
> @@ -144,19 +144,19 @@ AUTO_INCREMENT	NULL
>  CREATE_TIME	#CRT#
>  UPDATE_TIME	#UT#
>  CHECK_TIME	#CT#
> -TABLE_COLLATION	utf8_general_ci
> +TABLE_COLLATION	utf8_bin
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	help categories
> +user_comment	User defined functions
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	help_keyword
> +TABLE_NAME	general_log
>  TABLE_TYPE	BASE TABLE
> -ENGINE	MyISAM
> +ENGINE	CSV
>  VERSION	10
> -ROW_FORMAT	Fixed
> +ROW_FORMAT	Dynamic
>  TABLE_ROWS	#TBLR#
>  AVG_ROW_LENGTH	#ARL#
>  DATA_LENGTH	#DL#
> @@ -171,11 +171,11 @@ TABLE_COLLATION	utf8_general_ci
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	help keywords
> +user_comment	General log
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	help_relation
> +TABLE_NAME	help_category
>  TABLE_TYPE	BASE TABLE
>  ENGINE	MyISAM
>  VERSION	10
> @@ -194,15 +194,15 @@ TABLE_COLLATION	utf8_general_ci
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	keyword-topic relation
> +user_comment	help categories
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	help_topic
> +TABLE_NAME	help_keyword
>  TABLE_TYPE	BASE TABLE
>  ENGINE	MyISAM
>  VERSION	10
> -ROW_FORMAT	Dynamic
> +ROW_FORMAT	Fixed
>  TABLE_ROWS	#TBLR#
>  AVG_ROW_LENGTH	#ARL#
>  DATA_LENGTH	#DL#
> @@ -217,11 +217,11 @@ TABLE_COLLATION	utf8_general_ci
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	help topics
> +user_comment	help keywords
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	host
> +TABLE_NAME	help_relation
>  TABLE_TYPE	BASE TABLE
>  ENGINE	MyISAM
>  VERSION	10
> @@ -236,15 +236,15 @@ AUTO_INCREMENT	NULL
>  CREATE_TIME	#CRT#
>  UPDATE_TIME	#UT#
>  CHECK_TIME	#CT#
> -TABLE_COLLATION	utf8_bin
> +TABLE_COLLATION	utf8_general_ci
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	Host privileges;  Merged with database privileges
> +user_comment	keyword-topic relation
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	ndb_binlog_index
> +TABLE_NAME	help_topic
>  TABLE_TYPE	BASE TABLE
>  ENGINE	MyISAM
>  VERSION	10
> @@ -259,42 +259,42 @@ AUTO_INCREMENT	NULL
>  CREATE_TIME	#CRT#
>  UPDATE_TIME	#UT#
>  CHECK_TIME	#CT#
> -TABLE_COLLATION	latin1_swedish_ci
> +TABLE_COLLATION	utf8_general_ci
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	
> +user_comment	help topics
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	online_backup
> +TABLE_NAME	host
>  TABLE_TYPE	BASE TABLE
>  ENGINE	MyISAM
>  VERSION	10
> -ROW_FORMAT	Dynamic
> +ROW_FORMAT	Fixed
>  TABLE_ROWS	#TBLR#
>  AVG_ROW_LENGTH	#ARL#
>  DATA_LENGTH	#DL#
>  MAX_DATA_LENGTH	#MDL#
>  INDEX_LENGTH	#IL#
>  DATA_FREE	#DF#
> -AUTO_INCREMENT	1
> +AUTO_INCREMENT	NULL
>  CREATE_TIME	#CRT#
>  UPDATE_TIME	#UT#
>  CHECK_TIME	#CT#
> -TABLE_COLLATION	latin1_swedish_ci
> +TABLE_COLLATION	utf8_bin
>  CHECKSUM	NULL
>  CREATE_OPTIONS	#CO#
>  TABLE_COMMENT	#TC#
> -user_comment	
> +user_comment	Host privileges;  Merged with database privileges
>  Separator	-----------------------------------------------------
>  TABLE_CATALOG	NULL
>  TABLE_SCHEMA	mysql
> -TABLE_NAME	online_backup_progress
> +TABLE_NAME	ndb_binlog_index
>  TABLE_TYPE	BASE TABLE
>  ENGINE	MyISAM
>  VERSION	10
> -ROW_FORMAT	Fixed
> +ROW_FORMAT	Dynamic
>  TABLE_ROWS	#TBLR#
>  AVG_ROW_LENGTH	#ARL#
>  DATA_LENGTH	#DL#
> 
> === modified file 'mysql-test/t/backup_errors.test'
> --- a/mysql-test/t/backup_errors.test	2008-03-04 17:09:56 +0000
> +++ b/mysql-test/t/backup_errors.test	2008-06-25 21:29:44 +0000
> @@ -160,8 +160,8 @@ BACKUP DATABASE mysql, information_schem
>  
>  # Make backup copies of the tables first.
>  --echo Making copies of progress tables.
> -CREATE TABLE IF NOT EXISTS test.ob_copy LIKE mysql.online_backup;
> -CREATE TABLE IF NOT EXISTS test.obp_copy LIKE mysql.online_backup_progress;
> +CREATE TABLE IF NOT EXISTS test.ob_copy LIKE mysql.backup_history;
> +CREATE TABLE IF NOT EXISTS test.obp_copy LIKE mysql.backup_progress;
>  
>  # Create a database and put some data in it.
>  CREATE DATABASE test_ob_error;
> @@ -175,7 +175,7 @@ BACKUP DATABASE test_ob_error TO 'ob_err
>  --remove_file $MYSQLTEST_VARDIR/master-data/ob_err.bak
>  
>  # Drop one of the tables and try a backup.
> -DROP TABLE mysql.online_backup;
> +DROP TABLE mysql.backup_history;
>  
>  # Try to backup the database (should be error).
>  --echo Backup the database;
> @@ -188,11 +188,11 @@ SHOW ERRORS;
>  
>  # Restore the table
>  --echo Restoring the table
> -CREATE TABLE mysql.online_backup LIKE test.ob_copy;
> +CREATE TABLE mysql.backup_history LIKE test.ob_copy;
>  DROP TABLE test.ob_copy;
>  
>  # Drop one of the tables and try a backup.
> -DROP TABLE mysql.online_backup_progress;
> +DROP TABLE mysql.backup_progress;
>  
>  # Try to backup the database (should be error).
>  --echo Backup the database;
> @@ -205,7 +205,7 @@ SHOW ERRORS;
>  
>  # Restore the table
>  --echo Restoring the table
> -CREATE TABLE mysql.online_backup_progress LIKE test.obp_copy;
> +CREATE TABLE mysql.backup_progress LIKE test.obp_copy;
>  DROP TABLE test.obp_copy;
>  
>  DROP DATABASE test_ob_error;
> 
> === renamed file 'mysql-test/t/backup_progress.test' =>
> 'mysql-test/t/backup_log.test'
> --- a/mysql-test/t/backup_progress.test	2008-03-20 14:53:16 +0000
> +++ b/mysql-test/t/backup_log.test	2008-06-25 21:29:44 +0000
> @@ -77,14 +77,14 @@ let $wait_condition = SELECT state = "de
>  # Wait for row to be written to progress table.
>  --echo con1: Checking progress.
>  let $wait_condition = SELECT backup_state = "starting"
> -                      FROM mysql.online_backup
> +                      FROM mysql.backup_history
>                        WHERE command LIKE "BACKUP DATABASE backup_progress%";
>  --source include/wait_condition.inc
>  
>  --echo: Display progress
> -SELECT MAX(backup_id) INTO @bup_id FROM mysql.online_backup WHERE command LIKE
> "BACKUP DATABASE backup_progress%";
> +SELECT MAX(backup_id) INTO @bup_id FROM mysql.backup_history WHERE command LIKE
> "BACKUP DATABASE backup_progress%";
>  INSERT INTO backup_progress.t1_res (id) VALUES (@bup_id);
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  
>  --echo con1: Advance the lock.
>  SELECT get_lock("bp_running_state", 0);
> @@ -99,12 +99,12 @@ let $wait_condition = SELECT state = "de
>  # Wait for row to be written to progress table.
>  --echo con1: Checking progress.
>  let $wait_condition = SELECT backup_state = "running"
> -                      FROM mysql.online_backup
> +                      FROM mysql.backup_history
>                        WHERE command LIKE "BACKUP DATABASE backup_progress%";
>  --source include/wait_condition.inc
>  
>  --echo: Display progress
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  
>  --echo con1: Advance the lock.
>  SELECT get_lock("bp_vp_state", 0);
> @@ -119,12 +119,12 @@ let $wait_condition = SELECT state = "de
>  # Wait for row to be written to progress table.
>  --echo con1: Checking progress.
>  let $wait_condition = SELECT backup_state = "validity point"
> -                      FROM mysql.online_backup
> +                      FROM mysql.backup_history
>                        WHERE command LIKE "BACKUP DATABASE backup_progress%";
>  --source include/wait_condition.inc
>  
>  --echo: Display progress
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  
>  --echo con1: Advance the lock.
>  SELECT get_lock("bp_running_state", 0);
> @@ -139,12 +139,12 @@ let $wait_condition = SELECT state = "de
>  # Wait for row to be written to progress table.
>  --echo con1: Checking progress.
>  let $wait_condition = SELECT backup_state = "running"
> -                      FROM mysql.online_backup
> +                      FROM mysql.backup_history
>                        WHERE command LIKE "BACKUP DATABASE backup_progress%";
>  --source include/wait_condition.inc
>  
>  --echo: Display progress
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  
>  --echo con1: Advance the lock.
>  SELECT release_lock("bp_running_state");
> @@ -156,9 +156,9 @@ reap;
>  
>  #Show results
>  --replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 #
> ---query_vertical SELECT ob.* FROM mysql.online_backup AS ob JOIN
> backup_progress.t1_res AS t1 ON ob.backup_id = t1.id;
> +--query_vertical SELECT ob.* FROM mysql.backup_history AS ob JOIN
> backup_progress.t1_res AS t1 ON ob.backup_id = t1.id;
>  --replace_column 1 # 3 # 4 #
> -SELECT obp.* FROM mysql.online_backup_progress AS obp JOIN backup_progress.t1_res AS
> t1 ON obp.backup_id = t1.id;
> +SELECT obp.* FROM mysql.backup_progress AS obp JOIN backup_progress.t1_res AS t1 ON
> obp.backup_id = t1.id;
>  
>  connection con1;
>  
> @@ -185,15 +185,15 @@ let $wait_condition = SELECT state = "de
>  # Wait for row to be written to progress table.
>  --echo con1: Checking progress.
>  let $wait_condition = SELECT backup_state = "starting"
> -                      FROM mysql.online_backup
> +                      FROM mysql.backup_history
>                        WHERE command LIKE "RESTORE FROM
> 'backup_progress_orig.bak'%";
>  --source include/wait_condition.inc
>  
>  --echo: Display progress
>  select * from backup_progress.t1_res;
> -SELECT MAX(backup_id) INTO @bup_id FROM mysql.online_backup WHERE command LIKE
> "RESTORE FROM%";
> +SELECT MAX(backup_id) INTO @bup_id FROM mysql.backup_history WHERE command LIKE
> "RESTORE FROM%";
>  INSERT INTO backup_progress.t1_res (id) VALUES (@bup_id);
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  
>  --echo con1: Advance the lock.
>  SELECT get_lock("bp_running_state", 0);
> @@ -208,12 +208,12 @@ let $wait_condition = SELECT state = "de
>  # Wait for row to be written to progress table.
>  --echo con1: Checking progress.
>  let $wait_condition = SELECT backup_state = "running"
> -                      FROM mysql.online_backup
> +                      FROM mysql.backup_history
>                        WHERE command LIKE "RESTORE FROM
> 'backup_progress_orig.bak'%";
>  --source include/wait_condition.inc
>  
>  --echo: Display progress
> -SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1
> ON ob.backup_id = t1.id;
> +SELECT backup_state FROM mysql.backup_history AS ob JOIN backup_progress.t1_res as
> t1 ON ob.backup_id = t1.id;
>  
>  --echo con1: Advance the lock.
>  SELECT release_lock("bp_running_state");
> @@ -225,12 +225,12 @@ reap;
>  
>  #Show results
>  DELETE FROM backup_progress.t1_res;
> -SELECT MAX(backup_id) INTO @bup_id FROM mysql.online_backup WHERE command LIKE
> "RESTORE FROM%";
> +SELECT MAX(backup_id) INTO @bup_id FROM mysql.backup_history WHERE command LIKE
> "RESTORE FROM%";
>  INSERT INTO backup_progress.t1_res (id) VALUES (@bup_id);
>  --replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 #
> ---query_vertical SELECT ob.* FROM mysql.online_backup AS ob JOIN
> backup_progress.t1_res AS t1 ON ob.backup_id = t1.id;
> +--query_vertical SELECT ob.* FROM mysql.backup_history AS ob JOIN
> backup_progress.t1_res AS t1 ON ob.backup_id = t1.id;
>  --replace_column 1 # 3 # 4 #
> -SELECT obp.* FROM mysql.online_backup_progress AS obp JOIN backup_progress.t1_res AS
> t1 ON obp.backup_id = t1.id;
> +SELECT obp.* FROM mysql.backup_progress AS obp JOIN backup_progress.t1_res AS t1 ON
> obp.backup_id = t1.id;
>  
>  connection con1;
>  
> 
> === added file 'mysql-test/t/backup_log_output.test'
> --- a/mysql-test/t/backup_log_output.test	1970-01-01 00:00:00 +0000
> +++ b/mysql-test/t/backup_log_output.test	2008-06-25 21:29:44 +0000
> @@ -0,0 +1,286 @@
> +#
> +# Test backup log output options
> +#
> +# This test tests the --log-backup-output options for writing backup log
> +# information. The choices are FILE | TABLE | FILE,TABLE | NONE
> +#
> +
> +--source include/not_embedded.inc
> +
> +--echo Reset backupdir 
> +SET @@global.backupdir = @@global.datadir;
> +
> +connect (con1,localhost,root,,,,);
> +--echo con1
> +connection con1;
> +
> +--echo Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +SHOW VARIABLES LIKE 'log_backup_output';
> +
> +--echo '---Checking backup logs when log_backup_output is NONE---'
> +--echo '---and the backup logs are turned off                 ---'
> +
> +SET @@global.log_backup_output = 'NONE';
> +SET @@global.backup_history_log = 'OFF';
> +SET @@global.backup_progress_log = 'OFF';
> +
> +--echo Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +SHOW VARIABLES LIKE 'log_backup_output';
> +
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +
> +--echo Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +SELECT count(*) FROM mysql.backup_progress;
> +
> +--disable_warnings
> +DROP DATABASE IF EXISTS bup_log;
> +--enable_warnings
> +
> +--echo Create a database and back it up
> +CREATE DATABASE bup_log;
> +CREATE TABLE bup_log.t1(a INT);
> +INSERT INTO bup_log.t1 VALUES (1), (2), (3);
> +
> +--replace_column 1 #
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +
> +--echo Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +SELECT count(*) FROM mysql.backup_progress;
> +
> +FLUSH BACKUP LOGS;
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_history.log
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_progress.log
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/master-data/bup_log.bak
> +
> +--echo '---Checking backup logs when log_backup_output is TABLE---'
> +
> +SET @@global.log_backup_output = 'TABLE';
> +
> +--echo turning backup logs back on
> +SET @@global.backup_history_log = 'ON';
> +SET @@global.backup_progress_log = 'ON';
> +
> +--echo Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +SHOW VARIABLES LIKE 'log_backup_output';
> +
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +
> +--replace_column 1 #
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +
> +--echo Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +SELECT count(*) FROM mysql.backup_progress;
> +
> +FLUSH BACKUP LOGS;
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_history.log
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_progress.log
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/master-data/bup_log.bak
> +
> +--echo '---Checking backup logs when log_backup_output is TABLE---'
> +--echo '---and the history log is turned off                   ---'
> +
> +SET @@global.backup_history_log = 'ON';
> +SET @@global.backup_progress_log = 'OFF';
> +
> +--echo Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +SHOW VARIABLES LIKE 'log_backup_output';
> +
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +
> +--echo Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +SELECT count(*) FROM mysql.backup_progress;
> +
> +--replace_column 1 #
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +
> +--echo Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +SELECT count(*) FROM mysql.backup_progress;
> +
> +FLUSH BACKUP LOGS;
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_history.log
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_progress.log
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/master-data/bup_log.bak
> +
> +--echo '---Checking backup logs when log_backup_output is TABLE---'
> +--echo '---and the progress log is turned off                 ---'
> +
> +SET @@global.backup_history_log = 'OFF';
> +SET @@global.backup_progress_log = 'ON';
> +
> +--echo Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +SHOW VARIABLES LIKE 'log_backup_output';
> +
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +
> +--echo Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +SELECT count(*) FROM mysql.backup_progress;
> +
> +--replace_column 1 #
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +
> +--echo Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +SELECT count(*) FROM mysql.backup_progress;
> +
> +FLUSH BACKUP LOGS;
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_history.log
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_progress.log
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/master-data/bup_log.bak
> +
> +--echo '---Checking backup logs when log_backup_output is FILE---'
> +
> +SET @@global.log_backup_output = 'FILE';
> +
> +--echo turning backup logs back on
> +SET @@global.backup_history_log = 'ON';
> +SET @@global.backup_progress_log = 'ON';
> +
> +--echo Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +SHOW VARIABLES LIKE 'log_backup_output';
> +
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +
> +--replace_column 1 #
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +
> +--echo Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +SELECT count(*) FROM mysql.backup_progress;
> +
> +FLUSH BACKUP LOGS;
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_history.log
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_progress.log
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/master-data/bup_log.bak
> +
> +--echo '---Checking backup logs when log_backup_output is TABLE, FILE---'
> +
> +SET @@global.log_backup_output = 'TABLE,FILE';
> +
> +--echo Display backup variables
> +SHOW VARIABLES LIKE 'backup_history_log';
> +SHOW VARIABLES LIKE 'backup_progress_log';
> +SHOW VARIABLES LIKE 'log_backup_output';
> +
> +TRUNCATE TABLE mysql.backup_history;
> +TRUNCATE TABLE mysql.backup_progress;
> +
> +--replace_column 1 #
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +
> +--echo Show the size of the logs
> +SELECT count(*) FROM mysql.backup_history;
> +SELECT count(*) FROM mysql.backup_progress;
> +
> +FLUSH BACKUP LOGS;
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_history.log
> +--file_exists $MYSQLTEST_VARDIR/master-data/backup_progress.log
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/master-data/bup_log.bak
> +
> +SET @@global.log_backup_output = 'TABLE';
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/master-data/bup_log.bak
> +
> +#
> +# The following tests the backupdir variable by changing it to
> +# redirect the output of the backup command/input of the restore
> +# command.
> +#
> +
> +--error 0,1,2
> +rmdir $MYSQLTEST_VARDIR/tmp/backup;
> +
> +--let $backup_out_path=$MYSQLTEST_VARDIR/master-data
> +
> +--echo Examine the backupdir
> +SHOW VARIABLES LIKE 'backupdir%';
> +
> +--echo Create a directory for backup images
> +mkdir $MYSQLTEST_VARDIR/tmp/backup;
> +
> +--echo Reset backupdir 
> +SET @@global.backupdir = '../tmp/backup';
> +
> +--echo Examine the backupdir
> +SHOW VARIABLES LIKE 'backupdir%';
> +
> +--echo Perform backup
> +--replace_column 1 #
> +BACKUP DATABASE bup_log TO 'bup_log.bak';
> +
> +--echo Ensure backup image file went to the correct location
> +--echo $MYSQLTEST_DIR/backup/bup_log.bak
> +--file_exists $MYSQLTEST_VARDIR/tmp/backup/bup_log.bak
> +
> +--echo Perform restore
> +--replace_column 1 #
> +RESTORE FROM 'bup_log.bak';
> +
> +--echo Now do the backup and restore by specifying a path.
> +
> +--echo Perform backup
> +--replace_column 1 #
> +BACKUP DATABASE bup_log TO '../tmp/bup_log.bak';
> +
> +--echo Ensure backup image file went to the correct location
> +--file_exists $MYSQLTEST_VARDIR/tmp/bup_log.bak
> +
> +--echo Perform restore
> +--replace_column 1 #
> +RESTORE FROM '../tmp/bup_log.bak';
> +
> +--echo Reset backupdir 
> +SET @@global.backupdir = @@global.datadir;
> +
> +--echo Examine the backupdir
> +SHOW VARIABLES LIKE 'backupdir%';
> +
> +--echo Cleanup
> +DROP DATABASE bup_log;
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/tmp/bup_log.bak
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/tmp/backup/bup_log.bak
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/master-data/bup_log.bak
> +
> +--error 0,1
> +rmdir $MYSQLTEST_VARDIR/tmp/backup;
> 
> === modified file 'mysql-test/t/backup_no_be.test'
> --- a/mysql-test/t/backup_no_be.test	2008-05-10 08:42:49 +0000
> +++ b/mysql-test/t/backup_no_be.test	2008-06-25 21:29:44 +0000
> @@ -7,7 +7,7 @@
>  # Test uses error injection activated with 'backup_test_dummy_be_factory' keyword.
>  # The code is injected into has_native_backup() function in backup_info.cc.
>  # When activated, it overwrites the native MyISAM backup factory with a dummy one 
> -# which never creates an engine. This change is permanent and can not be reversed by
> 
> +# which never creates a driver. This change is permanent and can not be reversed by
> 
>  # disabling the error injection code. The only way to restore the original situation
> 
>  # is by restarting the server. Therefore:
>  #
> @@ -41,16 +41,16 @@ SELECT @@debug;
>  BACKUP DATABASE db1 TO 'db1.bak';
>  SHOW WARNINGS;
>  
> -# See what engines were used for BACKUP
> +# See what drivers were used for BACKUP
>  
> -SELECT max(backup_id) INTO @id FROM mysql.online_backup 
> +SELECT max(backup_id) INTO @id FROM mysql.backup_history 
>  WHERE command LIKE 'BACKUP DATABASE db1 %';
>  
> -# Note: right now default engine will be used (as below) because there is no
> +# Note: right now default driver will be used (as below) because there is no
>  # native backup for MyISAM. But when it is added, the SELECT below should list
> native 
> -# MYISAM engine.
> +# MYISAM driver.
>  
> -SELECT engines FROM mysql.online_backup WHERE backup_id=@id;
> +SELECT drivers FROM mysql.backup_history WHERE backup_id=@id;
>  
>  # Now see what happens when injected code is activated and MyISAM uses the dummy
>  # factory function.
> @@ -59,7 +59,7 @@ SET SESSION debug="d,backup_test_dummy_b
>  SELECT @@debug;
>  
>  # The following BACKUP command should generate a warning but otherwise
> -# should complete using the default backup engine.
> +# should complete using the default backup driver.
>  # We disable warnings temporarily and show them with SHOW WARNINGS instead. This is
> to 
>  # avoid showing message codes (which change sometimes)
>  
> @@ -73,12 +73,12 @@ BACKUP DATABASE db1 TO 'db1.bak';
>  --replace_column 2 #
>  SHOW WARNINGS;
>  
> -# See what engines were used for BACKUP
> +# See what drivers were used for BACKUP
>  
> -SELECT max(backup_id) INTO @id FROM mysql.online_backup 
> +SELECT max(backup_id) INTO @id FROM mysql.backup_history 
>  WHERE command LIKE 'BACKUP DATABASE db1 %';
>  
> -SELECT engines FROM mysql.online_backup WHERE backup_id=@id;
> +SELECT drivers FROM mysql.backup_history WHERE backup_id=@id;
>  
>  # check that we can restore from the created image.
>  
> 
> === modified file 'mysql-test/t/disabled.def'
> --- a/mysql-test/t/disabled.def	2008-06-04 13:20:03 +0000
> +++ b/mysql-test/t/disabled.def	2008-06-25 21:29:44 +0000
> @@ -20,7 +20,7 @@ user_limits          : Bug#23921 2007-12
>  backup                :BUG#34235 pending replacement of test facility with WL#4259
>  backup_commit_blocker :BUG#34235 pending replacement of test facility with WL#4259
>  backup_ddl_blocker    :BUG#34235 pending replacement of test facility with WL#4259
> -backup_progress       :BUG#34235 pending replacement of test facility with WL#4259
> +backup_log            :BUG#34235 pending replacement of test facility with WL#4259
>  backup_security       :BUG#34235 pending replacement of test facility with WL#4259
>  backup_snapshot       :BUG#34235 pending replacement of test facility with WL#4259
>  backup_no_engine     : Bug#36021 2008-04-13 rsomla server crashes when openning
> table with unknown storage engine
> 
> === modified file 'mysql-test/t/mysqldump.test'
> --- a/mysql-test/t/mysqldump.test	2008-04-07 15:32:14 +0000
> +++ b/mysql-test/t/mysqldump.test	2008-06-25 21:29:44 +0000
> @@ -1379,7 +1379,7 @@ insert into u1 values (4);
>  create view v1 (c1) as select * from t1;
>  
>  # Backup should not fail for Bug #21527. Flush priviliges test begins.
> ---exec $MYSQL_DUMP --skip-comments --add-drop-table --flush-privileges
> --ignore-table=mysql.general_log --ignore-table=mysql.slow_log
> --ignore-table=mysql.online_backup --ignore-table=mysql.online_backup_progress --databases
> mysqldump_myDB mysql > $MYSQLTEST_VARDIR/tmp/bug21527.sql
> +--exec $MYSQL_DUMP --skip-comments --add-drop-table --flush-privileges
> --ignore-table=mysql.general_log --ignore-table=mysql.slow_log
> --ignore-table=mysql.backup_history --ignore-table=mysql.backup_progress --databases
> mysqldump_myDB mysql > $MYSQLTEST_VARDIR/tmp/bug21527.sql
>  
>  # Clean up
>  connection root;
> 
> === modified file 'mysql-test/t/system_mysql_db_fix30020.test'
> --- a/mysql-test/t/system_mysql_db_fix30020.test	2007-11-30 06:02:04 +0000
> +++ b/mysql-test/t/system_mysql_db_fix30020.test	2008-06-25 21:29:44 +0000
> @@ -102,7 +102,7 @@ DROP TABLE db, host, user, func, plugin,
>  procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc,
>  time_zone, time_zone_leap_second, time_zone_name, time_zone_transition,
>  time_zone_transition_type, general_log, slow_log, event, ndb_binlog_index,
> -online_backup, online_backup_progress;
> +backup_history, backup_progress;
>  
>  -- enable_query_log
>  
> 
> === modified file 'mysql-test/t/system_mysql_db_fix40123.test'
> --- a/mysql-test/t/system_mysql_db_fix40123.test	2007-11-30 06:04:31 +0000
> +++ b/mysql-test/t/system_mysql_db_fix40123.test	2008-06-25 21:29:44 +0000
> @@ -76,7 +76,7 @@ CREATE TABLE time_zone_leap_second (   T
>  -- disable_query_log
>  
>  # Drop all tables created by this test
> -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv,
> servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone,
> time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type,
> general_log, slow_log, event, ndb_binlog_index, online_backup, online_backup_progress;
> +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv,
> servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone,
> time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type,
> general_log, slow_log, event, ndb_binlog_index, backup_history, backup_progress;
>  
>  -- enable_query_log
>  
> 
> === modified file 'mysql-test/t/system_mysql_db_fix50030.test'
> --- a/mysql-test/t/system_mysql_db_fix50030.test	2007-11-30 06:04:31 +0000
> +++ b/mysql-test/t/system_mysql_db_fix50030.test	2008-06-25 21:29:44 +0000
> @@ -75,7 +75,7 @@ INSERT INTO servers VALUES ('test','loca
>  -- disable_query_log
>  
>  # Drop all tables created by this test
> -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv,
> servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone,
> time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type,
> general_log, slow_log, event, ndb_binlog_index, online_backup, online_backup_progress;
> +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv,
> servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone,
> time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type,
> general_log, slow_log, event, ndb_binlog_index, backup_history, backup_progress;
>  
>  -- enable_query_log
>  
> 
> === modified file 'mysql-test/t/system_mysql_db_fix50117.test'
> --- a/mysql-test/t/system_mysql_db_fix50117.test	2008-02-27 10:04:05 +0000
> +++ b/mysql-test/t/system_mysql_db_fix50117.test	2008-06-25 21:29:44 +0000
> @@ -94,7 +94,7 @@ CREATE TABLE IF NOT EXISTS ndb_binlog_in
>  -- disable_query_log
>  
>  # Drop all tables created by this test
> -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv,
> servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone,
> time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type,
> general_log, slow_log, event, ndb_binlog_index, online_backup, online_backup_progress;
> +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv,
> servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone,
> time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type,
> general_log, slow_log, event, ndb_binlog_index, backup_history, backup_progress;
>  
>  -- enable_query_log
>  
> 
> === modified file 'scripts/mysql_system_tables.sql'
> --- a/scripts/mysql_system_tables.sql	2008-02-27 10:04:05 +0000
> +++ b/scripts/mysql_system_tables.sql	2008-06-25 21:29:44 +0000
> @@ -83,10 +83,10 @@ DROP PREPARE stmt;
>  CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin
> NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob
> NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
> execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field
> ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND')
> default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed
> DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status
> ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion
> ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode 
> set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE'
,'!
> 
> NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
> DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default
> '', originator int(10) NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT
> 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32)
> collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY
> (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
>  
>  
> -CREATE TABLE IF NOT EXISTS online_backup ( backup_id BIGINT UNSIGNED PRIMARY KEY
> AUTO_INCREMENT COMMENT 'Surrogate key for (near) duplicate entries', process_id INT
> UNSIGNED NOT NULL COMMENT 'The process id that operation ran as', binlog_pos INT UNSIGNED
> DEFAULT 0 COMMENT 'The recorded binlog position of backup/restore', binlog_file CHAR(64)
> COMMENT 'The recorded binlog filename at time of backup/restore', backup_state
> ENUM('complete', 'starting', 'validity point', 'running', 'error', 'cancel') NOT NULL
> COMMENT 'Status of current operation', operation ENUM('backup', 'restore') NOT NULL
> COMMENT 'Type of operation', error_num INT NOT NULL DEFAULT 0 COMMENT 'The error from this
> run 0 == none', num_objects INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'The number of objects
> in the backup', total_bytes BIGINT UNSIGNED COMMENT 'The size of the backup repository in
> bytes', validity_point_time datetime COMMENT 'The time of the validity point.', start_time
> datetime COMMENT 'The date/tim
e !
>  of start of operation', stop_time datetime COMMENT 'The date/time of end of
> operation', host_or_server_name CHAR (30) COMMENT 'The server name where operation ran',
> username CHAR (30) COMMENT 'The user name who ran the operation', backup_file CHAR (100)
> COMMENT 'The name of the file', user_comment VARCHAR (200) DEFAULT NULL COMMENT 'The
> comment from user entered at command line', command VARCHAR (512) COMMENT 'The command
> used to issue operation', engines VARCHAR (100) COMMENT 'The name of the storage engines
> used in the operation') ENGINE=MYISAM;
> +CREATE TABLE IF NOT EXISTS backup_history ( backup_id BIGINT UNSIGNED NOT NULL
> COMMENT 'Surrogate key for (near) duplicate entries', process_id INT UNSIGNED NOT NULL
> COMMENT 'The process id that operation ran as', binlog_pos INT UNSIGNED  NOT NULL DEFAULT
> 0 COMMENT 'The recorded binlog position of backup/restore', binlog_file CHAR(64)  NOT NULL
> DEFAULT '' COMMENT 'The recorded binlog filename at time of backup/restore', backup_state
> ENUM('complete', 'starting', 'validity point', 'running', 'error', 'cancel') NOT NULL
> COMMENT 'Status of current operation', operation ENUM('backup', 'restore') NOT NULL
> COMMENT 'Type of operation', error_num INT NOT NULL DEFAULT 0 COMMENT 'The error from this
> run 0 == none', num_objects INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'The number of objects
> in the backup', total_bytes BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'The size of the
> backup repository in bytes', validity_point_time datetime NOT NULL DEFAULT 0 COMMENT 'The
> time of the validit
y !
>  point.', start_time datetime NOT NULL DEFAULT 0 COMMENT 'The date/time of start of
> operation', stop_time datetime NOT NULL DEFAULT 0 COMMENT 'The date/time of end of
> operation', host_or_server_name CHAR (30)  NOT NULL DEFAULT '' COMMENT 'The server name
> where operation ran', username CHAR (30)  NOT NULL DEFAULT '' COMMENT 'The user name who
> ran the operation', backup_file CHAR (100) NOT NULL DEFAULT ''  COMMENT 'The name of the
> file', user_comment VARCHAR (200) NOT NULL DEFAULT ''  COMMENT 'The comment from user
> entered at command line', command VARCHAR (512)  NOT NULL DEFAULT '' COMMENT 'The command
> used to issue operation', drivers VARCHAR (100) NOT NULL DEFAULT '' COMMENT 'The name of
> the storage engines used in the operation') ENGINE=CSV;
>  
>  
> -CREATE TABLE IF NOT EXISTS online_backup_progress ( backup_id BIGINT UNSIGNED NOT
> NULL COMMENT 'Key for online_backup table entries', object CHAR (30) NOT NULL COMMENT 'The
> object being operated on', start_time datetime COMMENT 'The date/time of start of
> operation', stop_time datetime COMMENT 'The date/time of end of operation', total_bytes
> BIGINT COMMENT 'The size of the object in bytes', progress BIGINT UNSIGNED COMMENT 'The
> number of bytes processed', error_num INT NOT NULL DEFAULT 0 COMMENT 'The error from this
> run 0 == none', notes CHAR(100) COMMENT 'Commentary from the backup engine')
> ENGINE=MYISAM;
> +CREATE TABLE IF NOT EXISTS backup_progress ( backup_id BIGINT UNSIGNED NOT NULL
> COMMENT 'Key for backup_history table entries', object CHAR (30) NOT NULL DEFAULT ''
> COMMENT 'The object being operated on', start_time datetime NOT NULL DEFAULT 0 COMMENT
> 'The date/time of start of operation', stop_time datetime NOT NULL DEFAULT 0 COMMENT 'The
> date/time of end of operation', total_bytes BIGINT NOT NULL DEFAULT 0 COMMENT 'The size of
> the object in bytes', progress BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'The number of
> bytes processed', error_num INT NOT NULL DEFAULT 0 COMMENT 'The error from this run 0 ==
> none', notes CHAR(100) NOT NULL DEFAULT '' COMMENT 'Commentary from the backup engine')
> ENGINE=CSV;
>  
>  
>  CREATE TABLE IF NOT EXISTS ndb_binlog_index (Position BIGINT UNSIGNED NOT NULL, File
> VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts INT UNSIGNED NOT NULL,
> updates INT UNSIGNED NOT NULL, deletes INT UNSIGNED NOT NULL, schemaops INT UNSIGNED NOT
> NULL, orig_server_id INT UNSIGNED NOT NULL, orig_epoch BIGINT UNSIGNED NOT NULL, gci INT
> UNSIGNED NOT NULL, PRIMARY KEY(epoch, orig_server_id, orig_epoch)) ENGINE=MYISAM;
> 
> === modified file 'sql/backup/CMakeLists.txt'
> --- a/sql/backup/CMakeLists.txt	2008-05-27 19:47:15 +0000
> +++ b/sql/backup/CMakeLists.txt	2008-06-25 21:29:44 +0000
> @@ -25,7 +25,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/
>  SET(BACKUP_SOURCES stream.cc logger.cc kernel.cc
>                 image_info.cc backup_info.cc data_backup.cc
>                 be_default.cc buffer_iterator.cc
> -               be_snapshot.cc be_thread.cc backup_progress.cc
> +               be_snapshot.cc be_thread.cc 
>                 backup_test.cc be_nodata.cc)
>  
>  IF(NOT SOURCE_SUBLIBS)
> 
> === modified file 'sql/backup/Makefile.am'
> --- a/sql/backup/Makefile.am	2008-05-14 00:24:06 +0000
> +++ b/sql/backup/Makefile.am	2008-06-25 21:29:44 +0000
> @@ -37,7 +37,6 @@ libbackup_la_SOURCES = \
>    be_nodata.cc \
>    buffer_iterator.cc \
>    be_thread.cc \
> -  backup_progress.cc \
>    backup_test.cc
>  
>  libbackup_la_LIBADD = libbackupstream.la
> @@ -66,7 +65,6 @@ noinst_HEADERS = \
>    be_nodata.h \
>    buffer_iterator.h \
>    be_thread.h \
> -  backup_progress.h \
>    stream_v1.h \
>    stream_v1_services.h \
>    backup_test.h
> 


> === modified file 'sql/backup/backup_info.cc'
> --- a/sql/backup/backup_info.cc	2008-05-28 15:25:24 +0000
> +++ b/sql/backup/backup_info.cc	2008-06-25 21:29:44 +0000
> @@ -376,7 +376,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_ctx.report_engine(m_snap[n]->name());

Why this rename?

>    
>    m_state= CLOSED;
>    return 0;
> 
> === modified file 'sql/backup/backup_kernel.h'
> --- a/sql/backup/backup_kernel.h	2008-05-05 15:06:40 +0000
> +++ b/sql/backup/backup_kernel.h	2008-06-25 21:29:44 +0000
> @@ -129,7 +129,7 @@ bool Backup_restore_ctx::is_valid() cons
>    return m_error == 0;
>  }
>  
> -/// Return global id of the backup/restore operation.
> +/// Return global history data of the backup/restore operation.
>  inline
>  ulonglong Backup_restore_ctx::op_id() const
>  {
> 
> === removed file 'sql/backup/backup_progress.cc'
> --- a/sql/backup/backup_progress.cc	2008-03-25 10:04:09 +0000
> +++ b/sql/backup/backup_progress.cc	1970-01-01 00:00:00 +0000
> @@ -1,907 +0,0 @@
> -/* Copyright (C) 2004-2007 MySQL AB
> -
> -   This program is free software; you can redistribute it and/or modify
> -   it under the terms of the GNU General Public License as published by
> -   the Free Software Foundation; version 2 of the License.
> -
> -   This program is distributed in the hope that it will be useful,
> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> -   GNU General Public License for more details.
> -
> -   You should have received a copy of the GNU General Public License
> -   along with this program; if not, write to the Free Software
> -   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
> -*/
> -
> -/**
> -   @file backup_progress.cc
> -
> -   This file contains the methods to create and update rows in the 
> -   online backup progress tables.
> -
> -   @todo Decide on what "size" means. Does it mean number of rows or number
> -         of byte?
> -  */
> -
> -#include "../mysql_priv.h"
> -#include "backup_progress.h"
> -#include "be_thread.h"
> -
> -/* BACKUP_HISTORY_LOG name */
> -LEX_STRING BACKUP_HISTORY_LOG_NAME= {C_STRING_WITH_LEN("online_backup")};
> -
> -/* BACKUP_PROGRESS_LOG name */
> -LEX_STRING BACKUP_PROGRESS_LOG_NAME= {C_STRING_WITH_LEN("online_backup_progress")};
> -
> -/**
> -   Check online backup progress tables.
> -
> -   This method attempts to open the online backup progress tables. It returns
> -   an error if either table is not present or cannot be opened.
> -
> -   @param[in] THD * The current thread.
> -
> -   @returns Information whether backup progress tables can be used.
> -
> -   @retval FALSE  success
> -   @retval TRUE  failed to open one of the tables
> -  */
> -my_bool check_ob_progress_tables(THD *thd)
> -{
> -  TABLE_LIST tables;
> -  my_bool ret= FALSE;
> -
> -  DBUG_ENTER("check_ob_progress_tables");
> -
> -  /* Check mysql.online_backup */
> -  tables.init_one_table("mysql", "online_backup", TL_READ);
> -  if (simple_open_n_lock_tables(thd, &tables))
> -  {
> -    ret= TRUE;
> -    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
> -    DBUG_RETURN(ret);
> -  }
> -  close_thread_tables(thd);
> -
> -  /* Check mysql.online_backup_progress */
> -  tables.init_one_table("mysql", "online_backup_progress", TL_READ);
> -  if (simple_open_n_lock_tables(thd, &tables))
> -  {
> -    ret= TRUE;
> -    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
> -    DBUG_RETURN(ret);
> -  }
> -  close_thread_tables(thd);
> -  DBUG_RETURN(ret);
> -}
> -
> -/**
> -   Get text string for state.
> -
> -   @param enum_backup_state  state        The current state of the operation
> -
> -   @returns char * a text string for state.
> -  */
> -void get_state_string(enum_backup_state state, String *str)
> -{
> -  DBUG_ENTER("get_state_string()");
> -
> -  str->length(0);
> -  switch (state) {
> -  case BUP_COMPLETE:
> -    str->append("complete");
> -    break;
> -  case BUP_STARTING:
> -    str->append("starting");
> -    break;
> -  case BUP_VALIDITY_POINT:
> -    str->append("validity point");
> -    break;
> -  case BUP_RUNNING:
> -    str->append("running");
> -    break;
> -  case BUP_ERRORS:
> -    str->append("error");
> -    break;
> -  case BUP_CANCEL:
> -    str->append("cancel");
> -    break;
> -  default:
> -    str->append("unknown");
> -    break;
> -  }
> -  DBUG_VOID_RETURN;
> -}
> -
> -/**
> -  Write the backup log entry for the backup history log to a table.
> -
> -  This method creates a new row in the backup history log with the
> -  information provided.
> -
> -  @param[IN]   thd          The current thread
> -  @param[OUT]  backup_id    The new row id for the backup history
> -  @param[IN]   process_id   The process id of the operation 
> -  @param[IN]   state        The current state of the operation
> -  @param[IN]   operation    The current operation (backup or restore)
> -  @param[IN]   error_num    The error number
> -  @param[IN]   user_comment The user's comment specified in the
> -                            command (not implemented yet)
> -  @param[IN]   backup_file  The name of the target file
> -  @param[IN]   command      The actual command entered
> -
> -  @retval TRUE if error.
> -
> -  @todo Add internal error handler to handle errors that occur on
> -        open. See  thd->push_internal_handler(&error_handler).
> -*/
> -bool backup_history_log_write(THD *thd, 
> -                              ulonglong *backup_id,
> -                              int process_id,
> -                              enum_backup_state state,
> -                              enum_backup_operation operation,
> -                              int error_num,
> -                              const char *user_comment,
> -                              const char *backup_file,
> -                              const char *command)
> -{
> -  TABLE_LIST table_list;
> -  TABLE *table= NULL;
> -  bool result= TRUE;
> -  bool need_close= FALSE;
> -  bool need_rnd_end= FALSE;
> -  Open_tables_state open_tables_backup;
> -  bool save_time_zone_used;
> -  char *host= current_thd->security_ctx->host; // host name
> -  char *user= current_thd->security_ctx->user; // user name
> -
> -  save_time_zone_used= thd->time_zone_used;
> -  bzero(& table_list, sizeof(TABLE_LIST));
> -  table_list.alias= table_list.table_name= BACKUP_HISTORY_LOG_NAME.str;
> -  table_list.table_name_length= BACKUP_HISTORY_LOG_NAME.length;
> -
> -  table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
> -
> -  table_list.db= MYSQL_SCHEMA_NAME.str;
> -  table_list.db_length= MYSQL_SCHEMA_NAME.length;
> -
> -  if (!(table= open_performance_schema_table(thd, & table_list,
> -                                             & open_tables_backup)))
> -    goto err;
> -
> -  need_close= TRUE;
> -
> -  if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
> -      table->file->ha_rnd_init(0))
> -    goto err;
> -
> -  need_rnd_end= TRUE;
> -
> -  /* Honor next number columns if present */
> -  table->next_number_field= table->found_next_number_field;
> -
> -  /*
> -    Get defaults for new record.
> -  */
> -  restore_record(table, s->default_values); 
> -
> -  /* check that all columns exist */
> -  if (table->s->fields < ET_OBH_FIELD_COUNT)
> -    goto err;
> -
> -  /*
> -    Fill in the data.
> -  */
> -  table->field[ET_OBH_FIELD_PROCESS_ID]->store(process_id, TRUE);
> -  table->field[ET_OBH_FIELD_PROCESS_ID]->set_notnull();
> -  table->field[ET_OBH_FIELD_BACKUP_STATE]->store(state, TRUE);
> -  table->field[ET_OBH_FIELD_BACKUP_STATE]->set_notnull();
> -  table->field[ET_OBH_FIELD_OPER]->store(operation, TRUE);
> -  table->field[ET_OBH_FIELD_OPER]->set_notnull();
> -  table->field[ET_OBH_FIELD_ERROR_NUM]->store(error_num, TRUE);
> -  table->field[ET_OBH_FIELD_ERROR_NUM]->set_notnull();
> -
> -  if (host)
> -  {
> -    if(table->field[ET_OBH_FIELD_HOST_OR_SERVER]->store(host, 
> -       strlen(host), system_charset_info))
> -      goto err;
> -    table->field[ET_OBH_FIELD_HOST_OR_SERVER]->set_notnull();
> -  }
> -
> -  if (user)
> -  {
> -    if (table->field[ET_OBH_FIELD_USERNAME]->store(user,
> -        strlen(user), system_charset_info))
> -      goto err;
> -    table->field[ET_OBH_FIELD_USERNAME]->set_notnull();
> -  }
> -
> -  if (user_comment)
> -  {
> -    if (table->field[ET_OBH_FIELD_COMMENT]->store(user_comment,
> -        strlen(user_comment), system_charset_info))
> -      goto err;
> -    table->field[ET_OBH_FIELD_COMMENT]->set_notnull();
> -  }
> -
> -  if (backup_file)
> -  {
> -    if (table->field[ET_OBH_FIELD_BACKUP_FILE]->store(backup_file, 
> -        strlen(backup_file), system_charset_info))
> -      goto err;
> -    table->field[ET_OBH_FIELD_BACKUP_FILE]->set_notnull();
> -  }
> -
> -  if (command)
> -  {
> -    if (table->field[ET_OBH_FIELD_COMMAND]->store(command,
> -        strlen(command), system_charset_info))
> -      goto err;
> -    table->field[ET_OBH_FIELD_COMMAND]->set_notnull();
> -  }
> -
> -  /* log table entries are not replicated */
> -  if (table->file->ha_write_row(table->record[0]))
> -    goto err;
> -
> -  /*
> -    Get last insert id for row.
> -  */
> -  *backup_id= table->file->insert_id_for_cur_row;
> -
> -  result= FALSE;
> -
> -err:
> -  if (result && !thd->killed)
> -    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
> -                        ER_BACKUP_LOG_WRITE_ERROR,
> -                        ER(ER_BACKUP_LOG_WRITE_ERROR),
> -                        "mysql.online_backup");
> -
> -  if (need_rnd_end)
> -  {
> -    table->file->ha_rnd_end();
> -    table->file->ha_release_auto_increment();
> -  }
> -  if (need_close)
> -    close_performance_schema_table(thd, & open_tables_backup);
> -
> -  thd->time_zone_used= save_time_zone_used;
> -  return result;
> -}
> -
> -/**
> -  Update a backup history log entry for the given backup_id to a table.
> -
> -  This method updates a row in the backup history log using one
> -  of four data types as determined by the field (see fld).
> -
> -  @param[IN]   thd          The current thread
> -  @param[IN]   backup_id    The row id for the backup history to be updated
> -  @param[IN]   fld          The enum for the field to be updated 
> -  @param[IN]   val_long     The value for long fields
> -  @param[IN]   val_time     The value for time fields
> -  @param[IN]   val_str      The value for char * fields
> -  @param[IN]   val_state    The value for state fields
> -
> -  @retval TRUE if error.
> -
> -  @todo Add internal error handler to handle errors that occur on
> -        open. See  thd->push_internal_handler(&error_handler).
> -*/
> -bool backup_history_log_update(THD *thd, 
> -                               ulonglong backup_id,
> -                               enum_backup_history_table_field fld,
> -                               ulonglong val_long,
> -                               time_t val_time,
> -                               const char *val_str,
> -                               int val_state)
> -{
> -  TABLE_LIST table_list;
> -  TABLE *table= NULL;
> -  bool result= TRUE;
> -  bool need_close= FALSE;
> -  Open_tables_state open_tables_backup;
> -  bool save_time_zone_used;
> -  int ret= 0;
> -
> -  save_time_zone_used= thd->time_zone_used;
> -
> -  bzero(& table_list, sizeof(TABLE_LIST));
> -  table_list.alias= table_list.table_name= BACKUP_HISTORY_LOG_NAME.str;
> -  table_list.table_name_length= BACKUP_HISTORY_LOG_NAME.length;
> -
> -  table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
> -
> -  table_list.db= MYSQL_SCHEMA_NAME.str;
> -  table_list.db_length= MYSQL_SCHEMA_NAME.length;
> -
> -  if (!(table= open_performance_schema_table(thd, & table_list,
> -                                             & open_tables_backup)))
> -    goto err;
> -
> -  if (find_backup_history_row(table, backup_id))
> -    goto err;
> -
> -  need_close= TRUE;
> -
> -  store_record(table, record[1]);
> -
> -  /*
> -    Fill in the data.
> -  */
> -  switch (fld) {
> -    case ET_OBH_FIELD_BINLOG_POS:
> -    case ET_OBH_FIELD_ERROR_NUM:
> -    case ET_OBH_FIELD_NUM_OBJ:
> -    case ET_OBH_FIELD_TOTAL_BYTES:
> -    {
> -      table->field[fld]->store(val_long, TRUE);
> -      table->field[fld]->set_notnull();
> -      break;
> -    }
> -    case ET_OBH_FIELD_BINLOG_FILE:
> -    {
> -      if (val_str)
> -      {
> -        if(table->field[fld]->store(val_str, strlen(val_str), 
> -                                    system_charset_info))
> -          goto err;
> -        table->field[fld]->set_notnull();
> -      }
> -      break;
> -    }    
> -    case ET_OBH_FIELD_ENGINES:
> -    {
> -      String str;    // engines string
> -      str.length(0);
> -      table->field[fld]->val_str(&str);
> -      if (str.length() > 0)
> -        str.append(", ");
> -      str.append(val_str);
> -      if (str.length() > 0)
> -      {
> -        if(table->field[fld]->store(str.c_ptr(), 
> -           str.length(), system_charset_info))
> -          goto err;
> -        table->field[fld]->set_notnull();
> -      }
> -      break;
> -    }    
> -    case ET_OBH_FIELD_START_TIME:
> -    case ET_OBH_FIELD_STOP_TIME:
> -    case ET_OBH_FIELD_VP:
> -    {
> -      if (val_time)
> -      {
> -        MYSQL_TIME time;
> -        my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)val_time);
> -
> -        table->field[fld]->set_notnull();
> -        table->field[fld]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
> -      }
> -      break;
> -    }
> -    case ET_OBH_FIELD_BACKUP_STATE:
> -    {
> -      table->field[fld]->store(val_state, TRUE);
> -      table->field[fld]->set_notnull();
> -      break;
> -    }
> -    default:
> -      goto err;
> -  }
> -
> -  /*
> -    Update the row.
> -  */
> -  if ((ret= table->file->ha_update_row(table->record[1],
> table->record[0])))
> -    goto err;
> -
> -  result= FALSE;
> -
> -err:
> -  if (result && !thd->killed)
> -    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
> -                        ER_BACKUP_LOG_WRITE_ERROR,
> -                        ER(ER_BACKUP_LOG_WRITE_ERROR),
> -                        "mysql.online_backup");
> -
> -  if (need_close)
> -    close_performance_schema_table(thd, & open_tables_backup);
> -
> -  thd->time_zone_used= save_time_zone_used;
> -  return result;
> -}
> -
> -/**
> -  Write the backup log entry for the backup progress log to a table.
> -
> -  This method creates a new row in the backup progress log with the
> -  information provided.
> -
> -  @param[IN]   thd         The current thread
> -  @param[OUT]  backup_id   The id of the backup/restore operation for
> -                           the progress information
> -  @param[IN]   object      The name of the object processed
> -  @param[IN]   start       Start datetime
> -  @param[IN]   stop        Stop datetime
> -  @param[IN]   size        Size value
> -  @param[IN]   progress    Progress (percent)
> -  @param[IN]   error_num   Error number (should be 0 if success)
> -  @param[IN]   notes       Misc data from engine
> -
> -  @retval TRUE if error.
> -
> -  @todo Add internal error handler to handle errors that occur on
> -        open. See  thd->push_internal_handler(&error_handler).
> -*/
> -bool backup_progress_log_write(THD *thd,
> -                               ulonglong backup_id,
> -                               const char *object,
> -                               time_t start,
> -                               time_t stop,
> -                               longlong size,
> -                               longlong progress,
> -                               int error_num,
> -                               const char *notes)
> -{
> -  TABLE_LIST table_list;
> -  TABLE *table;
> -  bool result= TRUE;
> -  bool need_close= FALSE;
> -  bool need_rnd_end= FALSE;
> -  Open_tables_state open_tables_backup;
> -  bool save_time_zone_used;
> -
> -  save_time_zone_used= thd->time_zone_used;
> -
> -  bzero(& table_list, sizeof(TABLE_LIST));
> -  table_list.alias= table_list.table_name= BACKUP_PROGRESS_LOG_NAME.str;
> -  table_list.table_name_length= BACKUP_PROGRESS_LOG_NAME.length;
> -
> -  table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
> -
> -  table_list.db= MYSQL_SCHEMA_NAME.str;
> -  table_list.db_length= MYSQL_SCHEMA_NAME.length;
> -
> -  if (!(table= open_performance_schema_table(thd, & table_list,
> -                                             & open_tables_backup)))
> -    goto err;
> -
> -  need_close= TRUE;
> -
> -  if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
> -      table->file->ha_rnd_init(0))
> -    goto err;
> -
> -  need_rnd_end= TRUE;
> -
> -  /* Honor next number columns if present */
> -  table->next_number_field= table->found_next_number_field;
> -
> -  /*
> -    Get defaults for new record.
> -  */
> -  restore_record(table, s->default_values); 
> -
> -  /* check that all columns exist */
> -  if (table->s->fields < ET_OBP_FIELD_PROG_COUNT)
> -    goto err;
> -
> -  /*
> -    Fill in the data.
> -  */
> -  table->field[ET_OBP_FIELD_BACKUP_ID_FK]->store(backup_id, TRUE);
> -  table->field[ET_OBP_FIELD_BACKUP_ID_FK]->set_notnull();
> -
> -  if (object)
> -  {
> -    if (table->field[ET_OBP_FIELD_PROG_OBJECT]->store(object,
> -        strlen(object), system_charset_info))
> -      goto err;
> -    table->field[ET_OBP_FIELD_PROG_OBJECT]->set_notnull();
> -  }
> -
> -  if (notes)
> -  {
> -    if (table->field[ET_OBP_FIELD_PROG_NOTES]->store(notes,
> -        strlen(notes), system_charset_info))
> -      goto err;
> -    table->field[ET_OBP_FIELD_PROG_NOTES]->set_notnull();
> -  }
> -
> -  if (start)
> -  {
> -    MYSQL_TIME time;
> -    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)start);
> -
> -    table->field[ET_OBP_FIELD_PROG_START_TIME]->set_notnull();
> -    table->field[ET_OBP_FIELD_PROG_START_TIME]->store_time(&time,
> MYSQL_TIMESTAMP_DATETIME);
> -  }
> -
> -  if (stop)
> -  {
> -    MYSQL_TIME time;
> -    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)stop);
> -
> -    table->field[ET_OBP_FIELD_PROG_STOP_TIME]->set_notnull();
> -    table->field[ET_OBP_FIELD_PROG_STOP_TIME]->store_time(&time,
> MYSQL_TIMESTAMP_DATETIME);
> -  }
> -
> -  table->field[ET_OBP_FIELD_PROG_SIZE]->store(size, TRUE);
> -  table->field[ET_OBP_FIELD_PROG_SIZE]->set_notnull();
> -  table->field[ET_OBP_FIELD_PROGRESS]->store(progress, TRUE);
> -  table->field[ET_OBP_FIELD_PROGRESS]->set_notnull();
> -  table->field[ET_OBP_FIELD_PROG_ERROR_NUM]->store(error_num, TRUE);
> -  table->field[ET_OBP_FIELD_PROG_ERROR_NUM]->set_notnull();
> -
> -  /* log table entries are not replicated */
> -  if (table->file->ha_write_row(table->record[0]))
> -    goto err;
> -
> -  result= FALSE;
> -
> -err:
> -  if (result && !thd->killed)
> -    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
> -                        ER_BACKUP_LOG_WRITE_ERROR,
> -                        ER(ER_BACKUP_LOG_WRITE_ERROR),
> -                        "mysql.online_backup_progress");
> -
> -  if (need_rnd_end)
> -  {
> -    table->file->ha_rnd_end();
> -    table->file->ha_release_auto_increment();
> -  }
> -  if (need_close)
> -    close_performance_schema_table(thd, & open_tables_backup);
> -
> -  thd->time_zone_used= save_time_zone_used;
> -  return result;
> -}
> -
> -/**
> -   Find the row in the table that matches the backup_id.
> -
> -   This method locates the row in the online backup table that matches the
> -   backup_id passed.
> -
> -   @param TABLE      table      The open table.
> -   @param ulonglong  backup_id  The id of the row to locate.
> -
> -   @retval 0  success
> -   @retval 1  failed to find row
> -  */
> -bool find_backup_history_row(TABLE *table, ulonglong backup_id)
> -{
> -  uchar key[MAX_KEY_LENGTH]; // key buffer for search
> -  /*
> -    Create key to find row. We have to use field->store() to be able to
> -    handle different field types (method is overloaded).
> -  */
> -  table->field[ET_OBH_FIELD_BACKUP_ID]->store(backup_id, TRUE);
> -
> -  key_copy(key, table->record[0], table->key_info,
> table->key_info->key_length);
> -
> -  if (table->file->index_read_idx_map(table->record[0], 0, key,
> HA_WHOLE_KEY,
> -                                      HA_READ_KEY_EXACT))
> -    return true;
> -
> -  return false;
> -}
> -
> -/**
> -   report_ob_init()
> -
> -   This method inserts a new row in the online_backup table populating it
> -   with the initial values passed. It returns the backup_id of the new row.
> -
> -   @param THD                thd          The current thread class.
> -   @param int                process_id   The process id of the operation 
> -   @param enum_backup_state  state        The current state of the operation
> -   @param enum_backup_op     operation    The current operation 
> -                                          (backup or restore)
> -   @param int                error_num    The error number
> -   @param char *             user_comment The user's comment specified in the
> -                                          command (not implemented yet)
> -   @param char *             backup_file  The name of the target file
> -   @param char *             command      The actual command entered
> -
> -   @retval long backup_id  The autoincrement value for the new row.
> -  */
> -ulonglong report_ob_init(THD *thd, 
> -                         int process_id,
> -                         enum_backup_state state,
> -                         enum_backup_operation operation,
> -                         int error_num,
> -                         const char *user_comment,
> -                         const char *backup_file,
> -                         const char *command)
> -{ 
> -  ulonglong backup_id= 0;
> -  int ret= 0;                                  // return value
> -  DBUG_ENTER("report_ob_init()");
> -
> -  ret= backup_history_log_write(thd, &backup_id, process_id, state, operation,
> -                                error_num, user_comment, backup_file, command);
> -  /*
> -    Record progress update.
> -  */
> -  String str;
> -  get_state_string(state, &str);
> -  report_ob_progress(thd, backup_id, "backup kernel", 0, 
> -                     0, 0, 0, 0, str.c_ptr());
> -  DBUG_RETURN(backup_id);
> -}
> -
> -/**
> -   Update the binlog information for the row that matches the backup_id.
> -
> -   This method locates the row in the online backup table that matches the
> -   backup_id passed and updates the binlog values.
> -
> -   @param THD                  thd          The current thread class.
> -   @param ulonglong            backup_id    The id of the row to locate.
> -   @param int                  backup_pos   The id of the row to locate.
> -   @param char *               binlog_file  The filename of the binlog.
> -
> -   @retval 0  success
> -   @retval 1  failed to find row
> -  */
> -int report_ob_binlog_info(THD *thd,
> -                          ulonglong backup_id,
> -                          int binlog_pos,
> -                          const char *binlog_file)
> -{
> -  int ret= 0;                           // return value
> -  DBUG_ENTER("report_ob_binlog_info()");
> -
> -  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_BINLOG_POS, 
> -                                 binlog_pos, 0, 0, 0);
> -  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_BINLOG_FILE, 
> -                                 0, 0, binlog_file, 0);
> -  DBUG_RETURN(ret);
> -}
> -
> -/**
> -   Update the error number for the row that matches the backup_id.
> -
> -   This method locates the row in the online backup table that matches the
> -   backup_id passed and updates the error number value.
> -
> -   @param THD        thd        The current thread class.
> -   @param ulonglong  backup_id  The id of the row to locate.
> -   @param int        error_num  New error number.
> -
> -   @retval 0  success
> -   @retval 1  failed to find row
> -  */
> -int report_ob_error(THD *thd,
> -                    ulonglong backup_id,
> -                    int error_num)
> -{
> -  int ret= 0;  // return value
> -  DBUG_ENTER("report_ob_error()");
> -
> -  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_ERROR_NUM, 
> -                                 error_num, 0, 0, 0);
> -
> -  DBUG_RETURN(ret);
> -}
> -
> -/**
> -   Update the number of objects for the row that matches the backup_id.
> -
> -   This method locates the row in the online backup table that matches the
> -   backup_id passed and updates the number of objects value.
> -
> -   @param THD        thd         The current thread class.
> -   @param ulonglong  backup_id    The id of the row to locate.
> -   @param int        num_objects  New error number.
> -
> -   @retval 0  success
> -   @retval 1  failed to find row
> -  */
> -int report_ob_num_objects(THD *thd,
> -                          ulonglong backup_id,
> -                          int num_objects)
> -{
> -  int ret= 0;  // return value
> -  DBUG_ENTER("report_ob_num_objects()");
> -
> -  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_NUM_OBJ, 
> -                                 num_objects, 0, 0, 0);
> -
> -  DBUG_RETURN(ret);
> -}
> -
> -/**
> -   Update the size for the row that matches the backup_id.
> -
> -   This method locates the row in the online backup table that matches the
> -   backup_id passed and updates the size value.
> -
> -   @param THD        thd        The current thread class.
> -   @param ulonglong  backup_id  The id of the row to locate.
> -   @param int        size       New size value.
> -
> -   @retval 0  success
> -   @retval 1  failed to find row
> -  */
> -int report_ob_size(THD *thd,
> -                   ulonglong backup_id,
> -                   longlong size)
> -{
> -  int ret= 0;  // return value
> -  DBUG_ENTER("report_ob_size()");
> -
> -  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_TOTAL_BYTES, 
> -                                 size, 0, 0, 0);
> -
> -  DBUG_RETURN(ret);
> -}
> -
> -/**
> -   Update the start/stop time for the row that matches the backup_id.
> -
> -   This method locates the row in the online backup table that matches the
> -   backup_id passed and updates the start/stop values.
> -
> -   @param THD        thd        The current thread class.
> -   @param ulonglong  backup_id  The id of the row to locate.
> -   @param my_time_t  start      Start datetime.
> -   @param my_time_t  stop       Stop datetime.
> -
> -   @retval 0  success
> -   @retval 1  failed to find row
> -  */
> -int report_ob_time(THD *thd,
> -                   ulonglong backup_id,
> -                   time_t start,
> -                   time_t stop)
> -{
> -  int ret= 0;  // return value
> -  DBUG_ENTER("report_ob_time()");
> -
> -  if (start)
> -    ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_START_TIME, 
> -                                   0, start, 0, 0);
> -
> -  if (stop)
> -    ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_STOP_TIME, 
> -                                   0, stop, 0, 0);
> -
> -  DBUG_RETURN(ret);
> -}
> -
> -/**
> -   Update the validity point time for the row that matches the backup_id.
> -
> -   This method updates the validity point time for the backup operation
> -   identified by backup_id.
> -
> -   @param THD        thd        The current thread class.
> -   @param ulonglong  backup_id  The id of the row to locate.
> -   @param my_time_t  vp_time    Validity point datetime.
> -
> -   @retval 0  success
> -   @retval 1  failed to find row
> -  */
> -int report_ob_vp_time(THD *thd,
> -                      ulonglong backup_id,
> -                      time_t vp_time)
> -{
> -  int ret= 0;  // return value
> -  DBUG_ENTER("report_ob_vp_time()");
> -
> -  if (vp_time)
> -    ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_VP, 
> -                                   0, vp_time, 0, 0);
> -
> -  DBUG_RETURN(ret);
> -}
> -
> -/**
> -   Update the engines string for the row that matches the backup_id.
> -
> -   This method updates the engines information for the backup operation
> -   identified by backup_id. This method appends to the those listed in the
> -   table for the backup_id.
> -
> -   @param THD        thd          The current thread class.
> -   @param ulonglong  backup_id    The id of the row to locate.
> -   @param char *     egnine_name  The name of the engine to add.
> -
> -   @retval 0  success
> -   @retval 1  failed to find row
> -  */
> -int report_ob_engines(THD *thd,
> -                      ulonglong backup_id,
> -                      const char *engine_name)
> -{
> -  int ret= 0;  // return value
> -  DBUG_ENTER("report_ob_engines()");
> -
> -  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_ENGINES, 
> -                                 0, 0, engine_name, 0);
> -
> -  DBUG_RETURN(ret);
> -}
> -
> -/**
> -   Update the state for the row that matches the backup_id.
> -
> -   This method locates the row in the online backup table that matches the
> -   backup_id passed and updates the state value.
> -
> -   @param THD                thd        The current thread class.
> -   @param ulonglong          backup_id  The id of the row to locate.
> -   @param enum_backup_state  state      New state value.
> -
> -   @retval 0  success
> -   @retval 1  failed to find row
> -  */
> -int report_ob_state(THD *thd, 
> -                    ulonglong backup_id,
> -                    enum_backup_state state)
> -{
> -  int ret= 0;  // return value
> -  String str;
> -  DBUG_ENTER("report_ob_state()");
> -
> -  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_BACKUP_STATE, 
> -                                 0, 0, 0, state);
> -  /*
> -    Record progress update.
> -  */
> -  get_state_string(state, &str);
> -  report_ob_progress(thd, backup_id, "backup kernel", 0, 
> -                     0, 0, 0, 0, str.c_ptr());
> -
> -  DBUG_RETURN(ret);
> -}
> -
> -/**
> -   Creates a new progress row for the row that matches the backup_id.
> -
> -   This method inserts a new row in the online backup progress table using
> -   the values passed. This method is used to insert progress information during
> -   the backup operation.
> -
> -   @param THD        thd        The current thread class.
> -   @param ulonglong  backup_id  The id of the master table row.
> -   @param char *     object     The name of the object processed.
> -   @param my_time_t  start      Start datetime.
> -   @param my_time_t  stop       Stop datetime.
> -   @param longlong   size       Size value.
> -   @param longlong   progress   Progress (percent).
> -   @param int        error_num  Error number (should be 0 is success).
> -   @param char *     notes      Misc data from engine
> -
> -   @retval 0  success
> -   @retval 1  failed to find row
> -  */
> -inline int report_ob_progress(THD *thd,
> -                       ulonglong backup_id,
> -                       const char *object,
> -                       time_t start,
> -                       time_t stop,
> -                       longlong size,
> -                       longlong progress,
> -                       int error_num,
> -                       const char *notes)
> -{
> -  int ret= 0;                           // return value
> -  DBUG_ENTER("report_ob_progress()");
> -
> -  ret= backup_progress_log_write(thd, backup_id, object, start, stop, 
> -                                 size, progress, error_num, notes);
> -
> -  DBUG_RETURN(ret);
> -}
> -
> -
> -
>


> === removed file 'sql/backup/backup_progress.h'
> --- a/sql/backup/backup_progress.h	2008-03-21 09:05:40 +0000
> +++ b/sql/backup/backup_progress.h	1970-01-01 00:00:00 +0000
> @@ -1,243 +0,0 @@
> -#ifndef _BACKUP_PROGRESS_H
> -#define _BACKUP_PROGRESS_H
> -
> -/* Copyright (C) 2004-2007 MySQL AB
> -
> -   This program is free software; you can redistribute it and/or modify
> -   it under the terms of the GNU General Public License as published by
> -   the Free Software Foundation; version 2 of the License.
> -
> -   This program is distributed in the hope that it will be useful,
> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> -   GNU General Public License for more details.
> -
> -   You should have received a copy of the GNU General Public License
> -   along with this program; if not, write to the Free Software
> -   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
> -
> -/**
> -   @file backup_progress.h
> -
> -   Data Dictionary related operations of Online Backup.
> -*/
> -
> -/**
> -   List of fields for online backup table.
> -  */
> -enum enum_backup_history_table_field
> -{
> -  ET_OBH_FIELD_BACKUP_ID = 0, /* start from 0 to correspond with field array */
> -  ET_OBH_FIELD_PROCESS_ID,
> -  ET_OBH_FIELD_BINLOG_POS,
> -  ET_OBH_FIELD_BINLOG_FILE,
> -  ET_OBH_FIELD_BACKUP_STATE,
> -  ET_OBH_FIELD_OPER,
> -  ET_OBH_FIELD_ERROR_NUM,
> -  ET_OBH_FIELD_NUM_OBJ,
> -  ET_OBH_FIELD_TOTAL_BYTES,
> -  ET_OBH_FIELD_VP,
> -  ET_OBH_FIELD_START_TIME,
> -  ET_OBH_FIELD_STOP_TIME,
> -  ET_OBH_FIELD_HOST_OR_SERVER,
> -  ET_OBH_FIELD_USERNAME,
> -  ET_OBH_FIELD_BACKUP_FILE,
> -  ET_OBH_FIELD_COMMENT,
> -  ET_OBH_FIELD_COMMAND,
> -  ET_OBH_FIELD_ENGINES,
> -  ET_OBH_FIELD_COUNT /* a cool trick to count the number of fields :) */
> -};
> -
> -/**
> -   List of fields for online backup progress table.
> -  */
> -enum enum_backup_progress_table_field
> -{
> -  ET_OBP_FIELD_BACKUP_ID_FK = 0, /* start from 0 to correspond with field array */
> -  ET_OBP_FIELD_PROG_OBJECT,
> -  ET_OBP_FIELD_PROG_START_TIME,
> -  ET_OBP_FIELD_PROG_STOP_TIME,
> -  ET_OBP_FIELD_PROG_SIZE,
> -  ET_OBP_FIELD_PROGRESS,
> -  ET_OBP_FIELD_PROG_ERROR_NUM,
> -  ET_OBP_FIELD_PROG_NOTES,
> -  ET_OBP_FIELD_PROG_COUNT /* a cool trick to count the number of fields :) */
> -};
> -
> -/**
> -   List of states for online backup table.
> -  */
> -enum enum_backup_state
> -{
> -  BUP_UNKNOWN = 0,
> -  BUP_COMPLETE,
> -  BUP_STARTING,
> -  BUP_VALIDITY_POINT,
> -  BUP_RUNNING,
> -  BUP_ERRORS,
> -  BUP_CANCEL
> -};
> -
> -/**
> -   List of operations for online backup table.
> -  */
> -enum enum_backup_operation
> -{
> -  OP_BACKUP = 1,
> -  OP_RESTORE,
> -  OP_SHOW,
> -  OP_OTHER
> -};
> -
> -/*
> -  This method attempts to open the online backup progress tables. It returns
> -  an error if either table is not present or cannot be opened.
> -*/
> -my_bool check_ob_progress_tables(THD *thd);
> -
> -
> -/*
> -  This method creates a new row in the backup history log with the
> -  information provided.
> -*/
> -bool backup_history_log_write(THD *thd, 
> -                              ulonglong *backup_id,
> -                              int process_id,
> -                              enum_backup_state state,
> -                              enum_backup_operation operation,
> -                              int error_num,
> -                              const char *user_comment,
> -                              const char *backup_file,
> -                              const char *command);
> -
> -/*
> -   This method locates the row in the online backup table that matches the
> -   backup_id passed.
> -*/
> -bool find_backup_history_row(TABLE *table, ulonglong backup_id);
> -
> -/*
> -  This method updates a row in the backup history log using one
> -  of four data types as determined by the field (see fld).
> -*/
> -bool backup_history_log_update(THD *thd, 
> -                               ulonglong backup_id,
> -                               enum_backup_history_table_field fld,
> -                               ulonglong val_long,
> -                               time_t val_time,
> -                               const char *val_str,
> -                               int val_state);
> -
> -/*
> -  This method creates a new row in the backup progress log with the
> -  information provided.
> -*/
> -bool backup_progress_log_write(THD *thd,
> -                               ulonglong backup_id,
> -                               const char *object,
> -                               time_t start,
> -                               time_t stop,
> -                               longlong size,
> -                               longlong progress,
> -                               int error_num,
> -                               const char *notes);
> -
> -/*
> -  This method inserts a new row in the online_backup table populating it with
> -  the initial values passed. It returns the backup_id of the new row.
> -*/
> -ulonglong report_ob_init(THD *thd,
> -                         int process_id,
> -                         enum_backup_state state,
> -                         enum_backup_operation operation,
> -                         int error_num,
> -                         const char *user_comment,
> -                         const char *backup_file,
> -                         const char *command);
> -
> -/*
> -  This method updates the binary log information for the backup operation
> -  identified by backup_id.
> -*/
> -int report_ob_binlog_info(THD *thd,
> -                          ulonglong backup_id,
> -                          int binlog_pos,
> -                          const char *binlog_file);
> -
> -/*
> -  This method updates the error number for the backup operation identified by
> -  backup_id.
> -*/
> -int report_ob_error(THD *thd,
> -                    ulonglong backup_id,
> -                    int error_num);
> -
> -/*
> -  This method updates the state for the backup operation identified by
> -  backup_id.
> -*/
> -int report_ob_state(THD *thd,
> -                    ulonglong backup_id,
> -                    enum_backup_state state);
> -
> -/*
> -  This method updates the number of objects for the backup operation identified by
> -  backup_id.
> -*/
> -int report_ob_num_objects(THD *thd,
> -                          ulonglong backup_id,
> -                          int num_objects);
> -
> -/*
> -  This method updates the size for the backup operation identified by
> -  backup_id.
> -*/
> -int report_ob_size(THD *thd,
> -                   ulonglong backup_id,
> -                   longlong size);
> -
> -/*
> -  This method updates the start/stop time for the backup operation identified by
> -  backup_id.
> -
> -  Note: This method ignores values for start or stop that are NULL (only saves 
> -  values provided so that it can be called once for start and once again later 
> -  for stop).
> -*/
> -int report_ob_time(THD *thd,
> -                   ulonglong backup_id,
> -                   time_t start,
> -                   time_t stop);
> -
> -/*
> -  This method updates the validity point time for the backup operation
> -  identified by backup_id.
> -*/
> -int report_ob_vp_time(THD *thd,
> -                      ulonglong backup_id,
> -                      time_t vp_time);
> -
> -/*
> -  This method updates the engines information for the backup operation
> -  identified by backup_id. This method appends to the those listed in the
> -  table for the backup_id.
> -*/
> -int report_ob_engines(THD *thd,
> -                      ulonglong backup_id,
> -                      const char *engine_name);
> -
> -/*
> -  This method inserts a new row in the progress table.
> -*/
> -int report_ob_progress(THD *thd,
> -                       ulonglong backup_id,
> -                       const char *object,
> -                       time_t start,
> -                       time_t stop,
> -                       longlong size,
> -                       longlong progress,
> -                       int error_num,
> -                       const char *notes);
> -
> -#endif
> -
> 


> === modified file 'sql/backup/data_backup.cc'
> --- a/sql/backup/data_backup.cc	2008-06-05 12:26:31 +0000
> +++ b/sql/backup/data_backup.cc	2008-06-25 21:29:44 +0000
> @@ -10,7 +10,7 @@
>    @todo Implement better scheduling strategy in Scheduler::step
>    @todo Add error reporting in the scheduler and elsewhere
>    @todo If an error from driver is ignored (and operation retried) leave trace
> -        of the error in the log.
> +        of the error in the log.`
>   */
>  
>  #include "../mysql_priv.h"
> @@ -18,7 +18,6 @@
>  #include "backup_kernel.h"
>  #include "backup_engine.h"
>  #include "stream.h"
> -#include "backup_progress.h"
>  #include "debug.h"
>  #include "be_default.h"  // needed for table locking code
>  
> 

> === modified file 'sql/backup/kernel.cc'
> --- a/sql/backup/kernel.cc	2008-05-21 10:45:55 +0000
> +++ b/sql/backup/kernel.cc	2008-06-25 21:29:44 +0000
> @@ -75,7 +75,6 @@
>  #include "be_snapshot.h"
>  #include "be_nodata.h"
>  #include "ddl_blocker.h"
> -#include "backup_progress.h"
>  
>  
>  /** 
> @@ -87,6 +86,7 @@
>  int backup_init()
>  {
>    pthread_mutex_init(&Backup_restore_ctx::run_lock, MY_MUTEX_INIT_FAST);
> +  pthread_mutex_init(&backup::LOCK_backupid, MY_MUTEX_INIT_FAST);
>    return 0;
>  }
>  
> @@ -99,6 +99,7 @@ int backup_init()
>  void backup_shutdown()
>  {
>    pthread_mutex_destroy(&Backup_restore_ctx::run_lock);
> +  pthread_mutex_destroy(&backup::LOCK_backupid);
>  }
>  
>  /*
> @@ -123,6 +124,8 @@ int
>  execute_backup_command(THD *thd, LEX *lex)
>  {
>    int res= 0;
> +  LEX_STRING path;
> +  int path_len= 0;
>    
>    DBUG_ENTER("execute_backup_command");
>    DBUG_ASSERT(thd && lex);
> @@ -136,13 +139,31 @@ execute_backup_command(THD *thd, LEX *le
>    if (!context.is_valid())
>      DBUG_RETURN(send_error(context, ER_BACKUP_CONTEXT_CREATE));
>  
> +  /*
> +    Prepare the path using the backupdir iff no path included
> +  */
> +  if (!has_path(lex->backup_dir.str))
> +  {
> +    path.length= sys_var_backupdir.value_length + lex->backup_dir.length + 1;
> +    path.str= (char *)my_malloc(path.length + 1, MYF(0));
> +    strcpy(path.str, fn_format(path.str, lex->backup_dir.str, 
> +                               sys_var_backupdir.value, "",
> +                               MY_UNPACK_FILENAME));
> +  }
> +  else
> +  {
> +    path.length= lex->backup_dir.length + 1;
> +    path.str= (char *)my_malloc(path.length + 1, MYF(0));
> +    strcpy(path.str, lex->backup_dir.str);
> +  }
> +

This is breaking separation between backup kernel and the resto of the server. 
Here backup kernel directly access server variables. Instead, the SI API should 
be extended.

Actually I think that the backup kernel should export an API for setting the 
backupdir option. When server sees this option, it will call a function like 
set_backup_dir(), defined by the backup kernel. That function would process the 
option and setup backup kernel to use the indicated directory as default.

>    switch (lex->sql_command) {
>  
>    case SQLCOM_BACKUP:
>    {
>      // prepare for backup operation
>      
> -    Backup_info *info= context.prepare_for_backup(lex->backup_dir,
> thd->query);
> +    Backup_info *info= context.prepare_for_backup(path, thd->query);
>                                                                // reports errors
>  
>      if (!info || !info->is_valid())
> @@ -187,7 +208,7 @@ execute_backup_command(THD *thd, LEX *le
>  
>    case SQLCOM_RESTORE:
>    {
> -    Restore_info *info= context.prepare_for_restore(lex->backup_dir,
> thd->query);
> +    Restore_info *info= context.prepare_for_restore(path, thd->query);
>      
>      if (!info || !info->is_valid())
>        DBUG_RETURN(send_error(context, ER_BACKUP_RESTORE_PREPARE));
> @@ -211,6 +232,7 @@ execute_backup_command(THD *thd, LEX *le
>  
>    } // switch(lex->sql_command)
>  
> +  my_free(path.str, MYF(0));  // free memory for path
>    if (context.close())
>      DBUG_RETURN(send_error(context, ER_BACKUP_CONTEXT_REMOVE));
>  
> @@ -335,14 +357,14 @@ Backup_restore_ctx::Backup_restore_ctx(T
>    /*
>      Check for progress tables.
>    */
> -  if (check_ob_progress_tables(thd))
> +  if (backup::check_backup_logs(thd))
>      m_error= ER_BACKUP_PROGRESS_TABLES;
>  }
>  
>  Backup_restore_ctx::~Backup_restore_ctx()
>  {
>    close();
> -  
> +
>    delete m_catalog;  
>    delete m_stream;
>  }
> @@ -398,7 +420,12 @@ int Backup_restore_ctx::prepare(LEX_STRI
>  
>    // check if location is valid (we assume it is a file path)
>  
> -  bool bad_filename= (location.length == 0);
> +  /*
> +    For this error to work correctly, we need to check original
> +    file specified by the user rather than the path formed
> +    using the backupdir.
> +  */
> +  bool bad_filename= (m_thd->lex->backup_dir.length == 0);
>    
>    /*
>      On some systems certain file names are invalid. We use 
> @@ -406,13 +433,13 @@ int Backup_restore_ctx::prepare(LEX_STRI
>     */ 
>  #if defined(__WIN__) || defined(__EMX__)  
>  
> -  bad_filename = bad_filename || check_if_legal_filename(location.str);
> -  
> +  bad_filename = bad_filename ||
> check_if_legal_filename(m_thd->lex->backup_dir.str);
> +
>  #endif
>  
>    if (bad_filename)
>    {
> -    fatal_error(ER_BAD_PATH, location.str);
> +    fatal_error(ER_BAD_PATH, m_thd->lex->backup_dir.str);
>      return m_error;
>    }
>  
> @@ -498,7 +525,12 @@ Backup_restore_ctx::prepare_for_backup(L
>    
>    if (!s->open())
>    {
> -    fatal_error(ER_BACKUP_WRITE_LOC, path.ptr());
> +    /*
> +      For this error, use the actual value returned instead of the
> +      path complimented with backupdir.
> +    */
> +    THD *thd= ::current_thd;
> +    fatal_error(ER_BACKUP_WRITE_LOC, thd->lex->backup_dir.str);
>      return NULL;
>    }
>  
> @@ -576,7 +608,12 @@ Backup_restore_ctx::prepare_for_restore(
>    
>    if (!s->open())
>    {
> -    fatal_error(ER_BACKUP_READ_LOC, path.ptr());
> +    /*
> +      For this error, use the actual value returned instead of the
> +      path complimented with backupdir.
> +    */
> +    THD *thd= ::current_thd;
> +    fatal_error(ER_BACKUP_READ_LOC, thd->lex->backup_dir.str);
>      return NULL;
>    }
>  
> @@ -1043,7 +1080,7 @@ int bcat_reset(st_bstream_image_header *
>      }
>  
>      info->m_snap[n]->m_num= n + 1;
> -    info->m_ctx.report_driver(info->m_snap[n]->name());
> +    info->m_ctx.report_engine(info->m_snap[n]->name());
>    }
>  
>    return BSTREAM_OK;
> 

> === modified file 'sql/backup/logger.cc'
> --- a/sql/backup/logger.cc	2008-03-21 09:57:45 +0000
> +++ b/sql/backup/logger.cc	2008-06-25 21:29:44 +0000
> @@ -1,7 +1,8 @@
>  #include "../mysql_priv.h"
>  
> -#include "logger.h"
>  #include "image_info.h"
> +#include <my_dir.h>
> +#include "logger.h"
>  
>  /** @file
>   
> @@ -10,6 +11,55 @@
>  
>  namespace backup {
>  
> +pthread_mutex_t LOCK_backupid; ///< mutex for backupid generation
> +
> +/**
> +  Check backup history logs.
> +  
> +  This method attempts to open the backup logs. It returns
> +  an error if either log is not present or cannot be opened.
> +
> +  @param[in] THD * The current thread.
> +
> +  @returns Information whether backup logs can be used.
> +
> +  @retval FALSE  success
> +  @retval TRUE  failed to open one of the logs
> +*/

This is not a good place for such a method. Checking if backup logs are ready 
should be the job of the server who provides backup logging service and knows 
the details of how it is implemented. E.g., only the server knows that log 
tables are stored in the mysql database and that they are called 
"backup_history" and "backup_progress". A client of the backup logging service 
should not need to know such details.

> +my_bool check_backup_logs(THD *thd)
> +{
> +  TABLE_LIST tables;
> +  my_bool ret= FALSE;
> +
> +  DBUG_ENTER("check_backup_logs");
> +
> +  /*
> +     ADD TO THIS AREA!!!
> +     CHECK TO SEE IF LOG TO TABLE OR LOG TO FILE! 
> +     ONLY DO CHECK IF WE ARE LOGGING TO TABLE!
> +  */
> +
> +  /* Check mysql.backup_history */
> +  tables.init_one_table("mysql", "backup_history", TL_READ);
> +  if (simple_open_n_lock_tables(thd, &tables))
> +  {
> +    ret= TRUE;
> +    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
> +    DBUG_RETURN(ret);
> +  }
> +  close_thread_tables(thd);
> +
> +  /* Check mysql.backup_progress */
> +  tables.init_one_table("mysql", "backup_progress", TL_READ);
> +  if (simple_open_n_lock_tables(thd, &tables))
> +  {
> +    ret= TRUE;
> +    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
> +    DBUG_RETURN(ret);
> +  }
> +  close_thread_tables(thd);
> +  DBUG_RETURN(ret);
> +}
>  
>  /**
>    Output message on a given level.
> @@ -55,7 +105,7 @@ int Logger::write_message(log_level::val
>       DBUG_PRINT("backup_log",("[ERROR] %s", out));
>       
>       if (m_state == READY || m_state == RUNNING)
> -       report_ob_error(m_thd, m_op_id, error_code);
> +       report_error_to_log(m_thd, error_code);

This is just m_op_hist->error_num= error_code - why having a helper method for that?

The error is not written to the progress log. Should be something like:

time_t ts = my_time(0);

backup_progress_log_write(m_thd, get_op_id(), 0, &ts, &ts, 0, 0, error_code, out);

I think that we should also log all warning and info messages.

>       
>       return 0;
>  
> @@ -115,7 +165,7 @@ void Logger::report_stats_pre(const Imag
>  {
>    DBUG_ASSERT(m_state == RUNNING);
>    
> -  report_ob_num_objects(m_thd, m_op_id, info.table_count());
> +  report_num_objects(m_thd, info.table_count());

This is just m_op_hist->num_objects= info.table_count() -- why a helper method 
for that?

>  }
>  
>  /**
> @@ -126,7 +176,195 @@ void Logger::report_stats_post(const Ima
>  {
>    DBUG_ASSERT(m_state == RUNNING);
>    
> -  report_ob_size(m_thd, m_op_id, info.data_size);
> +  report_size(m_thd, info.data_size);

This is just m_op_hist->data_size= info.data_size -- why a helper method for that?

> +  write_history(m_thd, m_op_hist);

This is just backup_history_log_write(m_thd, m_op_hist) -- why a helper method 
for that?

> +}
> +
> +/**
> +  Report name of a driver used in backup/restore operation.
> +
> +  This method updates the engines information in the history data. This method 
> +  appends to the those listed in the history data.
> +
> +  @param[IN] THD               thd          The current thread class.
> +  @param[IN] char *            driver_name  The name of the engine to add.
> +*/
> +void Logger::report_engine(const char *engine_name)

Why rename driver -> engine?

> +{
> +  String str;    // engines string
> +  DBUG_ASSERT(m_state == READY || m_state == RUNNING);
> +
> +  str.length(0);
> +  if (m_op_hist->engine_name &&
> +      (strlen(m_op_hist->engine_name) > 0) &&
> +      (strlen(engine_name) > 0))
> +    str.append(", ");
> +  if (strlen(engine_name) > 0)
> +    str.append(engine_name);
> +  if (str.length() > 0)
> +  {
> +    if (m_op_hist->engine_name)
> +      delete m_op_hist->engine_name;
> +    m_op_hist->engine_name = new char[str.length()+1];
> +    strcpy(m_op_hist->engine_name, str.ptr());
> +  }
> +}
> +
> +/**
> +  Creates a new progress row in the progress log.
> +
> +  This method inserts a new row in the backup progress log using the values 
> +  passed. This method is used to insert progress information during
> +  the backup operation.
> +
> +  @param[IN] THD               thd          The current thread class.
> +  @param[IN] st_backup_history m_op_hist Data for the row.
> +  @param[IN] char *            object       The name of the object processed.
> +  @param[IN] my_time_t         start        Start datetime.
> +  @param[IN] my_time_t         stop         Stop datetime.
> +  @param[IN] longlong          size         Size value.
> +  @param[IN] longlong          progress     Progress (percent).
> +  @param[IN] int               error_num    Error number (should be 0 is success).
> +  @param[IN] char *            notes        Misc data from engine
> +
> +  @retval 0  success
> +  @retval 1  failed to find row
> +*/

I don't think we need yet another wrapper around backup_progress_log_write(). 
There is nothing wrong in calling it directly when needed.

> +int Logger::write_progress(THD *thd,
> +                           st_backup_history *m_op_hist,
> +                           const char *object,
> +                           time_t start,
> +                           time_t stop,
> +                           longlong size,
> +                           longlong progress,
> +                           int error_num,
> +                           const char *notes)
> +{
> +  int ret= 0;                           // return value
> +  DBUG_ENTER("write_progress()");
> +
> +  ret= backup_progress_log_write(thd, m_op_hist->backup_id, object, start,
> +                                 stop, size, progress, error_num, notes);
> +  DBUG_RETURN(ret);
> +}
> +
> +/**
> +  Creates a new history row in the history log.
> +
> +  This method inserts a new row in the backup history log using the values 
> +  passed in the history data.
> +  
> +  @param[IN] THD               thd          The current thread class.
> +  @param[IN] st_backup_history m_op_hist Data for the row.
> +
> +  @retval 0  success
> +  @retval 1  failed to find row
> +*/

The same as above - you can use backup_history_log_write() directly.

> +int Logger::write_history(THD *thd, st_backup_history *m_op_hist)
> +{
> +  int ret= 0;                           // return value
> +  DBUG_ENTER("write_history()");
> +
> +  ret= backup_history_log_write(thd, m_op_hist);
> +  DBUG_RETURN(ret);
> +}
> +
> +/**
> +  Generate the next backup id.
> +  
> +  Since autoincrement columns are not permitted in CSV files, an alternative 
> +  mechanism has been developed to create monotonically increasing values. When 
> +  a server that does not have any logs written (no backup logs), the system 
> +  starts at backup_id = 0. This value is stored in a binary file in the data 
> +  directory named backup_settings.obx. Each time a new backup_id is needed, 
> +  this value is read, incremented, then the file rewritten. This ensures a 
> +  monotonically increasing backup_id. If the backup logs exist and the 
> +  backup_settings.obx file does not, the system uses the backup log file size 
> +  as the starting backup_id. 
> +
> +  @todo Do we need a mutex to protect this call internally?
> +*/


Generating new backup_id from backup logs requires knowledge of the 
implementation details of the backup logging service (e.g. the log file paths). 
Therefore it should be implemented as part of that service, not here.

Generating backup_id and storing it in a persistent storage are two different 
tasks which can and should be separated. Generating new backup_id should be 
implemented in the server as part of backup logging service. Storing the current 
backup_id (and perhaps some other backup state) should be implemented by backup 
kernel.

> +void Logger::get_next_backup_id()
> +{
> +  ulonglong id= 0;
> +  char buff[FN_REFLEN], *file_path;
> +  int error= 0;
> +  File file= 0;
> +
> +  /*
> +    This code attempts to generate a new backup_id. The process is:
> +    1) Attempt to read from backup settings file.
> +    2) If file exists, read value, increment, write new values.
> +    3) If file does not exist, create it and set the first backup_id
> +       equal to the filesize of the backup history log file.
> +
> +    Notes:
> +    m_next_id == 0 means we need to read the next id from the file (on startup).
> +    m_next_id > 0 means use this value
> +  */
> +  if (!m_next_id)
> +  {
> +    file_path= make_backup_log_name(buff, BACKUP_SETTINGS_NAME.str, ".obx");

Accessing the name of the settings file like this, creates implicit dependency 
between backup kernel and the rest of the server. That is, the kernel must be 
aware of the BACKUP_SETTINGS_NAME variable defined in the server and of the 
make_backup_log_name() function also defined there.

I think the dependency should go in the other direction. That is, the server, 
should somehow know that this is a backup option and then pass it to the backup 
module (if loaded) for processing. Backup module should define a method for 
processing its options in the API.

There may be other backup related options in the future. The server should not 
try to interpret them but rather pass them to the backup kernel which will know 
how to deal with them.

> +    MY_STAT state;  
> +  
> +    file= my_open(file_path, O_RDWR|O_BINARY|O_CREAT, MYF(MY_WME));
> +    if (!file)
> +      goto err_end; 
> +
> +    if (my_fstat(file, &state, MYF(0)))
> +      goto err;
> +    /*
> +      Check to see if the file size is 0. If it is, we need to pick a 
> +      new backup_id to start from. 
> +    */
> +    if (state.st_size == 0)
> +    {
> +      MY_STAT fstate;
> +      File hist_file= my_open(sys_var_backup_history_log_path.value,
> +        O_RDONLY|O_BINARY, MYF(MY_WME));

You use bcackup history log *file* to generate the new id. What if we don't log 
to files but only to tables? Can a reasonable id be generated also in that case?

> +      if (hist_file > 0)
> +      {
> +         my_fstat(hist_file, &fstate, MYF(0));
> +         my_close(hist_file, MYF(MY_WME));
> +        id= fstate.st_size + 1;
> +      }
> +      else
> +        id= 1;

Above code requires backup kernel to know internals of the backup logging 
service provided by the server. We need to know that there is a log file and we 
need to know a path to that file and so on. All these things are better to be 
hidden bahind backup logging API as implementation details. If we need to 
generate backup id by looking at the backup logs, this should be implemented in 
the server as part of backup logging services, not here.

> +    }
> +    // else .... we read the next value in the file!
> +    else
> +    {

The settings file should be versioned, so that we don't have problems when we 
extend it in the future.

> +      my_seek(file, 0, 0, MYF(MY_WME));
> +      size_t read_len= my_read(file, (uchar *)&id, sizeof(ulonglong), 
> +        MYF(MY_WME|MY_NABP));

This is not endianess agnostic. Beter to store it so that if someone copies 
settings file to another architecture (e.g., after upgrading hardware) the code 
will still work.

> +      id++;
> +    }
> +  }
> +  else  // increment the counter
> +    id= m_next_id + 1;
> +  
> +  /* 
> +    Write the new value to the file
> +  */
> +  if ((m_next_id != id) && id)
> +  {
> +    if (!file)
> +    {
> +      file_path= make_backup_log_name(buff, BACKUP_SETTINGS_NAME.str, ".obx");
> +      file= my_open(file_path, O_RDWR|O_BINARY|O_CREAT, MYF(MY_WME));
> +      if (!file)
> +        goto err_end; 
> +    }
> +    my_seek(file, 0, 0, MYF(MY_WME));
> +    my_write(file, (uchar *)&id, sizeof(ulonglong), MYF(MY_WME));
> +  }
> +err:
> +  if (file > 0)
> +    my_close(file,MYF(MY_WME));
> +  
> +err_end:		     
> +  m_next_id= id;
> +  printf("The next id is %lu.\n", id);

Use DBUG_PRINT() for such messages.

>  }
>  
>  } // backup namespace
> 

> === modified file 'sql/backup/logger.h'
> --- a/sql/backup/logger.h	2008-03-21 09:57:45 +0000
> +++ b/sql/backup/logger.h	2008-06-25 21:29:44 +0000
> @@ -4,7 +4,6 @@
>  #include <backup_stream.h>
>  #include <backup/error.h>
>  #include <backup/debug.h>
> -#include <backup/backup_progress.h>
>  
>  
>  namespace backup {
> @@ -19,6 +18,13 @@ struct log_level {
>  
>  };
>  
> +/*
> +  This method attempts to open the backup logs. It returns
> +  an error if either log is not present or cannot be opened.
> +*/
> +my_bool check_backup_logs(THD *thd);
> +
> +extern pthread_mutex_t LOCK_backupid; ///< mutex for backupid generation
>  
>  class Image_info;
>  
> @@ -46,7 +52,7 @@ class Logger
>  
>     Logger(THD*);
>     ~Logger();
> -   int init(enum_type, const LEX_STRING, const char*);
> +   int init(enum_type type, const LEX_STRING path, const char *query);
>  
>     int report_error(int error_code, ...);
>     int report_error(log_level::value level, int error_code, ...);
> @@ -58,10 +64,33 @@ class Logger
>     void report_state(enum_backup_state);
>     void report_vp_time(time_t);
>     void report_binlog_pos(const st_bstream_binlog_pos&);
> -   void report_driver(const char*);
> +   void report_engine(const char*);

Why this rename? I think the intention of this method is to report 
backup/restore drivers used in the operation.

>     void report_stats_pre(const Image_info&);
>     void report_stats_post(const Image_info&);
>     
> +   void report_error_to_log(THD *thd, int error_num);
> +   void report_num_objects(THD *thd, int num_objects);
> +   void report_size(THD *thd, longlong size);
> +
> +   /*
> +     This method inserts a new row in the history log.
> +   */
> +   int write_history(THD *thd,
> +                    st_backup_history *m_op_hist);
> +
> +   /*  
> +     This method inserts a new row in the progress log.
> +   */
> +	 int write_progress(THD *thd,
> +                      st_backup_history *m_op_hist,
> +                      const char *object,
> +                      time_t start,
> +                      time_t stop,
> +                      longlong size,
> +                      longlong progress,
> +                      int error_num,
> +                      const char *notes);
> +

We really don't need these helper methods. And definitely not in the public 
interface.

>     void save_errors();
>     void stop_save_errors();
>     void clear_saved_errors();
> @@ -73,28 +102,33 @@ class Logger
>    THD *m_thd;
>  
>    /**
> -    Id of the backup or restore operation.
> +    history of the backup or restore operation.
>      
>      This id is used in the backup progress and log tables to identify the
> -    operation. Value of @c m_op_id is meaningful only after a successful 
> +    operation. Value of @c m_op_hist is meaningful only after a successful 
>      call to @c init(), when @m_state != CREATED.
>     */ 

Please add a separate documentation for m_op_hist.

According to my understanding of m_op_hist, I'd document it as follows.

/**
   Stores information about backup or restore operation for reporting purposes.

   This structure is filled when various events are reported via Logger methods.
   When the operation is finished, its contents is written to the backup history
   log.
*/

>    ulonglong m_op_id;
> +  st_backup_history *m_op_hist;

There is no reason for allocating m_op_hist dynamically. Instead, it can be 
declared as

st_backup_history m_op_hist;

and then we don't have to worry about my_alloc/my_free. This member should be 
private - no need to export it in the interface.

Since backup_id is stored inside m_op_hist, the m_op_id can be turned into 
accessor method:

ulonglong get_op_id() const { return m_op_hist.backup_id; }

>  
>    int v_report_error(log_level::value, int, va_list);
>    int v_write_message(log_level::value, int, const char*, va_list);
>    int write_message(log_level::value level , int error_code, const char *msg);
> +	void get_state_string(enum_backup_state state, String *str);
>  
>   private:
>  
> +  int cleanup();
> +  void get_next_backup_id();
>    List<MYSQL_ERROR> errors;  ///< Used to store saved errors.
>    bool m_save_errors;        ///< Flag telling if errors should be saved.
> +  ulonglong m_next_id;       ///< the next available backup_id

I don't think you really need m_next_id. This is used internally for generating 
next backup id and there is no reason to store this value in a Logger instance.

>  };
>  
>  inline
>  Logger::Logger(THD *thd) 
>    :m_type(BACKUP), m_state(CREATED),
> -   m_thd(thd), m_op_id(0), m_save_errors(FALSE)
> +   m_thd(thd), m_op_id(0), m_op_hist(0), m_save_errors(FALSE), m_next_id(0)
>  {}
>  
>  inline
> @@ -104,33 +138,29 @@ Logger::~Logger()
>  }
>  
>  /**
> -  Initialize logger for backup or restore operation.
> -  
> -  A new id for that operation is assigned and stored in @c m_op_id
> -  member.
> -  
> -  @param[in]  type  type of operation (backup or restore)
> -  @param[in]  path  location of the backup image
> -  @param[in]  query backup or restore query starting the operation
> -  
> -  @returns 0 on success, error code otherwise.
> -
> -  @todo Decide what to do if @c report_ob_init() signals errors.
> - */ 
> +  Free the memory for the history data.
> +*/
>  inline
> -int Logger::init(enum_type type, const LEX_STRING path, const char *query)
> +int Logger::cleanup()
>  {
> -  if (m_state != CREATED)
> -    return 0;
> -
> -  m_type= type;
> -  m_state= READY;
> -
> -  // TODO: how to detect and report errors in report_ob_init()?
> -  m_op_id= report_ob_init(m_thd, m_thd->id, BUP_STARTING, 
> -                          type == BACKUP ? OP_BACKUP : OP_RESTORE, 
> -                          0, "", path.str, query);  
> -  BACKUP_BREAKPOINT("bp_starting_state");
> +  if (m_op_hist)
> +  {
> +    /*
> +    Free memory for strings used
> +    */
> +    if (m_op_hist->backup_file)
> +      delete m_op_hist->backup_file;
> +    if (m_op_hist->binlog_file)
> +      delete m_op_hist->binlog_file;
> +    if (m_op_hist->command)
> +      delete m_op_hist->command;
> +    if (m_op_hist->engine_name)
> +      delete m_op_hist->engine_name;
> +    if (m_op_hist->user_comment)
> +      delete m_op_hist->user_comment;
> +    my_free(m_op_hist, MYF(0));
> +    m_op_hist= 0;
> +  }

~Logger() is a good place for such cleanup. The advantage is that memory will be 
freed even if someone forgets to call cleanup().

>    return 0;
>  }
>  
> @@ -228,7 +258,8 @@ void Logger::report_start(time_t when)
>    
>    report_error(log_level::INFO, m_type == BACKUP ? ER_BACKUP_BACKUP_START
>                                                   : ER_BACKUP_RESTORE_START);  
> -  report_ob_time(m_thd, m_op_id, when, 0);
> +  if (when)
> +    m_op_hist->start= when;

I'd assume that if someone calls report_start() then he provides a valid timestamp.

>    report_state(BUP_RUNNING);
>  }
>  
> @@ -247,8 +278,10 @@ void Logger::report_stop(time_t when, bo
>  
>    report_error(log_level::INFO, m_type == BACKUP ? ER_BACKUP_BACKUP_DONE
>                                                   : ER_BACKUP_RESTORE_DONE);  
> -  report_ob_time(m_thd, m_op_id, 0, when);
> +  if (when)
> +    m_op_hist->stop= when;
>    report_state(success ? BUP_COMPLETE : BUP_ERRORS);
> +  cleanup();
>    m_state= DONE;
>  }
>  
> @@ -256,7 +289,7 @@ void Logger::report_stop(time_t when, bo
>    Report change of the state of operation
>   
>    For possible states see definition of @c enum_backup_state in 
> -  backup_progress.h
> +  backup_log.h
>  
>    @todo Consider reporting state changes in the server error log (as info
>    entries).
> @@ -264,10 +297,15 @@ void Logger::report_stop(time_t when, bo
>  inline
>  void Logger::report_state(enum_backup_state state)
>  {
> +  String str;
>    DBUG_ASSERT(m_state == RUNNING);
>    
>    // TODO: info about state change in the log?
> -  report_ob_state(m_thd, m_op_id, state);
> +
> +  m_op_hist->state= state;
> +  get_state_string(state, &str);
> +  write_progress(m_thd, m_op_hist, "backup kernel", 0, 
> +                     0, 0, 0, 0, str.c_ptr());
>  }
>  
>  /// Report validity point creation time.
> @@ -276,7 +314,8 @@ void Logger::report_vp_time(time_t when)
>  {
>    DBUG_ASSERT(m_state == RUNNING);
>    
> -  report_ob_vp_time(m_thd, m_op_id, when);
> +  if (when)
> +    m_op_hist->vp_time= when;

An entry should be written to the progress log I think.

>  }
>  
>  /** 
> @@ -290,17 +329,162 @@ void Logger::report_binlog_pos(const st_
>    DBUG_ASSERT(m_state == RUNNING);
>    
>    // TODO: write to the log
> -  report_ob_binlog_info(m_thd, m_op_id, pos.pos, pos.file);
> +  m_op_hist->binlog_pos= pos.pos;
> +  if (!m_op_hist->binlog_file && (strlen(pos.file) > 0))
> +  {
> +    m_op_hist->binlog_file= new char[strlen(pos.file)+1];
> +    strcpy(m_op_hist->binlog_file, pos.file);

Why allocating memory and copying sting here. I think it is safe to assume that 
the name of binlog is already stored safely in the Image_info structure. Then 
the only thing you have to do is

   m_op_hist->binlog_pos= pos.pos;
   m_op_hist->binlog_file= pos.file;

> +  }
> +}
> +
> +/**
> +  Update the error number for the row.
> +
> +  This method saves error number value to the history data.
> +
> +  @param[IN] THD               thd          The current thread class.
> +  @param[IN] int               error_num    New error number.
> +*/
> +inline
> +void Logger::report_error_to_log(THD *thd,
> +                                    int error_num)
> +{
> +  m_op_hist->error_num= error_num;
>  }
>  
> -/// Report name of a driver used in backup/restore operation.
> +/**
> +  Update the number of objects for the row.
> +
> +  This method updates the number of objects value in the history data.
> +
> +  @param[IN] THD               thd          The current thread class.
> +  @param[IN[ int               num_objects  New error number.
> +*/
>  inline
> -void Logger::report_driver(const char *name)
> +void Logger::report_num_objects(THD *thd,
> +                               int num_objects)
>  {
> -  DBUG_ASSERT(m_state == READY || m_state == RUNNING);
> +  m_op_hist->num_objects= num_objects;
> +}
> +
> +/**
> +  Update the size for the row.
> +
> +  This method updates the size value in the history data.
> +
> +  @param[IN] THD               thd          The current thread class.
> +  @param[IN] int               size         New size value.
> +*/
> +inline
> +void Logger::report_size(THD *thd, longlong size)
> +{
> +  m_op_hist->size= size;
> +}
> +
> +/**
> +  Initialize logger for backup or restore operation.
> +  
> +  A new id for that operation is assigned and stored in @c m_op_hist
> +  member.
> +  
> +  @param[in]  type  type of operation (backup or restore)
> +  @param[in]  path  location of the backup image
> +  @param[in]  query backup or restore query starting the operation
>    
> -  report_ob_engines(m_thd, m_op_id, name);
> +  @returns 0 on success, error code otherwise.
> +
> +  @todo Decide what to do if @c initialize() signals errors.
> +  @todo Add code to get the user comment from command.
> +*/ 
> +inline
> +int Logger::init(enum_type type, const LEX_STRING path, const char *query)
> +{
> +  ulonglong backup_id= 0;
> +
> +  if (m_state != CREATED)
> +    return 0;
> +
> +  m_type= type;
> +  m_state= READY;
> +
> +  m_op_hist= (st_backup_history *)my_malloc(sizeof(st_backup_history), 
> +    MYF(MY_WME | MY_ZEROFILL));
> +  m_op_hist->user_comment= 0; 
> +  m_op_hist->backup_file= 0; 
> +  m_op_hist->command= 0; 
> +  m_op_hist->engine_name= 0; 
> +  m_op_hist->binlog_file= 0; 
> +  m_op_hist->process_id= m_thd->id;
> +  m_op_hist->state= BUP_STARTING;
> +  m_op_hist->operation= BACKUP ? OP_BACKUP : OP_RESTORE;
> +  m_op_hist->error_num= 0;
> +

This can be done neatly by:

   bzero(m_op_hist,sizeof(st_backup_history);
   <set the non-zero members>;

> +  if (!m_op_hist->backup_file && (path.length > 0))
> +  {
> +    m_op_hist->backup_file= new char[path.length+1];
> +    strcpy(m_op_hist->backup_file, path.str);
> +  }
> +  if (!m_op_hist->command && (strlen(query) > 0))
> +  {
> +    m_op_hist->command= new char[strlen(query)+1];
> +    strcpy(m_op_hist->command, query);
> +  }
> +

Again, most probably the path and query strings remain in memory for the 
lifetime of the Logger object, so no need to copy the strings.

> +  pthread_mutex_lock(&LOCK_backupid);
> +  get_next_backup_id();
> +  m_op_hist->backup_id= m_next_id;
> +  pthread_mutex_unlock(&LOCK_backupid);

I think the backup id generation should be done inside Backup_restore_ctx. But 
in either case, the mutex protection can be done inside get_next_backup_id() so 
that the caller of that method doesn't have to remember about it (less error-prone).

> +
> +  /*
> +    Record progress update.
> +  */
> +  String str;
> +  get_state_string(BUP_STARTING, &str);
> +  write_progress(m_thd, m_op_hist, "backup kernel", 0, 
> +                 0, 0, 0, 0, str.c_ptr());
> +

This should be done with report_state(BUP_STARTING).

> +  if (m_op_hist)
> +    m_op_id= m_op_hist->backup_id;
> +  BACKUP_BREAKPOINT("bp_starting_state");
> +  return 0;
>  }
> +
> +/**
> +  Get text string for state.
> +
> +  @param enum_backup_state  state        The current state of the operation
> +
> +  @returns char * a text string for state.
> +*/

There is really no need to use heavy String class here (with the dynamic memory 
allocation done in str->append). One can define this method simply like this:

inline
const char* Logger::get_state_string(enum_backup_state)
{
    switch (state) {
    case BUP_COMPLETE: return "complete";
    ...
    }
}

> +inline
> +void Logger::get_state_string(enum_backup_state state, String *str)
> +{
> +  str->length(0);
> +  switch (state) {
> +  case BUP_COMPLETE:
> +    str->append("complete");
> +    break;
> +  case BUP_STARTING:
> +    str->append("starting");
> +    break;
> +  case BUP_VALIDITY_POINT:
> +    str->append("validity point");
> +    break;
> +  case BUP_RUNNING:
> +    str->append("running");
> +    break;
> +  case BUP_ERRORS:
> +    str->append("error");
> +    break;
> +  case BUP_CANCEL:
> +    str->append("cancel");
> +    break;
> +  default:
> +    str->append("unknown");
> +    break;
> +  }
> +}
> +
>  
>  } // backup namespace
>  
> 


> === modified file 'sql/log.cc'
> --- a/sql/log.cc	2008-05-23 21:39:20 +0000
> +++ b/sql/log.cc	2008-06-25 21:29:44 +0000
> @@ -114,6 +114,34 @@ char *make_default_log_name(char *buff,c
>  }
>  
>  /*
> +  Set the default for the backupdir
> +*/
> +char *make_default_backupdir(char *buff)
> +{
> +  strmake(buff, mysql_data_home, FN_REFLEN-5);
> +  return buff;
> +}
> +
> +/**
> +  Create the name of the backup log specified.
> +
> +  This method forms a new path + file name for the backup
> +  log specified in @c name.
> +
> +  @param[IN] buff    Location for building new string.
> +  @param[IN] name    Name of the backup log.
> +  @param[IN] log_ext The extension for the log (e.g. .log).
> +
> +  @returns Pointer to new string containing the name.
> +*/
> +char *make_backup_log_name(char *buff, const char *name, const char* log_ext)
> +{
> +  strmake(buff, name, FN_REFLEN-5);
> +  return fn_format(buff, buff, mysql_data_home, log_ext,
> +                   MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT));

Unsafe, since you don't check the space available in buff.

> +}
> +
> +/*
>    Helper class to hold a mutex for the duration of the
>    block.
>  
> @@ -682,16 +710,37 @@ int Log_to_csv_event_handler::
>  
>    bzero(& table_list, sizeof(TABLE_LIST));
>  
> -  if (log_table_type == QUERY_LOG_GENERAL)
> +  /*
> +    Code changed to use a switch now that there are 4 logs.
> +  */

I think such comments should go rather to the change set, not the source.

> +  switch (log_table_type) {
> +  case QUERY_LOG_GENERAL:
>    {
>      table_list.alias= table_list.table_name= GENERAL_LOG_NAME.str;
>      table_list.table_name_length= GENERAL_LOG_NAME.length;
> +    break;
>    }
> -  else
> +  case QUERY_LOG_SLOW:
>    {
>      DBUG_ASSERT(log_table_type == QUERY_LOG_SLOW);
>      table_list.alias= table_list.table_name= SLOW_LOG_NAME.str;
>      table_list.table_name_length= SLOW_LOG_NAME.length;
> +    break;
> +  }
> +  case BACKUP_HISTORY_LOG:
> +  {
> +    DBUG_ASSERT(log_table_type == BACKUP_HISTORY_LOG);
> +    table_list.alias= table_list.table_name= BACKUP_HISTORY_LOG_NAME.str;
> +    table_list.table_name_length= BACKUP_HISTORY_LOG_NAME.length;
> +    break;
> +  }
> +  case BACKUP_PROGRESS_LOG:
> +  {
> +    DBUG_ASSERT(log_table_type == BACKUP_PROGRESS_LOG);
> +    table_list.alias= table_list.table_name= BACKUP_PROGRESS_LOG_NAME.str;
> +    table_list.table_name_length= BACKUP_PROGRESS_LOG_NAME.length;
> +    break;
> +  }
>    }
>  
>    table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
> @@ -712,6 +761,335 @@ int Log_to_csv_event_handler::
>    DBUG_RETURN(result);
>  }
>  
> +/**
> +  Write the backup log entry for the backup history log to a table.
> +
> +  This method creates a new row in the backup history log with the
> +  information provided.
> +
> +  @param[IN]   thd   The current thread
> +  @param[IN]   st_backup_history   Data to write to log.
> +
> +  @retval TRUE if error.
> +
> +  @todo Add internal error handler to handle errors that occur on
> +        open. See  thd->push_internal_handler(&error_handler).
> +*/
> +bool Log_to_csv_event_handler::
> +  log_backup_history(THD *thd, 
> +                     st_backup_history *history_data)

I think this code, should be put in the MYSQL_BACKUP_LOG class, together with 
the code which writes log entries to a file. Here you only need to call an 
appropriate method of MYSQL_BACKUP_LOG class as is done in the case of 
Log_to_file_event_handler.

> +{
> +  TABLE_LIST table_list;
> +  TABLE *table= NULL;
> +  bool result= TRUE;
> +  bool need_close= FALSE;
> +  bool need_rnd_end= FALSE;
> +  Open_tables_state open_tables_backup;
> +  bool save_time_zone_used;
> +  char *host= current_thd->security_ctx->host; // host name
> +  char *user= current_thd->security_ctx->user; // user name
> +
> +  save_time_zone_used= thd->time_zone_used;
> +  bzero(& table_list, sizeof(TABLE_LIST));
> +  table_list.alias= table_list.table_name= BACKUP_HISTORY_LOG_NAME.str;
> +  table_list.table_name_length= BACKUP_HISTORY_LOG_NAME.length;
> +
> +  table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
> +
> +  table_list.db= MYSQL_SCHEMA_NAME.str;
> +  table_list.db_length= MYSQL_SCHEMA_NAME.length;
> +
> +  if (!(table= open_performance_schema_table(thd, & table_list,
> +                                             & open_tables_backup)))
> +    goto err;

I don't require that for approval, but for efficiency reasons I'd rather open 
the log table once and only write rows here. Even if it is not possible to open 
table so that other threads can write to it as well, we don't really need such 
functionality. For the backup logs, we could make them usable only from a single 
thread, as we have only one BACKUP/RESTORE command running at a time.

> +
> +  need_close= TRUE;
> +
> +  if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
> +      table->file->ha_rnd_init(0))
> +    goto err;
> +
> +  need_rnd_end= TRUE;
> +
> +  /*
> +    Get defaults for new record.
> +  */
> +  restore_record(table, s->default_values); 
> +
> +  /* check that all columns exist */
> +  if (table->s->fields < ET_OBH_FIELD_COUNT)
> +    goto err;
> +
> +  /*
> +    Fill in the data.
> +  */
> +  table->field[ET_OBH_FIELD_BACKUP_ID]->store(history_data->backup_id,
> TRUE);
> +  table->field[ET_OBH_FIELD_BACKUP_ID]->set_notnull();
> +  table->field[ET_OBH_FIELD_PROCESS_ID]->store(history_data->process_id,
> TRUE);
> +  table->field[ET_OBH_FIELD_PROCESS_ID]->set_notnull();
> +  table->field[ET_OBH_FIELD_BINLOG_POS]->store(history_data->binlog_pos,
> TRUE);
> +  table->field[ET_OBH_FIELD_BINLOG_POS]->set_notnull();
> +
> +  if (history_data->binlog_file)
> +  {
> +    if
> (table->field[ET_OBH_FIELD_BINLOG_FILE]->store(history_data->binlog_file, 
> +                                                     
> strlen(history_data->binlog_file), 
> +                                                      system_charset_info))
> +      goto err;
> +    table->field[ET_OBH_FIELD_BINLOG_FILE]->set_notnull();
> +  }
> +
> +  table->field[ET_OBH_FIELD_BACKUP_STATE]->store(history_data->state,
> TRUE);
> +  table->field[ET_OBH_FIELD_BACKUP_STATE]->set_notnull();
> +  table->field[ET_OBH_FIELD_OPER]->store(history_data->operation, TRUE);
> +  table->field[ET_OBH_FIELD_OPER]->set_notnull();
> +  table->field[ET_OBH_FIELD_ERROR_NUM]->store(history_data->error_num,
> TRUE);
> +  table->field[ET_OBH_FIELD_ERROR_NUM]->set_notnull();
> +  table->field[ET_OBH_FIELD_NUM_OBJ]->store(history_data->num_objects,
> TRUE);
> +  table->field[ET_OBH_FIELD_NUM_OBJ]->set_notnull();
> +  table->field[ET_OBH_FIELD_TOTAL_BYTES]->store(history_data->size, TRUE);
> +  table->field[ET_OBH_FIELD_TOTAL_BYTES]->set_notnull();
> +
> +  if (history_data->vp_time)
> +  {
> +    MYSQL_TIME time;
> +    my_tz_OFFSET0->gmt_sec_to_TIME(&time,
> (my_time_t)history_data->vp_time);
> +
> +    table->field[ET_OBH_FIELD_VP]->set_notnull();
> +    table->field[ET_OBH_FIELD_VP]->store_time(&time,
> MYSQL_TIMESTAMP_DATETIME);
> +  }
> +
> +  if (history_data->start)
> +  {
> +    MYSQL_TIME time;
> +    my_tz_OFFSET0->gmt_sec_to_TIME(&time,
> (my_time_t)history_data->start);
> +
> +    table->field[ET_OBH_FIELD_START_TIME]->set_notnull();
> +    table->field[ET_OBH_FIELD_START_TIME]->store_time(&time,
> MYSQL_TIMESTAMP_DATETIME);
> +  }
> +
> +  if (history_data->stop)
> +  {
> +    MYSQL_TIME time;
> +    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)history_data->stop);
> +
> +    table->field[ET_OBH_FIELD_STOP_TIME]->set_notnull();
> +    table->field[ET_OBH_FIELD_STOP_TIME]->store_time(&time,
> MYSQL_TIMESTAMP_DATETIME);
> +  }
> +
> +  if (host)
> +  {
> +    if(table->field[ET_OBH_FIELD_HOST_OR_SERVER]->store(host, 
> +       strlen(host), system_charset_info))
> +      goto err;
> +    table->field[ET_OBH_FIELD_HOST_OR_SERVER]->set_notnull();
> +  }
> +
> +  if (user)
> +  {
> +    if (table->field[ET_OBH_FIELD_USERNAME]->store(user,
> +        strlen(user), system_charset_info))
> +      goto err;
> +    table->field[ET_OBH_FIELD_USERNAME]->set_notnull();
> +  }
> +
> +  if (history_data->backup_file)
> +  {
> +    if (table->field[ET_OBH_FIELD_BACKUP_FILE]->store(
> +        history_data->backup_file, 
> +        strlen(history_data->backup_file), system_charset_info))
> +      goto err;
> +    table->field[ET_OBH_FIELD_BACKUP_FILE]->set_notnull();
> +  }
> +
> +  if (history_data->user_comment)
> +  {
> +    if
> (table->field[ET_OBH_FIELD_COMMENT]->store(history_data->user_comment,
> +        strlen(history_data->user_comment), system_charset_info))
> +      goto err;
> +    table->field[ET_OBH_FIELD_COMMENT]->set_notnull();
> +  }
> +
> +  if (history_data->command)
> +  {
> +    if (table->field[ET_OBH_FIELD_COMMAND]->store(history_data->command,
> +        strlen(history_data->command), system_charset_info))
> +      goto err;
> +    table->field[ET_OBH_FIELD_COMMAND]->set_notnull();
> +  }
> +
> +  if (history_data->engine_name)
> +  {
> +    if
> (table->field[ET_OBH_FIELD_DRIVERS]->store(history_data->engine_name,
> +        strlen(history_data->engine_name), system_charset_info))
> +      goto err;
> +    table->field[ET_OBH_FIELD_DRIVERS]->set_notnull();
> +  }
> +
> +  /* log table entries are not replicated */
> +  if (table->file->ha_write_row(table->record[0]))
> +    goto err;
> +
> +  result= FALSE;
> +
> +err:
> +  if (result && !thd->killed)
> +    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
> +                        ER_BACKUP_LOG_WRITE_ERROR,
> +                        ER(ER_BACKUP_LOG_WRITE_ERROR),
> +                        "mysql.backup_history");
> +
> +  if (need_rnd_end)
> +    table->file->ha_rnd_end();
> +  if (need_close)
> +    close_performance_schema_table(thd, & open_tables_backup);
> +
> +  thd->time_zone_used= save_time_zone_used;
> +  return result;
> +}
> +
> +/**
> +  Write the backup log entry for the backup progress log to a table.
> +
> +  This method creates a new row in the backup progress log with the
> +  information provided.
> +
> +  @param[IN]   thd         The current thread
> +  @param[OUT]  backup_id   The id of the backup/restore operation for
> +                           the progress information
> +  @param[IN]   object      The name of the object processed
> +  @param[IN]   start       Start datetime
> +  @param[IN]   stop        Stop datetime
> +  @param[IN]   size        Size value
> +  @param[IN]   progress    Progress (percent)
> +  @param[IN]   error_num   Error number (should be 0 if success)
> +  @param[IN]   notes       Misc data from engine
> +
> +  @retval TRUE if error.
> +
> +  @todo Add internal error handler to handle errors that occur on
> +        open. See  thd->push_internal_handler(&error_handler).
> +*/
> +bool Log_to_csv_event_handler::
> +  log_backup_progress(THD *thd,
> +                      ulonglong backup_id,
> +                      const char *object,
> +                      time_t start,
> +                      time_t stop,
> +                      longlong size,
> +                      longlong progress,
> +                      int error_num,
> +                      const char *notes)
> +{
> +  TABLE_LIST table_list;
> +  TABLE *table;
> +  bool result= TRUE;
> +  bool need_close= FALSE;
> +  bool need_rnd_end= FALSE;
> +  Open_tables_state open_tables_backup;
> +  bool save_time_zone_used;
> +
> +  save_time_zone_used= thd->time_zone_used;
> +
> +  bzero(& table_list, sizeof(TABLE_LIST));
> +  table_list.alias= table_list.table_name= BACKUP_PROGRESS_LOG_NAME.str;
> +  table_list.table_name_length= BACKUP_PROGRESS_LOG_NAME.length;
> +
> +  table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
> +
> +  table_list.db= MYSQL_SCHEMA_NAME.str;
> +  table_list.db_length= MYSQL_SCHEMA_NAME.length;
> +
> +  if (!(table= open_performance_schema_table(thd, & table_list,
> +                                             & open_tables_backup)))
> +    goto err;
> +
> +  need_close= TRUE;
> +
> +  if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
> +      table->file->ha_rnd_init(0))
> +    goto err;
> +
> +  need_rnd_end= TRUE;
> +
> +  /*
> +    Get defaults for new record.
> +  */
> +  restore_record(table, s->default_values); 
> +
> +  /* check that all columns exist */
> +  if (table->s->fields < ET_OBP_FIELD_PROG_COUNT)
> +    goto err;
> +
> +  /*
> +    Fill in the data.
> +  */
> +  table->field[ET_OBP_FIELD_BACKUP_ID_FK]->store(backup_id, TRUE);
> +  table->field[ET_OBP_FIELD_BACKUP_ID_FK]->set_notnull();
> +
> +  if (object)
> +  {
> +    if (table->field[ET_OBP_FIELD_PROG_OBJECT]->store(object,
> +        strlen(object), system_charset_info))
> +      goto err;
> +    table->field[ET_OBP_FIELD_PROG_OBJECT]->set_notnull();
> +  }
> +
> +  if (start)
> +  {
> +    MYSQL_TIME time;
> +    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)start);
> +
> +    table->field[ET_OBP_FIELD_PROG_START_TIME]->set_notnull();
> +    table->field[ET_OBP_FIELD_PROG_START_TIME]->store_time(&time,
> MYSQL_TIMESTAMP_DATETIME);
> +  }
> +
> +  if (stop)
> +  {
> +    MYSQL_TIME time;
> +    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)stop);
> +
> +    table->field[ET_OBP_FIELD_PROG_STOP_TIME]->set_notnull();
> +    table->field[ET_OBP_FIELD_PROG_STOP_TIME]->store_time(&time,
> MYSQL_TIMESTAMP_DATETIME);
> +  }
> +
> +  table->field[ET_OBP_FIELD_PROG_SIZE]->store(size, TRUE);
> +  table->field[ET_OBP_FIELD_PROG_SIZE]->set_notnull();
> +  table->field[ET_OBP_FIELD_PROGRESS]->store(progress, TRUE);
> +  table->field[ET_OBP_FIELD_PROGRESS]->set_notnull();
> +  table->field[ET_OBP_FIELD_PROG_ERROR_NUM]->store(error_num, TRUE);
> +  table->field[ET_OBP_FIELD_PROG_ERROR_NUM]->set_notnull();
> +
> +  if (notes)
> +  {
> +    if (table->field[ET_OBP_FIELD_PROG_NOTES]->store(notes,
> +        strlen(notes), system_charset_info))
> +      goto err;
> +    table->field[ET_OBP_FIELD_PROG_NOTES]->set_notnull();
> +  }
> +
> +  /* log table entries are not replicated */
> +  if (table->file->ha_write_row(table->record[0]))
> +    goto err;
> +
> +  result= FALSE;
> +
> +err:
> +  if (result && !thd->killed)
> +    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
> +                        ER_BACKUP_LOG_WRITE_ERROR,
> +                        ER(ER_BACKUP_LOG_WRITE_ERROR),
> +                        "mysql.backup_progress");
> +
> +  if (need_rnd_end)
> +    table->file->ha_rnd_end();
> +  if (need_close)
> +    close_performance_schema_table(thd, & open_tables_backup);
> +
> +  thd->time_zone_used= save_time_zone_used;
> +  return result;
> +}
> +
>  bool Log_to_csv_event_handler::
>    log_error(enum loglevel level, const char *format, va_list args)
>  {
> @@ -731,6 +1109,8 @@ void Log_to_file_event_handler::init_pth
>  {
>    mysql_log.init_pthread_objects();
>    mysql_slow_log.init_pthread_objects();
> +  mysql_backup_history_log.init_pthread_objects();
> +  mysql_backup_progress_log.init_pthread_objects();
>  }
>  
>  
> @@ -774,6 +1154,65 @@ bool Log_to_file_event_handler::
>    return retval;
>  }
>  
> +/**
> +  Write the history data to a file.
> +
> +  This method calls the write method for the backup log
> +  class to write the history data to the file.
> +
> +  @param[IN]   thd   The current thread
> +  @param[IN]   st_backup_history   Data to write to log.
> +
> +  @returns TRUE if error.
> +*/
> +bool Log_to_file_event_handler::
> +  log_backup_history(THD *thd, 
> +                     st_backup_history *history_data)
> +{
> +  Silence_log_table_errors error_handler;
> +  thd->push_internal_handler(&error_handler);
> +  bool retval= mysql_backup_history_log.write(thd, history_data);
> +  thd->pop_internal_handler();
> +  return retval;
> +}
> +
> +/**
> +  Write the progress data to a file.
> +
> +  This method calls the write method for the backup log
> +  class to write the progress data to the file.
> +
> +  @param[IN]   thd         The current thread
> +  @param[OUT]  backup_id   The new row id for the backup history
> +  @param[IN]   object      The name of the object processed
> +  @param[IN]   start       Start datetime
> +  @param[IN]   stop        Stop datetime
> +  @param[IN]   size        Size value
> +  @param[IN]   progress    Progress (percent)
> +  @param[IN]   error_num   Error number (should be 0 is success)
> +  @param[IN]   notes       Misc data from engine
> +
> +  @returns TRUE if error.
> +*/
> +bool Log_to_file_event_handler::
> +  log_backup_progress(THD *thd,
> +                      ulonglong backup_id,
> +                      const char *object,
> +                      time_t start,
> +                      time_t stop,
> +                      longlong size,
> +                      longlong progress,
> +                      int error_num,
> +                      const char *notes)
> +{
> +  Silence_log_table_errors error_handler;
> +  thd->push_internal_handler(&error_handler);
> +  bool retval= mysql_backup_progress_log.write(thd, backup_id, object, start,
> +                 stop, size, progress, error_num, notes);

I suggest to rename the method to write_to_file(...) and define similar 
write_to_table(...) method in MYSQL_BACKUP_LOG and call it from the 
Log_to_cvs_event_handler.

An alternative would be to implement write() method so that it can write to both 
table and file. See below for more thoughs on that.

> +  thd->pop_internal_handler();
> +  return retval;
> +}
> +
>  
>  bool Log_to_file_event_handler::init()
>  {
> @@ -785,17 +1224,39 @@ bool Log_to_file_event_handler::init()
>      if (opt_log)
>        mysql_log.open_query_log(sys_var_general_log_path.value);
>  
> +    /*
> +      Check the backup log options and open if they are turned on.
> +    */
> +    if (opt_backup_history_log)
> +      mysql_backup_history_log.open_backup_history_log(
> +        sys_var_backup_history_log_path.value);
> +
> +    if (opt_backup_progress_log)
> +      mysql_backup_progress_log.open_backup_progress_log(
> +        sys_var_backup_progress_log_path.value);
> +
>      is_initialized= TRUE;
>    }
>  
>    return FALSE;
>  }
>  
> +/**
> +  Close and reopen the backup logs.
> +*/
> +void Log_to_file_event_handler::flush_backup_logs()
> +{
> +  /* reopen log files */
> +  mysql_backup_history_log.reopen_file(TRUE);
> +  mysql_backup_progress_log.reopen_file(FALSE);

Would be nice to add comments explaining the meaning of TRUE and FALSE.

> +}
>  
>  void Log_to_file_event_handler::cleanup()
>  {
>    mysql_log.cleanup();
>    mysql_slow_log.cleanup();
> +  mysql_backup_history_log.cleanup();
> +  mysql_backup_progress_log.cleanup();
>  }
>  
>  void Log_to_file_event_handler::flush()
> @@ -914,6 +1375,32 @@ bool LOGGER::flush_logs(THD *thd)
>  }
>  
>  
> +/**
> +  Close and reopen the backup logs (with locks).
> +
> +  @param[IN]  thd   The current thread.
> +
> +  @returns FALSE.
> +*/
> +bool LOGGER::flush_backup_logs(THD *thd)
> +{
> +  int rc= 0;
> +
> +  /*
> +    Now we lock logger, as nobody should be able to use logging routines while
> +    log tables are closed
> +  */
> +  logger.lock_exclusive();
> +
> +  /* reopen log files */
> +  file_log_handler->flush_backup_logs();
> +
> +  /* end of log flush */
> +  logger.unlock();
> +  return rc;
> +}
> +
> +
>  /*
>    Log slow query with all enabled log event handlers
>  
> @@ -1065,6 +1552,106 @@ bool LOGGER::general_log_print(THD *thd,
>    return general_log_write(thd, command, message_buff, message_buff_len);
>  }
>  
> +
> +/**
> +  Write the backup log entry for the backup history logs (file or table).
> +
> +  This method creates a new row in the backup history log with the
> +  information provided. It is a high-level wrapper for writing to any
> +  of the log types (e.g., FILE or TABLE) as specified by --log-option.
> +
> +  @Note The backup logs currently only write to tables.
> +
> +  @param[IN]   thd   The current thread
> +  @param[IN]   st_backup_history   Data to write to log.
> +  
> +  @returns TRUE if error.
> +*/
> +bool LOGGER::
> +  backup_history_log_write(THD *thd, 
> +                           st_backup_history *history_data)
> +{
> +  bool error= FALSE;
> +  Log_event_handler **current_handler= backup_history_log_handler_list;
> +  ulong id;
> +
> +  /*
> +    Don't write if log is turned off.
> +  */
> +  if (!opt_backup_history_log)
> +    return 0;
> +
> +  if (thd)
> +    id= thd->thread_id;                 /* Normal thread */
> +  else
> +    id= 0;                              /* Log from connect handler */
> +
> +  lock_shared();
> +  while (*current_handler)
> +    error|= (*current_handler++)->
> +      log_backup_history(thd, history_data) || error;
> +  unlock();
> +
> +  return error;
> +}
> +
> +/**
> +  Write the backup log entry for the backup progress logs (file or table).
> +
> +  This method creates a new row in the backup progress log with the
> +  information provided. It is a high-level wrapper for writing to any
> +  of the log types (e.g., FILE or TABLE) as specified by --log-option.
> +
> +  @Note The backup logs currently only write to tables.
> +
> +  @param[IN]   thd         The current thread
> +  @param[OUT]  backup_id   The new row id for the backup history
> +  @param[IN]   object      The name of the object processed
> +  @param[IN]   start       Start datetime
> +  @param[IN]   stop        Stop datetime
> +  @param[IN]   size        Size value
> +  @param[IN]   progress    Progress (percent)
> +  @param[IN]   error_num   Error number (should be 0 is success)
> +  @param[IN]   notes       Misc data from engine
> +
> +  @returns TRUE if error.
> +*/
> +bool LOGGER::backup_progress_log_write(THD *thd,
> +                                       ulonglong backup_id,
> +                                       const char *object,
> +                                       time_t start,
> +                                       time_t stop,
> +                                       longlong size,
> +                                       longlong progress,
> +                                       int error_num,
> +                                       const char *notes)
> +{
> +  bool error= FALSE;
> +  Log_event_handler **current_handler= backup_progress_log_handler_list;
> +  ulong id;
> +
> +  /*
> +    Don't write if log is turned off.
> +  */
> +  if (!opt_backup_progress_log)
> +    return 0;
> +
> +  if (thd)
> +    id= thd->thread_id;                 /* Normal thread */
> +  else
> +    id= 0;                              /* Log from connect handler */
> +
> +  lock_shared();
> +  while (*current_handler)
> +    error|= (*current_handler++)->
> +      log_backup_progress(thd, backup_id, object, start, 
> +                             stop, size, progress, error_num, notes) || error;
> +  unlock();
> +
> +  return error;
> +}
> +
> +
>  void LOGGER::init_error_log(uint error_log_printer)
>  {
>    if (error_log_printer & LOG_NONE)
> @@ -1139,9 +1726,77 @@ void LOGGER::init_general_log(uint gener
>  }
>  
>  
> +/**
> +  Initialize the backup history log.
> +
> +  This method initializes the backup log handlers. Currently, only
> +  log to table is supported.
> +
> +  @param[IN]   backup_history_log_printer  The output type for log.
> +*/
> +void LOGGER::init_backup_history_log(uint backup_history_log_printer)
> +{
> +  if (backup_history_log_printer & LOG_NONE)
> +  {
> +    backup_history_log_handler_list[0]= 0;
> +    return;
> +  }
> +
> +  switch (backup_history_log_printer) {
> +  case LOG_FILE:
> +    backup_history_log_handler_list[0]= file_log_handler;
> +    backup_history_log_handler_list[1]= 0;
> +    break;
> +  case LOG_TABLE:
> +    backup_history_log_handler_list[0]= table_log_handler;
> +    backup_history_log_handler_list[1]= 0;
> +    break;
> +  case LOG_TABLE|LOG_FILE:
> +    backup_history_log_handler_list[0]= file_log_handler;
> +    backup_history_log_handler_list[1]= table_log_handler;
> +    backup_history_log_handler_list[2]= 0;
> +    break;
> +  }
> +}
> +
> +/**
> +  Initialize the backup progress log.
> +
> +  This method initializes the backup log handlers. Currently, only
> +  log to table is supported.
> +
> +  @param[IN]   backup_history_log_printer  The output type for log.
> +*/
> +void LOGGER::init_backup_progress_log(uint backup_progress_log_printer)
> +{
> +  if (backup_progress_log_printer & LOG_NONE)
> +  {
> +    backup_progress_log_handler_list[0]= 0;
> +    return;
> +  }
> +
> +  switch (backup_progress_log_printer) {
> +  case LOG_FILE:
> +    backup_progress_log_handler_list[0]= file_log_handler;
> +    backup_progress_log_handler_list[1]= 0;
> +    break;
> +  case LOG_TABLE:
> +    backup_progress_log_handler_list[0]= table_log_handler;
> +    backup_progress_log_handler_list[1]= 0;
> +    break;
> +  case LOG_TABLE|LOG_FILE:
> +    backup_progress_log_handler_list[0]= file_log_handler;
> +    backup_progress_log_handler_list[1]= table_log_handler;
> +    backup_progress_log_handler_list[2]= 0;
> +    break;
> +  }
> +}
> +
> +
>  bool LOGGER::activate_log_handler(THD* thd, uint log_type)
>  {
>    MYSQL_QUERY_LOG *file_log;
> +  MYSQL_BACKUP_LOG *backup_log;
>    bool res= FALSE;
>    lock_exclusive();
>    switch (log_type) {
> @@ -1183,6 +1838,51 @@ bool LOGGER::activate_log_handler(THD* t
>        }
>      }
>      break;
> +  /*
> +    Check the backup history and progress logs for activation.
> +  */
> +  case BACKUP_HISTORY_LOG:
> +  {
> +    if (!opt_backup_history_log)
> +    {
> +      backup_log= file_log_handler->get_backup_history_log();
> +
> +     
> backup_log->open_backup_history_log(sys_var_backup_history_log_path.value);
> +      if (table_log_handler->activate_log(thd, BACKUP_HISTORY_LOG))
> +      {
> +        /* Error printed by open table in activate_log() */
> +        res= TRUE;
> +        backup_log->close(0);
> +      }
> +      else
> +      {
> +        init_backup_history_log(log_backup_output_options);
> +        opt_backup_history_log= TRUE;
> +      }
> +    }
> +    break;
> +  }
> +  case BACKUP_PROGRESS_LOG:
> +  {
> +    if (!opt_backup_progress_log)
> +    {
> +      backup_log= file_log_handler->get_backup_progress_log();
> +
> +     
> backup_log->open_backup_progress_log(sys_var_backup_progress_log_path.value);
> +      if (table_log_handler->activate_log(thd, BACKUP_PROGRESS_LOG))
> +      {
> +        /* Error printed by open table in activate_log() */
> +        res= TRUE;
> +        backup_log->close(0);
> +      }
> +      else
> +      {
> +        init_backup_progress_log(log_backup_output_options);
> +        opt_backup_progress_log= TRUE;
> +      }
> +    }
> +    break;
> +  }
>    default:
>      DBUG_ASSERT(0);
>    }
> @@ -1205,6 +1905,17 @@ void LOGGER::deactivate_log_handler(THD 
>      tmp_opt= &opt_log;
>      file_log= file_log_handler->get_mysql_log();
>      break;
> +  /*
> +    Deactivate the backup history and progress logs on request.
> +  */
> +  case BACKUP_HISTORY_LOG:
> +    tmp_opt= &opt_backup_history_log;
> +    file_log= file_log_handler->get_backup_history_log();
> +    break;
> +  case BACKUP_PROGRESS_LOG:
> +    tmp_opt= &opt_backup_progress_log;
> +    file_log= file_log_handler->get_backup_progress_log();
> +    break;
>    default:
>      assert(0);                                  // Impossible
>    }
> @@ -1253,6 +1964,30 @@ int LOGGER::set_handlers(uint error_log_
>    return 0;
>  }
>  
> +/**
> +  Set the logging handlers for operation on the backup logs.
> +
> +  This method allows the caller to set the method of logging
> +  for the backup logs. Values for these variables equate
> +  to the {FILE, TABLE, NONE} definitions.
> +
> +  @param[IN] backup_history_log_printer  The type of output.
> +  @param[IN] backup_progress_log_printer The type of output.
> +
> +  @returns 0
> +*/
> +int LOGGER::set_backup_handlers(uint backup_history_log_printer,
> +                                uint backup_progress_log_printer)
> +{
> +  lock_exclusive();
> +
> +  init_backup_history_log(backup_history_log_printer);
> +  init_backup_progress_log(backup_progress_log_printer);
> +
> +  unlock();
> +
> +  return 0;
> +}
>  
>   /*
>    Save position of binary log transaction cache.
> @@ -2332,6 +3067,384 @@ bool MYSQL_QUERY_LOG::write(THD *thd, ti
>  
>  
>  /**
> +  Open a (new) backup log file.
> +
> +  Open the backup log file, init IO_CACHE and write startup messages.
> +
> +  @param[IN] log_name          The name of the log to open
> +  @param[IN] log_type_arg      The type of the log. E.g. LOG_NORMAL
> +  @param[IN] new_name          The new name for the logfile.
> +  @param[IN] io_cache_type_arg The type of the IO_CACHE to use for this loge
> +  @param[IN] history           If TRUE, process history log headeer else do
> +                               progress header
> +
> +  @returns 0 success, 1 error
> +*/
> +bool MYSQL_BACKUP_LOG::open(const char *log_name, 
> +                            enum_log_type log_type_arg,
> +                            const char *new_name, 
> +                            enum cache_type io_cache_type_arg,
> +                            bool history)
> +{
> +  char buff[FN_REFLEN];
> +  File file= -1;
> +  int open_flags= O_CREAT | O_BINARY;
> +  DBUG_ENTER("MYSQL_BACKUP_LOG::open");
> +  DBUG_PRINT("enter", ("log_type: %d", (int) log_type_arg));
> +
> +  write_error= 0;
> +
> +  init(log_type_arg, io_cache_type_arg);
> +
> +  if (!(name= my_strdup(log_name, MYF(MY_WME))))
> +  {
> +    name= (char *)log_name; // for the error message
> +    goto err;
> +  }
> +
> +  if (new_name)
> +    strmov(log_file_name, new_name);
> +  else if (generate_new_name(log_file_name, name))
> +    goto err;
> +
> +  if (io_cache_type == SEQ_READ_APPEND)
> +    open_flags |= O_RDWR | O_APPEND;
> +  else
> +    open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND);
> +
> +  db[0]= 0;
> +
> +  if ((file= my_open(log_file_name, open_flags,
> +                     MYF(MY_WME | ME_WAITTANG))) < 0 ||
> +      init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
> +                    my_tell(file, MYF(MY_WME)), 0,
> +                    MYF(MY_WME | MY_NABP |
> +                        ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
> +    goto err;
> +
> +  /*
> +    Write header of column names if this is the first time the log
> +    has been opened.
> +  */
> +  if (!headers_written && (log_type == LOG_NORMAL))
> +  {
> +    char *end;
> +
> +    int len=my_snprintf(buff, sizeof(buff), "Columns for this log:\n");
> +    if (history)
> +      end= strnmov(buff + len, "backup_id \tprocess_id \tbinlog_pos "
> +                   "\tbinlog_file \tbackup_state \toperation "
> +                   "\terror_num \tnum_objects \ttotal_bytes "
> +                   "\tvalidity_point_time \tstart_time \tstop_time "
> +                   "\thost_or_server_name \tusername \tbackup_file "
> +                   "\tuser_comment \tcommand \tdrivers\n",
> +                   sizeof(buff) - len);
> +    else
> +      end= strnmov(buff + len, "\nbackup_id \tobject \tstart_time \tstop_time "
> +                   "\ttotal_bytes \tprogress \terror_num \tnotes \tbackup_id "
> +                   "\tobject \tstart_time \tstop_time \ttotal_bytes "
> +                   "\tprogress \terror_num \tnotes\n",
> +                   sizeof(buff) - len);
> +    if (my_b_write(&log_file, (uchar*) buff, (uint) (end-buff)) ||
> +        flush_io_cache(&log_file))
> +      goto err;
> +    headers_written= TRUE;
> +  }
> +
> +  log_state= LOG_OPENED;
> +  DBUG_RETURN(0);
> +
> +err:
> +  sql_print_error("Could not use %s for backup logging (error %d).", name, errno);

Should it be internationalized? Ok if it is not done elsewhere.

> +  if (file >= 0)
> +    my_close(file, MYF(0));
> +  end_io_cache(&log_file);
> +  safeFree(name);
> +  log_state= LOG_CLOSED;
> +  DBUG_RETURN(1);
> +}
> +
> +/**
> +  Write an integer value to the log file.
> +
> +  This method writes the data passed and appends a tab character.
> +
> +  @param[IN]   thd   The current thread
> +  @param[IN]   num   Data to write to log.
> +
> +  @returns TRUE if error.
> +*/
> +bool MYSQL_BACKUP_LOG::write_int(ulonglong num)
> +{
> +  char buff[32];
> +  uint length= 0;
> +
> +  /*
> +    This field is wide to allow ulonglong fields.
> +    We don't want to truncate any large backup id values.
> +  */
> +  length= my_snprintf(buff, 32, "%10lu ", (ulong)num);
> +  if (my_b_write(&log_file, (uchar*) buff, length))
> +    return TRUE;
> +  if (my_b_write(&log_file, (uchar*) "\t", 1))
> +    return TRUE;
> +  return FALSE;
> +}
> +
> +
> +/**
> +  Write a datetime value to the log file.
> +
> +  This method writes the data passed (if not null) and appends a tab character.
> +
> +  @param[IN]   thd       The current thread
> +  @param[IN]   time_val  Data to write to log.
> +
> +  @returns TRUE if error.
> +*/
> +bool MYSQL_BACKUP_LOG::write_datetime(time_t time_val)
> +{
> +  char local_time_buff[MAX_TIME_SIZE];
> +  uint time_buff_len= 0;
> +
> +  if (time_val)
> +  {
> +    MYSQL_TIME time;
> +    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)time_val);
> +
> +    time_buff_len= my_snprintf(local_time_buff, MAX_TIME_SIZE,
> +                               "%02d%02d%02d %2d:%02d:%02d",
> +                               time.year % 100, time.month + 1,
> +                               time.day, time.hour,
> +                               time.minute, time.second);
> +
> +    if (my_b_write(&log_file, (uchar*) local_time_buff, time_buff_len))
> +      return TRUE;
> +    if (my_b_write(&log_file, (uchar*) "\t", 1))
> +      return TRUE;
> +  }
> +  return FALSE;
> +}
> +
> +/**
> +  Write a character string value to the log file.
> +
> +  This method writes the data passed (if not null) and appends a tab character.
> +
> +  @param[IN]   thd       The current thread
> +  @param[IN]   str       Data to write to log.
> +
> +  @returns TRUE if error.
> +*/
> +bool MYSQL_BACKUP_LOG::write_str(const char *str)
> +{
> +  if (str)
> +  {
> +    if (my_b_write(&log_file, (uchar*)str, strlen(str)))
> +      return TRUE;
> +    if (my_b_write(&log_file, (uchar*) "\t", 1))
> +      return TRUE;
> +  }
> +  return FALSE;
> +}
> +
> +/**
> +  Write the backup log entry for the backup history log to a file.
> +
> +  This method creates a new row in the backup history log with the
> +  information provided.
> +
> +  @param[IN]   thd   The current thread
> +  @param[IN]   st_backup_history   Data to write to log.
> +
> +  @returns TRUE if error.
> +*/
> +bool MYSQL_BACKUP_LOG::write(THD *thd, st_backup_history *history_data)
> +{
> +  char *host= current_thd->security_ctx->host; // host name
> +  char *user= current_thd->security_ctx->user; // user name
> +  bool save_time_zone_used;
> +
> +  save_time_zone_used= thd->time_zone_used;
> +
> +  (void) pthread_mutex_lock(&LOCK_log);
> +
> +  /* 
> +    Test if someone closed between the is_open test and lock 
> +  */
> +  if (is_open())
> +  {
> +    /*
> +      Write log data.
> +    */
> +    if (write_int(history_data->backup_id))
> +      goto err;
> +    if (write_int(history_data->process_id))
> +      goto err;
> +    if (write_int(history_data->binlog_pos))
> +      goto err;
> +    if (write_str(history_data->binlog_file))
> +      goto err;
> +    if (write_int(history_data->state))
> +      goto err;
> +    if (write_int(history_data->operation))
> +      goto err;
> +    if (write_int(history_data->error_num))
> +      goto err;
> +    if (write_int(history_data->num_objects))
> +      goto err;
> +    if (write_int(history_data->size))
> +      goto err;
> +    if (write_datetime(history_data->vp_time))
> +      goto err;
> +    if (write_datetime(history_data->start))
> +      goto err;
> +    if (write_datetime(history_data->stop))
> +      goto err;
> +    if (write_str(host))
> +      goto err;
> +    if (write_str(user))
> +      goto err;
> +    if (write_str(history_data->user_comment))
> +      goto err;
> +    if (write_str(history_data->command))
> +      goto err;
> +    if (write_str(history_data->engine_name))
> +      goto err;
> +
> +    if (my_b_write(&log_file, (uchar*) "\n", 1) ||
> +        flush_io_cache(&log_file))
> +      goto err;
> +  }
> +
> +  (void) pthread_mutex_unlock(&LOCK_log);
> +  thd->time_zone_used= save_time_zone_used;
> +  return FALSE;
> +err:
> +
> +  if (!write_error)
> +  {
> +    write_error= 1;
> +    sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
> +  }
> +  (void) pthread_mutex_unlock(&LOCK_log);
> +  thd->time_zone_used= save_time_zone_used;
> +  return TRUE;
> +}
> +

I think it would be possible and nice to use single method for writting to both 
file and table. That way if someone changes the layout of log entry here it 
would be automaticaly reflected in file- and table-based logs. However I don't 
request such change.

An idea how to do this: define methods like write_str() so that they allso 
append the value to the next field of a table record stored un MYSQL_BACKUP_LOG 
instance (an internal field num will be increased by each write_*() method). The 
row will be prepared for writing by a new method e.g., 
MYSQL_BACKUP_LOG::prepare_log_entry() called at the beginning of this method and 
it will send to the table in another method e.g., 
MYSQL_BACKUP_LOG::write_log_entry() called at the end.


> +
> +/**
> +  Write the backup log entry for the backup progress log to a file.
> +
> +  This method creates a new row in the backup progress log with the
> +  information provided.
> +
> +  @param[IN]   thd         The current thread
> +  @param[OUT]  backup_id   The new row id for the backup history
> +  @param[IN]   object      The name of the object processed
> +  @param[IN]   start       Start datetime
> +  @param[IN]   stop        Stop datetime
> +  @param[IN]   size        Size value
> +  @param[IN]   progress    Progress (percent)
> +  @param[IN]   error_num   Error number (should be 0 is success)
> +  @param[IN]   notes       Misc data from engine
> +
> +  @returns TRUE if error.
> +*/
> +bool MYSQL_BACKUP_LOG::write(THD *thd, ulonglong backup_id, const char *object, 
> +                             time_t start, time_t stop, longlong size,
> +                             longlong progress, int error_num, const char *notes)
> +{
> +  bool save_time_zone_used;
> +
> +  save_time_zone_used= thd->time_zone_used;
> +
> +  (void) pthread_mutex_lock(&LOCK_log);
> +
> +  /* 
> +    Test if someone closed between the is_open test and lock 
> +  */
> +  if (is_open())
> +  {
> +    /*
> +      Write log data.
> +    */
> +    if (write_int(backup_id))
> +      goto err;
> +    if (write_str(object))
> +      goto err;
> +    if (write_datetime(start))
> +      goto err;
> +    if (write_datetime(stop))
> +      goto err;
> +    if (write_int(size))
> +      goto err;
> +    if (write_int(progress))
> +      goto err;
> +    if (write_int(error_num))
> +      goto err;
> +    if (write_str(notes))
> +      goto err;
> +
> +    if (my_b_write(&log_file, (uchar*) "\n", 1) ||
> +        flush_io_cache(&log_file))
> +      goto err;
> +  }
> +
> +  (void) pthread_mutex_unlock(&LOCK_log);
> +  thd->time_zone_used= save_time_zone_used;
> +  return FALSE;
> +err:
> +
> +  if (!write_error)
> +  {
> +    write_error= 1;
> +    sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
> +  }
> +  (void) pthread_mutex_unlock(&LOCK_log);
> +  thd->time_zone_used= save_time_zone_used;
> +  return TRUE;
> +}
> +
> +
> +/**
> +  Reopen the log file.
> +
> +  This method opens the log file.
> +
> +  @param[IN] history Process as history log if TRUE else progress log
> +*/
> +void MYSQL_BACKUP_LOG::reopen_file(bool history)
> +{
> +  char *save_name;
> +
> +  DBUG_ENTER("MYSQL_BACKUP_LOG::reopen_file");
> +  if (!is_open())
> +  {
> +    DBUG_PRINT("info",("log is closed"));
> +    DBUG_VOID_RETURN;
> +  }
> +
> +  pthread_mutex_lock(&LOCK_log);
> +
> +  save_name= name;
> +  name= 0;				// Don't free name
> +  close(LOG_CLOSE_TO_BE_OPENED);
> +
> +  /*
> +     Note that at this point, log_state != LOG_CLOSED (important for is_open()).
> +  */
> +
> +  open(save_name, log_type, 0, io_cache_type, history);
> +  my_free(save_name, MYF(0));
> +
> +  pthread_mutex_unlock(&LOCK_log);
> +
> +  DBUG_VOID_RETURN;
> +}
> +
> +
> +/**
>    @todo
>    The following should be using fn_format();  We just need to
>    first change fn_format() to cut the file name if it's too long.
> @@ -4084,6 +5197,58 @@ bool general_log_write(THD *thd, enum en
>      return logger.general_log_write(thd, command, query, query_length);
>  
>    return FALSE;
> +}
> +
> +
> +/**
> +  Write the backup log entry for the backup history logs.
> +
> +  This method is a pass-through to allow calling of the logging 
> +  functions for the backup history log.
> +
> +  @param[IN]   thd          The current thread
> +  @param[IN]   history_data The data for the row
> +  
> +  @returns results of logging function (i.e., TRUE if error)
> +*/
> +bool backup_history_log_write(THD *thd, 
> +                              st_backup_history *history_data)
> +{
> +  /* Write the message to the log if we want to log this king of commands */
> +  return logger.backup_history_log_write(thd, history_data);
> +}
> +
> +/**
> +  Write the backup log entry for the backup progress log.
> +
> +  This method is a pass-through to allow calling of the logging 
> +  functions for the backup history log.
> +
> +  @param[IN]   thd         The current thread
> +  @param[OUT]  backup_id   The new row id for the backup history
> +  @param[IN]   object      The name of the object processed
> +  @param[IN]   start       Start datetime
> +  @param[IN]   stop        Stop datetime
> +  @param[IN]   size        Size value
> +  @param[IN]   progress    Progress (percent)
> +  @param[IN]   error_num   Error number (should be 0 is success)
> +  @param[IN]   notes       Misc data from engine
> +
> +  @returns results of logging function (i.e., TRUE if error)
> +*/
> +bool backup_progress_log_write(THD *thd,
> +                               ulonglong backup_id,
> +                               const char *object,
> +                               time_t start,
> +                               time_t stop,
> +                               longlong size,
> +                               longlong progress,
> +                               int error_num,
> +                               const char *notes)
> +{
> +  /* Write the message to the log if we want to log this king of commands */
> +  return logger.backup_progress_log_write(thd, backup_id, object, start,
> +                                          stop, size, progress, error_num, notes);
>  }
>  
>  void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
> 


> === modified file 'sql/log.h'
> --- a/sql/log.h	2008-02-03 09:00:49 +0000
> +++ b/sql/log.h	2008-06-25 21:29:44 +0000
> @@ -223,6 +223,42 @@ private:
>    time_t last_time;
>  };
>  
> +class MYSQL_BACKUP_LOG: public MYSQL_LOG
> +{
> +public:
> +  MYSQL_BACKUP_LOG () { headers_written= FALSE; }
> +  void reopen_file(bool history);
> +  bool write(THD *thd, st_backup_history *history_data);
> +  bool write(THD *thd, ulonglong backup_id, const char *object, 
> +             time_t start, time_t stop, longlong size,
> +             longlong progress, int error_num, const char *notes);
> +
> +  bool open(const char *log_name,
> +            enum_log_type log_type,
> +            const char *new_name,
> +            enum cache_type io_cache_type_arg,
> +            bool history);
> +
> +  bool open_backup_history_log(const char *log_name)
> +  {
> +    char buf[FN_REFLEN];
> +    return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
> +                WRITE_CACHE, TRUE);
> +  }
> +  bool open_backup_progress_log(const char *log_name)
> +  {
> +    char buf[FN_REFLEN];
> +    return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
> +                WRITE_CACHE, FALSE);
> +  }
> +
> +private:
> +  bool write_int(ulonglong num);
> +  bool write_datetime(time_t time_val);
> +  bool write_str(const char *str);
> +  bool headers_written;
> +};
> +
>  class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
>  {
>   private:
> @@ -411,6 +447,20 @@ public:
>                             const char *command_type, uint command_type_len,
>                             const char *sql_text, uint sql_text_len,
>                             CHARSET_INFO *client_cs)= 0;
> +
> +  virtual bool log_backup_history(THD *thd, 
> +                                  st_backup_history *history_data)= 0;
> +
> +  virtual bool log_backup_progress(THD *thd,
> +                                   ulonglong backup_id,
> +                                   const char *object,
> +                                   time_t start,
> +                                   time_t stop,
> +                                   longlong size,
> +                                   longlong progress,
> +                                   int error_num,
> +                                   const char *notes)= 0;
> +
>    virtual ~Log_event_handler() {}
>  };
>  
> @@ -441,18 +491,36 @@ public:
>                             const char *sql_text, uint sql_text_len,
>                             CHARSET_INFO *client_cs);
>  
> +  virtual bool log_backup_history(THD *thd, 
> +                                  st_backup_history *history_data);
> +
> +  virtual bool log_backup_progress(THD *thd,
> +                                   ulonglong backup_id,
> +                                   const char *object,
> +                                   time_t start,
> +                                   time_t stop,
> +                                   longlong size,
> +                                   longlong progress,
> +                                   int error_num,
> +                                   const char *notes);
> +
>    int activate_log(THD *thd, uint log_type);
> +
>  };
>  
>  
>  /* type of the log table */
>  #define QUERY_LOG_SLOW 1
>  #define QUERY_LOG_GENERAL 2
> +#define BACKUP_HISTORY_LOG 3
> +#define BACKUP_PROGRESS_LOG 4
>  
>  class Log_to_file_event_handler: public Log_event_handler
>  {
>    MYSQL_QUERY_LOG mysql_log;
>    MYSQL_QUERY_LOG mysql_slow_log;
> +  MYSQL_BACKUP_LOG mysql_backup_history_log;
> +  MYSQL_BACKUP_LOG mysql_backup_progress_log;
>    bool is_initialized;
>  public:
>    Log_to_file_event_handler(): is_initialized(FALSE)
> @@ -472,14 +540,36 @@ public:
>                             const char *command_type, uint command_type_len,
>                             const char *sql_text, uint sql_text_len,
>                             CHARSET_INFO *client_cs);
> +
> +  virtual bool log_backup_history(THD *thd, 
> +                                   st_backup_history *history_data);
> +
> +  virtual bool log_backup_progress(THD *thd,
> +                                   ulonglong backup_id,
> +                                   const char *object,
> +                                   time_t start,
> +                                   time_t stop,
> +                                   longlong size,
> +                                   longlong progress,
> +                                   int error_num,
> +                                   const char *notes);
> +
>    void flush();
> +  void flush_backup_logs();
>    void init_pthread_objects();
>    MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; }
>    MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; }
> +  MYSQL_BACKUP_LOG *get_backup_history_log()
> +  { return &mysql_backup_history_log; }
> +  MYSQL_BACKUP_LOG *get_backup_progress_log() 
> +  { return &mysql_backup_progress_log; }
>  };
>  
>  
> -/* Class which manages slow, general and error log event handlers */
> +/*
> +   Class which manages slow, general, error log, backup history, and
> +   backup progress event handlers.
> +*/
>  class LOGGER
>  {
>    rw_lock_t LOCK_logger;
> @@ -494,6 +584,8 @@ class LOGGER
>    Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
>    Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
>    Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
> +  Log_event_handler *backup_history_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
> +  Log_event_handler *backup_progress_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
>  
>  public:
>  
> @@ -517,6 +609,7 @@ public:
>    void init_base();
>    void init_log_tables();
>    bool flush_logs(THD *thd);
> +  bool flush_backup_logs(THD *thd);
>    /* Perform basic logger cleanup. this will leave e.g. error log open. */
>    void cleanup_base();
>    /* Free memory. Nothing could be logged after this function is called */
> @@ -530,13 +623,30 @@ public:
>    bool general_log_write(THD *thd, enum enum_server_command command,
>                           const char *query, uint query_length);
>  
> +  bool backup_history_log_write(THD *thd, 
> +                                st_backup_history *history_data);
> +
> +  bool backup_progress_log_write(THD *thd,
> +                                 ulonglong backup_id,
> +                                 const char *object,
> +                                 time_t start,
> +                                 time_t stop,
> +                                 longlong size,
> +                                 longlong progress,
> +                                 int error_num,
> +                                 const char *notes);
> +
>    /* we use this function to setup all enabled log event handlers */
>    int set_handlers(uint error_log_printer,
>                     uint slow_log_printer,
>                     uint general_log_printer);
> +  int set_backup_handlers(uint backup_history_log_printer,
> +                          uint backup_progress_log_printer);
>    void init_error_log(uint error_log_printer);
>    void init_slow_log(uint slow_log_printer);
>    void init_general_log(uint general_log_printer);
> +  void init_backup_history_log(uint backup_history_log_printer);
> +  void init_backup_progress_log(uint backup_progress_log_printer);
>    void deactivate_log_handler(THD* thd, uint log_type);
>    bool activate_log_handler(THD* thd, uint log_type);
>    MYSQL_QUERY_LOG *get_slow_log_file_handler()
> @@ -549,6 +659,18 @@ public:
>    { 
>      if (file_log_handler)
>        return file_log_handler->get_mysql_log();
> +    return NULL;
> +  }
> +  MYSQL_BACKUP_LOG *get_backup_history_log_file_handler()
> +  { 
> +    if (file_log_handler)
> +      return file_log_handler->get_backup_history_log();
> +    return NULL;
> +  }
> +  MYSQL_BACKUP_LOG *get_backup_progress_log_file_handler()
> +  { 
> +    if (file_log_handler)
> +      return file_log_handler->get_backup_progress_log();
>      return NULL;
>    }
>  };
> 


> === modified file 'sql/mysql_priv.h'
> --- a/sql/mysql_priv.h	2008-05-27 19:47:15 +0000
> +++ b/sql/mysql_priv.h	2008-06-25 21:29:44 +0000
> @@ -901,6 +901,111 @@ int end_trans(THD *thd, enum enum_mysql_
>  Item *negate_expression(THD *thd, Item *expr);
>  
>  /* log.cc */
> +
> +/**
> +  List of fields for online backup table.
> +*/
> +enum enum_backup_history_table_field
> +{
> +  ET_OBH_FIELD_BACKUP_ID = 0, /* start from 0 to correspond with field array */
> +  ET_OBH_FIELD_PROCESS_ID,
> +  ET_OBH_FIELD_BINLOG_POS,
> +  ET_OBH_FIELD_BINLOG_FILE,
> +  ET_OBH_FIELD_BACKUP_STATE,
> +  ET_OBH_FIELD_OPER,
> +  ET_OBH_FIELD_ERROR_NUM,
> +  ET_OBH_FIELD_NUM_OBJ,
> +  ET_OBH_FIELD_TOTAL_BYTES,
> +  ET_OBH_FIELD_VP,
> +  ET_OBH_FIELD_START_TIME,
> +  ET_OBH_FIELD_STOP_TIME,
> +  ET_OBH_FIELD_HOST_OR_SERVER,
> +  ET_OBH_FIELD_USERNAME,
> +  ET_OBH_FIELD_BACKUP_FILE,
> +  ET_OBH_FIELD_COMMENT,
> +  ET_OBH_FIELD_COMMAND,
> +  ET_OBH_FIELD_DRIVERS,
> +  ET_OBH_FIELD_COUNT /* a cool trick to count the number of fields :) */
> +};
> +
> +/**
> +  List of fields for online backup progress table.
> +*/
> +enum enum_backup_progress_table_field
> +{
> +  ET_OBP_FIELD_BACKUP_ID_FK = 0, /* start from 0 to correspond with field array */
> +  ET_OBP_FIELD_PROG_OBJECT,
> +  ET_OBP_FIELD_PROG_START_TIME,
> +  ET_OBP_FIELD_PROG_STOP_TIME,
> +  ET_OBP_FIELD_PROG_SIZE,
> +  ET_OBP_FIELD_PROGRESS,
> +  ET_OBP_FIELD_PROG_ERROR_NUM,
> +  ET_OBP_FIELD_PROG_NOTES,
> +  ET_OBP_FIELD_PROG_COUNT /* a cool trick to count the number of fields :) */
> +};
> +

I don't see why you export these enums in mysql_priv.h. It is not done for any 
other IS tables. I managed to compile the server with these enums defined only 
in log.cc. If some other code needs to know about them, I suggest to define them 
in log.h instead.

> +/**
> +  List of states for online backup table.
> +*/
> +enum enum_backup_state
> +{
> +  BUP_UNKNOWN = 0,
> +  BUP_COMPLETE,
> +  BUP_STARTING,
> +  BUP_VALIDITY_POINT,
> +  BUP_RUNNING,
> +  BUP_ERRORS,
> +  BUP_CANCEL
> +};
> +
> +/**
> +  List of operations for online backup table.
> +*/
> +enum enum_backup_operation
> +{
> +  OP_BACKUP = 1,
> +  OP_RESTORE,
> +  OP_SHOW,
> +  OP_OTHER
> +};
> +
> +/**
> +  Structure for holding backup history data.
> +*/
> +struct st_backup_history
> +{
> +  ulonglong backup_id;             ///< the id for this row in the log
> +	int process_id;                  ///< the process id of the backup/restore
> +	enum_backup_state state;         ///< current state of the operaiont
> +	enum_backup_operation operation; ///< the type of operation (backup, restore)
> +	int error_num;                   ///< error number
> +	char *user_comment;              ///< user comment from command
> +	char *backup_file;               ///< the backup image file
> +	char *command;                   ///< the command used
> +  int binlog_pos;                  ///< position in the binary log
> +  char *binlog_file;               ///< the name of the binary log file
> +  int num_objects;                 ///< number of objects in backup
> +  longlong size;                   ///< total size of the backup image file
> +  time_t start;                    ///< start time of operation
> +	time_t stop;                     ///< stop time of operation
> +  time_t vp_time;                  ///< point in time validation was assured
> +  char *engine_name;               ///< list of backup engines used
> +};
> +
> +
> +bool backup_history_log_write(THD *thd, 
> +                              st_backup_history *history_data);
> +
> +bool backup_progress_log_write(THD *thd,
> +                               ulonglong backup_id,
> +                               const char *object,
> +                               time_t start,
> +                               time_t stop,
> +                               longlong size,
> +                               longlong progress,
> +                               int error_num,
> +                               const char *notes);
> +

This is the API for the backup logging service. We try to collect such APIs in 
the si_objects.h file. Perhaps another header like si_other.h would be 
appropriate. But burrying these daclarations in mysql_priv.h is not a good idea.

(Note: eventually we'd like to separate backup tree from the server tree. One of 
the main tasks will be to remove #include "../mysql_priv.h" from backup sources 
and this fragment of your patch won't make it easier...)

>  int vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
>  void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
>  void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
> @@ -1461,6 +1566,9 @@ extern LEX_STRING INFORMATION_SCHEMA_NAM
>  extern LEX_STRING MYSQL_SCHEMA_NAME;
>  extern LEX_STRING GENERAL_LOG_NAME;
>  extern LEX_STRING SLOW_LOG_NAME;
> +extern LEX_STRING BACKUP_HISTORY_LOG_NAME;
> +extern LEX_STRING BACKUP_PROGRESS_LOG_NAME;
> +extern LEX_STRING BACKUP_SETTINGS_NAME;
>  
>  extern const LEX_STRING partition_keywords[];
>  ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name);
> @@ -1659,6 +1767,8 @@ void remove_db_from_cache(const char *db
>  void flush_tables();
>  bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
>  char *make_default_log_name(char *buff,const char* log_ext);
> +char *make_backup_log_name(char *buff, const char *name, const char* log_ext);
> +char *make_default_backupdir(char *buff);
>  
>  #ifdef WITH_PARTITION_STORAGE_ENGINE
>  uint fast_alter_partition_table(THD *thd, TABLE *table,
> @@ -2045,7 +2155,10 @@ extern bool mysqld_embedded;
>  extern bool using_update_log, opt_large_files, server_id_supplied;
>  extern bool opt_update_log, opt_bin_log, opt_error_log;
>  extern my_bool opt_log, opt_slow_log;
> +extern my_bool opt_backup_history_log;
> +extern my_bool opt_backup_progress_log;
>  extern ulong log_output_options;
> +extern ulong log_backup_output_options;
>  extern my_bool opt_log_queries_not_using_indexes;
>  extern bool opt_disable_networking, opt_skip_show_db;
>  extern my_bool opt_character_set_client_handshake;
> @@ -2074,11 +2187,15 @@ extern uint opt_large_page_size;
>  #endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */
>  #ifdef MYSQL_SERVER
>  extern char *opt_logname, *opt_slow_logname;
> +extern char *opt_backup_history_logname, *opt_backup_progress_logname,
> +            *opt_backup_settings_name;
>  extern const char *log_output_str;
> +extern const char *log_backup_output_str;
>  
>  extern MYSQL_BIN_LOG mysql_bin_log;
>  extern LOGGER logger;
> -extern TABLE_LIST general_log, slow_log;
> +extern TABLE_LIST general_log, slow_log, 
> +       backup_history_log, backup_progress_log;
>  extern FILE *bootstrap_file;
>  extern int bootstrap_error;
>  extern FILE *stderror_file;
> 


> === modified file 'sql/mysqld.cc'
> --- a/sql/mysqld.cc	2008-06-04 13:20:03 +0000
> +++ b/sql/mysqld.cc	2008-06-25 21:29:44 +0000
> @@ -427,7 +427,10 @@ static pthread_cond_t COND_thread_cache,
>  extern DDL_blocker_class *DDL_blocker;
>  bool opt_update_log, opt_bin_log;
>  my_bool opt_log, opt_slow_log;
> +my_bool opt_backup_history_log;
> +my_bool opt_backup_progress_log;
>  ulong log_output_options;
> +ulong log_backup_output_options;
>  my_bool opt_log_queries_not_using_indexes= 0;
>  bool opt_error_log= IF_WIN(1,0);
>  bool opt_disable_networking=0, opt_skip_show_db=0;
> @@ -569,6 +572,7 @@ ulong slow_launch_threads = 0, sync_binl
>  ulong expire_logs_days = 0;
>  ulong rpl_recovery_rank=0;
>  const char *log_output_str= "FILE";
> +const char *log_backup_output_str= "TABLE";
>  
>  const double log_10[] = {
>    1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
> @@ -713,6 +717,8 @@ char *master_info_file;
>  char *relay_log_info_file, *report_user, *report_password, *report_host;
>  char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
>  char *opt_logname, *opt_slow_logname;
> +char *opt_backup_history_logname, *opt_backup_progress_logname,
> +     *opt_backup_settings_name;
>  
>  /* Static variables */
>  
> @@ -1361,6 +1367,9 @@ void clean_up(bool print_message)
>    my_free(sys_init_connect.value, MYF(MY_ALLOW_ZERO_PTR));
>    my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR));
>    my_free(sys_var_general_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
> +  my_free(sys_var_backup_history_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
> +  my_free(sys_var_backup_progress_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
> +  my_free(sys_var_backupdir.value, MYF(MY_ALLOW_ZERO_PTR));
>    my_free(sys_var_slow_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
>    free_tmpdir(&mysql_tmpdir_list);
>  #ifdef HAVE_REPLICATION
> @@ -2866,6 +2875,8 @@ pthread_handler_t signal_hand(void *arg 
>        /* switch to the old log message processing */
>        logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
>                            opt_log ? LOG_FILE:LOG_NONE);
> +      logger.set_backup_handlers(opt_backup_history_log ? LOG_FILE : LOG_NONE,
> +                                 opt_backup_progress_log ? LOG_FILE : LOG_NONE);
>        DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
>        if (!abort_loop)
>        {
> @@ -2883,6 +2894,7 @@ pthread_handler_t signal_hand(void *arg 
>        }
>        break;
>      case SIGHUP:
> +    {
>        if (!abort_loop)
>        {
>          bool not_used;
> @@ -2906,7 +2918,14 @@ pthread_handler_t signal_hand(void *arg 
>                              opt_slow_log ? log_output_options : LOG_NONE,
>                              opt_log ? log_output_options : LOG_NONE);
>        }
> +      if (log_backup_output_options & LOG_NONE)
> +        logger.set_backup_handlers(LOG_NONE, LOG_NONE);
> +      else
> +        logger.set_backup_handlers(
> +          opt_backup_history_log ? log_backup_output_options : LOG_NONE,
> +          opt_backup_progress_log ? log_backup_output_options : LOG_NONE);
>        break;
> +    }
>  #ifdef USE_ONE_SIGNAL_HAND
>      case THR_SERVER_ALARM:
>        process_alarm(sig);			// Trigger alarms.
> @@ -3543,10 +3562,35 @@ static int init_common_variables(const c
>                        "--log-slow-queries option, log tables are used. "
>                        "To enable logging to files use the --log-output=file
> option.");
>  
> +  if (opt_backup_history_log && opt_backup_history_logname
> +     && !(log_backup_output_options & LOG_FILE) &&
> !(log_backup_output_options & LOG_NONE))
> +    sql_print_warning("Although a path was specified for the "
> +                      "--log-backup-history option, log tables are used. "
> +                      "To enable logging to files use the --log-backup-output
> option.");
> +
> +  if (opt_backup_progress_log && opt_backup_progress_logname
> +     && !(log_backup_output_options & LOG_FILE) &&
> !(log_backup_output_options & LOG_NONE))
> +    sql_print_warning("Although a path was specified for the "
> +                      "--log-backup-progress option, log tables are used. "
> +                      "To enable logging to files use the --log-backup-output
> option.");
> +
>    s= opt_logname ? opt_logname : make_default_log_name(buff, ".log");
>    sys_var_general_log_path.value= my_strdup(s, MYF(0));
>    sys_var_general_log_path.value_length= strlen(s);
>  
> +  /*
> +    Set defaults for history and progress log paths.
> +  */
> +  s= opt_backup_history_logname ? opt_backup_history_logname : 
> +    make_backup_log_name(buff, BACKUP_HISTORY_LOG_NAME.str, ".log");
> +  sys_var_backup_history_log_path.value= my_strdup(s, MYF(0));
> +  sys_var_backup_history_log_path.value_length= BACKUP_HISTORY_LOG_NAME.length;
> +
> +  s= opt_backup_progress_logname ? opt_backup_progress_logname : 
> +    make_backup_log_name(buff, BACKUP_PROGRESS_LOG_NAME.str, ".log");
> +  sys_var_backup_progress_log_path.value= my_strdup(s, MYF(0));
> +  sys_var_backup_progress_log_path.value_length= BACKUP_PROGRESS_LOG_NAME.length;
> +
>    s= opt_slow_logname ? opt_slow_logname : make_default_log_name(buff,
> "-slow.log");
>    sys_var_slow_log_path.value= my_strdup(s, MYF(0));
>    sys_var_slow_log_path.value_length= strlen(s);
> @@ -4062,7 +4106,10 @@ server.");
>  
>  #ifdef WITH_CSV_STORAGE_ENGINE
>    if (opt_bootstrap)
> +  {
>      log_output_options= LOG_FILE;
> +    log_backup_output_options= LOG_FILE;
> +  }
>    else
>      logger.init_log_tables();
>  
> @@ -4094,9 +4141,41 @@ server.");
>      logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
>                          opt_log ? log_output_options:LOG_NONE);
>    }
> +
> +  if (log_backup_output_options & LOG_NONE)
> +  {
> +    /*
> +      Issue a warining if there were specified additional options to the
> +      log-backup-output along with NONE. Probably this wasn't what user wanted.
> +    */
> +    if ((log_backup_output_options & LOG_NONE) && 
> +        (log_backup_output_options & ~LOG_NONE))
> +      sql_print_warning("There were other values specified to "
> +                        "log-backup-output besides NONE. Disabling "
> +                        "backup logs anyway.");
> +    logger.set_backup_handlers(LOG_NONE, LOG_NONE);
> +  }
> +  else
> +  {
> +    /* fall back to the log files if tables are not present */
> +    LEX_STRING csv_name={C_STRING_WITH_LEN("csv")};
> +    if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
> +    {
> +      /* purecov: begin inspected */
> +      sql_print_error("CSV engine is not present, falling back to the "
> +                      "log files");
> +      log_backup_output_options= 
> +        (log_backup_output_options & ~LOG_TABLE) | LOG_FILE;
> +      /* purecov: end */
> +    }
> +
> +    logger.set_backup_handlers(log_backup_output_options,
> +      log_backup_output_options);
> +  }
>  #else
>    logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
>                        opt_log ? LOG_FILE:LOG_NONE);
> +  logger.set_backup_handlers(LOG_FILE, LOG_FILE);
>  #endif
>  
>    /*
> @@ -5688,10 +5767,13 @@ enum options_mysqld
>    OPT_PLUGIN_LOAD,
>    OPT_PLUGIN_DIR,
>    OPT_LOG_OUTPUT,
> +  OPT_LOG_BACKUP_OUTPUT,
>    OPT_PORT_OPEN_TIMEOUT,
>    OPT_PROFILING,
>    OPT_KEEP_FILES_ON_CREATE,
>    OPT_GENERAL_LOG,
> +  OPT_BACKUP_HISTORY_LOG,
> +  OPT_BACKUP_PROGRESS_LOG,
>    OPT_SLOW_LOG,
>    OPT_THREAD_HANDLING,
>    OPT_INNODB_ROLLBACK_ON_TIMEOUT,
> @@ -5745,6 +5827,14 @@ struct my_option my_long_options[] =
>     "Creating and dropping stored procedures alters ACLs. Disable with
> --skip-automatic-sp-privileges.",
>     (uchar**) &sp_automatic_privileges, (uchar**) &sp_automatic_privileges,
>     0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
> +  {"backupdir", 'B', "Path used to store backup data.", (uchar**)
> &sys_var_backupdir.value,
> +   (uchar**) &sys_var_backupdir.value, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0,
> 0},
> +  {"backup-history-log", OPT_BACKUP_HISTORY_LOG,
> +   "Enable|disable backup history log", (uchar**) &opt_backup_history_log,
> +   (uchar**) &opt_backup_history_log, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
> +  {"backup-progress-log", OPT_BACKUP_PROGRESS_LOG,
> +   "Enable|disable backup progress log", (uchar**) &opt_backup_progress_log,
> +   (uchar**) &opt_backup_progress_log, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
>    {"basedir", 'b',
>     "Path to installation directory. All paths are usually resolved relative to
> this.",
>     (uchar**) &mysql_home_ptr, (uchar**) &mysql_home_ptr, 0, GET_STR,
> REQUIRED_ARG,
> @@ -5990,6 +6080,11 @@ Disable with --skip-large-pages.",
>     "FILE or NONE.",
>     (uchar**) &log_output_str, (uchar**) &log_output_str, 0,
>     GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
> +  {"log-backup-output", OPT_LOG_BACKUP_OUTPUT,
> +   "Syntax: log-backup-output[=value[,value...]], where \"value\" could be TABLE, "
> +   "FILE or NONE.",
> +   (uchar**) &log_backup_output_str, (uchar**) &log_backup_output_str, 0,
> +   GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
>  #endif
>    {"log-queries-not-using-indexes", OPT_LOG_QUERIES_NOT_USING_INDEXES,
>     "Log queries that are executed without benefit of any index to the slow log if it
> is open.",
> @@ -7609,6 +7704,7 @@ static void mysql_init_variables(void)
>    opt_log= opt_slow_log= 0;
>    opt_update_log= 0;
>    log_output_options= find_bit_type(log_output_str, &log_output_typelib);
> +  log_backup_output_options= find_bit_type(log_backup_output_str,
> &log_output_typelib);
>    opt_bin_log= 0;
>    opt_disable_networking= opt_skip_show_db=0;
>    opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
> @@ -7695,6 +7791,8 @@ static void mysql_init_variables(void)
>    mysql_data_home_buff[1]=0;
>    mysql_data_home_len= 2;
>  
> +  strmake(language, LANGUAGE, sizeof(language)-1);
> + 
>    /* Replication parameters */
>    master_info_file= (char*) "master.info",
>      relay_log_info_file= (char*) "relay-log.info";
> @@ -7853,6 +7951,10 @@ mysqld_get_one_option(int optid,
>    case 'l':
>      opt_log=1;
>      break;
> +  case 'B':
> +    strcpy(sys_var_backupdir.value, argument);
> +    sys_var_backupdir.value_length= strlen(sys_var_backupdir.value);
> +    break;
>    case 'h':
>      strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
>      /* Correct pointer set by my_getopt (for embedded library) */
> @@ -8034,6 +8136,21 @@ mysqld_get_one_option(int optid,
>      {
>        log_output_str= argument;
>        log_output_options=
> +        find_bit_type_or_exit(argument, &log_output_typelib, opt->name);
> +  }
> +    break;
> +  }
> +  case  OPT_LOG_BACKUP_OUTPUT:
> +  {
> +    if (!argument || !argument[0])
> +    {
> +      log_backup_output_options= LOG_FILE;
> +      log_backup_output_str= log_output_typelib.type_names[1];
> +    }
> +    else
> +    {
> +      log_backup_output_str= argument;
> +      log_backup_output_options=
>          find_bit_type_or_exit(argument, &log_output_typelib, opt->name);
>    }
>      break;
> 


> === modified file 'sql/set_var.cc'
> --- a/sql/set_var.cc	2008-05-27 19:47:15 +0000
> +++ b/sql/set_var.cc	2008-06-25 21:29:44 +0000
> @@ -147,8 +147,15 @@ static uchar *get_tmpdir(THD *thd);
>  static int  sys_check_log_path(THD *thd,  set_var *var);
>  static bool sys_update_general_log_path(THD *thd, set_var * var);
>  static void sys_default_general_log_path(THD *thd, enum_var_type type);
> +static bool sys_update_backup_history_log_path(THD *thd, set_var * var);
> +static void sys_default_backup_history_log_path(THD *thd, enum_var_type type);
> +static bool sys_update_backup_progress_log_path(THD *thd, set_var * var);
> +static void sys_default_backup_progress_log_path(THD *thd, enum_var_type type);
>  static bool sys_update_slow_log_path(THD *thd, set_var * var);
>  static void sys_default_slow_log_path(THD *thd, enum_var_type type);
> +static int sys_check_backupdir(THD *thd, set_var *var);
> +static bool sys_update_backupdir(THD *thd, set_var * var);
> +static void sys_default_backupdir(THD *thd, enum_var_type type);
>  
>  /*
>    Variable definition list
> @@ -760,6 +767,12 @@ static sys_var_const_str	sys_license(&va
>  /* Global variables which enable|disable logging */
>  static sys_var_log_state sys_var_general_log(&vars, "general_log",
> &opt_log,
>                                        QUERY_LOG_GENERAL);
> +static sys_var_log_state sys_var_backup_history_log(&vars, "backup_history_log",
> 
> +                                                    &opt_backup_history_log,
> +                                                    BACKUP_HISTORY_LOG);
> +static sys_var_log_state sys_var_backup_progress_log(&vars,
> "backup_progress_log",
> +                                                     &opt_backup_progress_log,
> +                                                     BACKUP_PROGRESS_LOG);
>  /* Synonym of "general_log" for consistency with SHOW VARIABLES output */
>  static sys_var_log_state sys_var_log(&vars, "log", &opt_log,
>                                        QUERY_LOG_GENERAL);
> @@ -772,12 +785,39 @@ sys_var_str sys_var_general_log_path(&va
>  				     sys_update_general_log_path,
>  				     sys_default_general_log_path,
>  				     opt_logname);
> +/*
> +  Added new variables for backup log file paths.
> +*/
> +sys_var_str sys_var_backup_history_log_path(&vars, "backup_history_log_file", 
> +             sys_check_log_path,
> +				     sys_update_backup_history_log_path,
> +				     sys_default_backup_history_log_path,
> +				     opt_logname);
> +sys_var_str sys_var_backup_progress_log_path(&vars, "backup_progress_log_file",
> 
> +             sys_check_log_path,
> +				     sys_update_backup_progress_log_path,
> +				     sys_default_backup_progress_log_path,
> +				     opt_logname);
> +/*
> +  Create the backupdir dynamic variable.
> +*/
> +sys_var_str sys_var_backupdir(&vars, "backupdir",
> +                              sys_check_backupdir,
> +                              sys_update_backupdir,
> +                              sys_default_backupdir,
> +                               0);
> +
>  sys_var_str sys_var_slow_log_path(&vars, "slow_query_log_file",
> sys_check_log_path,
>  				  sys_update_slow_log_path, 
>  				  sys_default_slow_log_path,
>  				  opt_slow_logname);
>  static sys_var_log_output sys_var_log_output_state(&vars, "log_output",
> &log_output_options,
>  					    &log_output_typelib, 0);
> +/*
> +  Defines variable for specifying the backup log output.
> +*/
> +static sys_var_log_backup_output sys_var_log_backup_output_state(&vars,
> "log_backup_output",
> +              &log_backup_output_options, &log_output_typelib, 0);
>  
>  
>  /*
> @@ -2411,7 +2451,6 @@ void sys_var_log_state::set_default(THD 
>    pthread_mutex_unlock(&LOCK_global_system_variables);
>  }
>  
> -
>  static int  sys_check_log_path(THD *thd,  set_var *var)
>  {
>    char path[FN_REFLEN], buff[FN_REFLEN];
> @@ -2477,11 +2516,15 @@ bool update_sys_var_str_path(THD *thd, s
>  			     bool log_state, uint log_type)
>  {
>    MYSQL_QUERY_LOG *file_log;
> +  MYSQL_BACKUP_LOG *backup_log;
>    char buff[FN_REFLEN];
>    char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
>    bool result= 0;
>    uint str_length= (var ? var->value->str_value.length() : 0);
>  
> +  /*
> +    Added support for backup log types.
> +  */
>    switch (log_type) {
>    case QUERY_LOG_SLOW:
>      file_log= logger.get_slow_log_file_handler();
> @@ -2489,6 +2532,15 @@ bool update_sys_var_str_path(THD *thd, s
>    case QUERY_LOG_GENERAL:
>      file_log= logger.get_log_file_handler();
>      break;
> +  /* 
> +    Check the backup logs to update their paths.
> +  */
> +  case BACKUP_HISTORY_LOG:
> +    backup_log= logger.get_backup_history_log_file_handler();
> +    break;
> +  case BACKUP_PROGRESS_LOG:
> +    backup_log= logger.get_backup_progress_log_file_handler();
> +    break;
>    default:
>      assert(0);                                  // Impossible
>    }
> @@ -2515,6 +2567,9 @@ bool update_sys_var_str_path(THD *thd, s
>    my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
>    if (file_log && log_state)
>    {
> +    /*
> +      Added support for backup log types.
> +    */
>      switch (log_type) {
>      case QUERY_LOG_SLOW:
>        file_log->open_slow_log(sys_var_slow_log_path.value);
> @@ -2522,6 +2577,15 @@ bool update_sys_var_str_path(THD *thd, s
>      case QUERY_LOG_GENERAL:
>        file_log->open_query_log(sys_var_general_log_path.value);
>        break;
> +    /*
> +      Open the backup logs if specified.
> +    */
> +    case BACKUP_HISTORY_LOG:
> +     
> backup_log->open_backup_history_log(sys_var_backup_history_log_path.value);
> +      break;
> +    case BACKUP_PROGRESS_LOG:
> +     
> backup_log->open_backup_progress_log(sys_var_backup_progress_log_path.value);
> +      break;
>      default:
>        DBUG_ASSERT(0);
>      }
> @@ -2549,6 +2613,43 @@ static void sys_default_general_log_path
>  }
>  
>  
> +/*
> +  Update the backup history log path variable.
> +*/
> +static bool sys_update_backup_history_log_path(THD *thd, set_var * var)
> +{
> +  return update_sys_var_str_path(thd, &sys_var_backup_history_log_path, 
> +				 var, ".log", opt_log, BACKUP_HISTORY_LOG);
> +}
> +
> +/*
> +  Set the default for backup history log path variable.
> +*/
> +static void sys_default_backup_history_log_path(THD *thd, enum_var_type type)
> +{
> +  (void) update_sys_var_str_path(thd, &sys_var_backup_history_log_path,
> +				 0, ".log", opt_log, BACKUP_HISTORY_LOG);
> +}
> +
> +/*
> +  Update the backup progress log path variable.
> +*/
> +static bool sys_update_backup_progress_log_path(THD *thd, set_var * var)
> +{
> +  return update_sys_var_str_path(thd, &sys_var_backup_progress_log_path, 
> +				 var, ".log", opt_log, BACKUP_PROGRESS_LOG);
> +}
> +
> +/*
> +  Set the default for backup progress log path variable.
> +*/
> +static void sys_default_backup_progress_log_path(THD *thd, enum_var_type type)
> +{
> +  (void) update_sys_var_str_path(thd, &sys_var_backup_progress_log_path,
> +				 0, ".log", opt_log, BACKUP_PROGRESS_LOG);
> +}
> +
> +
>  static bool sys_update_slow_log_path(THD *thd, set_var * var)
>  {
>    return update_sys_var_str_path(thd, &sys_var_slow_log_path,
> @@ -2565,6 +2666,81 @@ static void sys_default_slow_log_path(TH
>  }
>  
>  
> +static int sys_check_backupdir(THD *thd, set_var *var)
> +{
> +  char path[FN_REFLEN], buff[FN_REFLEN];
> +  MY_STAT f_stat;
> +  String str(buff, sizeof(buff), system_charset_info), *res;
> +  const char *log_file_str;
> +  size_t path_length;
> +
> +  if (!(res= var->value->val_str(&str)))
> +    goto err;
> +
> +  log_file_str= res->c_ptr();
> +  bzero(&f_stat, sizeof(MY_STAT));
> +
> +  /* Get dirname of the file path. */
> +  (void) dirname_part(path, log_file_str, &path_length);
> +
> +  /* Dirname is empty if file path is relative. */
> +  if (!path_length)
> +    return 0;
> +
> +  /*
> +    Check if directory exists and we have permission to create file and
> +    write to file.
> +  */
> +  if (my_access(path, (F_OK|W_OK)))
> +    goto err;
> +
> +  return 0;
> +
> +err:
> +  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, 
> +           res ? log_file_str : "NULL");
> +  return 1;
> +}
> +
> +
> +static bool sys_update_backupdir(THD *thd, set_var * var)
> +{
> +  char buff[FN_REFLEN];
> +  char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
> +  bool result= 0;
> +  uint str_length= (var ? var->value->str_value.length() : 0);
> +
> +  if (!old_value)
> +  {
> +    old_value= make_default_backupdir(buff);
> +    str_length= strlen(old_value);
> +  }
> +  if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME))))
> +  {
> +    result= 1;
> +    goto err;
> +  }
> +
> +  pthread_mutex_lock(&LOCK_global_system_variables);
> +  logger.lock_exclusive();
> +
> +  old_value= sys_var_backupdir.value;
> +  sys_var_backupdir.value= res;
> +  sys_var_backupdir.value_length= str_length;
> +  my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
> +  logger.unlock();
> +  pthread_mutex_unlock(&LOCK_global_system_variables);
> +
> +err:
> +  return result;
> +}
> +
> +static void sys_default_backupdir(THD *thd, enum_var_type type)
> +{
> +  sys_update_backupdir(thd, 0);
> +}
> +
> +
>  bool sys_var_log_output::update(THD *thd, set_var *var)
>  {
>    pthread_mutex_lock(&LOCK_global_system_variables);
> @@ -2592,6 +2768,62 @@ void sys_var_log_output::set_default(THD
>  
>  uchar *sys_var_log_output::value_ptr(THD *thd, enum_var_type type,
>                                      LEX_STRING *base)
> +{
> +  char buff[256];
> +  String tmp(buff, sizeof(buff), &my_charset_latin1);
> +  ulong length;
> +  ulong val= *value;
> +
> +  tmp.length(0);
> +  for (uint i= 0; val; val>>= 1, i++)
> +  {
> +    if (val & 1)
> +    {
> +      tmp.append(log_output_typelib.type_names[i],
> +                 log_output_typelib.type_lengths[i]);
> +      tmp.append(',');
> +    }
> +  }
> +
> +  if ((length= tmp.length()))
> +    length--;
> +  return (uchar*) thd->strmake(tmp.ptr(), length);
> +}
> +
> +/*
> +  Allow update of the log-backup-output variable.
> +*/
> +bool sys_var_log_backup_output::update(THD *thd, set_var *var)
> +{
> +  pthread_mutex_lock(&LOCK_global_system_variables);
> +  logger.lock_exclusive();
> +  logger.init_backup_history_log(var->save_result.ulong_value);
> +  logger.init_backup_progress_log(var->save_result.ulong_value);
> +  *value= var->save_result.ulong_value;
> +  logger.unlock();
> +  pthread_mutex_unlock(&LOCK_global_system_variables);
> +  return 0;
> +}
> +
> +/*
> +  Set the default for the log-backup-output variable.
> +*/
> +void sys_var_log_backup_output::set_default(THD *thd, enum_var_type type)
> +{
> +  pthread_mutex_lock(&LOCK_global_system_variables);
> +  logger.lock_exclusive();
> +  logger.init_backup_history_log(LOG_TABLE);
> +  logger.init_backup_progress_log(LOG_TABLE);
> +  *value= LOG_TABLE;
> +  logger.unlock();
> +  pthread_mutex_unlock(&LOCK_global_system_variables);
> +}
> +
> +/*
> +  Allow reading of the log-backup-output variable.
> +*/
> +uchar *sys_var_log_backup_output::value_ptr(THD *thd, enum_var_type type,
> +                                            LEX_STRING *base)
>  {
>    char buff[256];
>    String tmp(buff, sizeof(buff), &my_charset_latin1);
> 

The same as in sys_var_log_output - should be inherited together with other 
methods which are the same (see below).

> === modified file 'sql/set_var.h'
> --- a/sql/set_var.h	2008-05-27 19:47:15 +0000
> +++ b/sql/set_var.h	2008-06-25 21:29:44 +0000
> @@ -935,6 +935,32 @@ public:
>    SHOW_TYPE show_type() { return SHOW_CHAR; }
>  };
>  
> +/*
> +  Class used to manage log-backup-output variable.
> +*/
> +class sys_var_log_backup_output : public sys_var
> +{
> +  ulong *value;
> +  TYPELIB *enum_names;
> +public:
> +  sys_var_log_backup_output(sys_var_chain *chain, const char *name_arg, ulong
> *value_arg,
> +                     TYPELIB *typelib, sys_after_update_func func)
> +    :sys_var(name_arg,func), value(value_arg), enum_names(typelib)
> +  {
> +    chain_sys_var(chain);
> +    set_allow_empty_value(FALSE);
> +  }
> +  virtual bool check(THD *thd, set_var *var)
> +  {
> +    return check_set(thd, var, enum_names);
> +  }
> +  bool update(THD *thd, set_var *var);
> +  uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
> +  bool check_update_type(Item_result type) { return 0; }
> +  void set_default(THD *thd, enum_var_type type);
> +  SHOW_TYPE show_type() { return SHOW_CHAR; }
> +};
> +
>  

Why not inherit from sys_var_log_backup_output and redefine only the methods 
which are changed instead of copy/paste the code around? Like this:

class sys_var_log_backup_output : public sys_var_log_output
{
public:
   sys_var_log_backup_output(sys_var_chain *chain, const char *name_arg, ulong 
*value_arg,
                      TYPELIB *typelib, sys_after_update_func func)
     :sys_var_log_output(chain,name_arg,value_arg,typelib,func)
   {}
   bool update(THD *thd, set_var *var);
   void set_default(THD *thd, enum_var_type type);
};

For this to work, I had to change private member variables of sys_var_log_output 
to protected, which is natural if you wan't to extend a class.

>  /* Variable that you can only read from */
>  
> @@ -1345,7 +1371,9 @@ CHARSET_INFO *get_old_charset_by_name(co
>  uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
>  		NAMED_LIST **found);
>  
> -extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path;
> +extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path,
> +       sys_var_backup_history_log_path, sys_var_backup_progress_log_path,
> +       sys_var_backupdir;
>  
>  /* key_cache functions */
>  KEY_CACHE *get_key_cache(LEX_STRING *cache_name);
> 


> === modified file 'sql/share/errmsg.txt'
> --- a/sql/share/errmsg.txt	2008-06-04 13:20:03 +0000
> +++ b/sql/share/errmsg.txt	2008-06-25 21:29:44 +0000
> @@ -6246,7 +6246,7 @@ ER_BACKUP_THREAD_INIT
>          eng "Backup driver's table locking thread can not be initialized."
>  
>  ER_BACKUP_PROGRESS_TABLES
> -        eng "Can't open the online backup progress tables. Check
> 'mysql.online_backup' and 'mysql.online_backup_progress'."
> +        eng "Can't open the backup log tables. Check 'mysql.backup_history' and
> 'mysql.backup_progress'."
>  
>  ER_TABLESPACE_EXIST
>    eng "Tablespace '%-.192s' already exists"
> 


> === modified file 'sql/sql_parse.cc'
> --- a/sql/sql_parse.cc	2008-06-04 13:20:03 +0000
> +++ b/sql/sql_parse.cc	2008-06-25 21:29:44 +0000
> @@ -6669,6 +6669,13 @@ bool reload_acl_and_cache(THD *thd, ulon
>      if (flush_error_log())
>        result=1;
>    }
> +  /*
> +    Added support for flushing backup logs.
> +  */
> +  if (options & REFRESH_BACKUP_LOG)
> +  {
> +    logger.flush_backup_logs(thd);
> +  }
>  #ifdef HAVE_QUERY_CACHE
>    if (options & REFRESH_QUERY_CACHE_FREE)
>    {
> 


> === modified file 'sql/sql_yacc.yy'
> --- a/sql/sql_yacc.yy	2008-06-04 13:20:03 +0000
> +++ b/sql/sql_yacc.yy	2008-06-25 21:29:44 +0000
> @@ -9970,6 +9970,8 @@ flush_option:
>            { Lex->type|= REFRESH_GRANT; }
>          | LOGS_SYM
>            { Lex->type|= REFRESH_LOG; }
> +        | BACKUP_SYM LOGS_SYM
> +          { Lex->type|= REFRESH_BACKUP_LOG; }
>          | STATUS_SYM
>            { Lex->type|= REFRESH_STATUS; }
>          | SLAVE
> 


> === modified file 'sql/table.cc'
> --- a/sql/table.cc	2008-05-08 16:01:15 +0000
> +++ b/sql/table.cc	2008-06-25 21:29:44 +0000
> @@ -33,9 +33,20 @@ LEX_STRING GENERAL_LOG_NAME= {C_STRING_W
>  /* SLOW_LOG name */
>  LEX_STRING SLOW_LOG_NAME= {C_STRING_WITH_LEN("slow_log")};
>  
> +/* BACKUP_HISTORY_LOG name */
> +LEX_STRING BACKUP_HISTORY_LOG_NAME= {C_STRING_WITH_LEN("backup_history")};
> +
> +/* BACKUP_PROGRESS_LOG name */
> +LEX_STRING BACKUP_PROGRESS_LOG_NAME= {C_STRING_WITH_LEN("backup_progress")};
> +
> +/* BACKUP_SETTINGS name */
> +LEX_STRING BACKUP_SETTINGS_NAME= {C_STRING_WITH_LEN("backup_settings")};
> +
> +
>  #ifndef EMBEDDED_LIBRARY
>  extern LEX_STRING BACKUP_HISTORY_LOG_NAME;
>  extern LEX_STRING BACKUP_PROGRESS_LOG_NAME;
> +extern LEX_STRING BACKUP_SETTINGS_NAME;
>  #endif
>  
>  	/* Functions defined in this file */
> @@ -246,6 +257,30 @@ TABLE_CATEGORY get_table_category(const 
>      if ((name->length == SLOW_LOG_NAME.length) &&
>          (my_strcasecmp(system_charset_info,
>                        SLOW_LOG_NAME.str,
> +                      name->str) == 0))
> +    {
> +      return TABLE_CATEGORY_PERFORMANCE;
> +    }
> +
> +    if ((name->length == BACKUP_HISTORY_LOG_NAME.length) &&
> +        (my_strcasecmp(system_charset_info,
> +                      BACKUP_HISTORY_LOG_NAME.str,
> +                      name->str) == 0))
> +    {
> +      return TABLE_CATEGORY_PERFORMANCE;
> +    }
> +
> +    if ((name->length == BACKUP_PROGRESS_LOG_NAME.length) &&
> +        (my_strcasecmp(system_charset_info,
> +                      BACKUP_PROGRESS_LOG_NAME.str,
> +                      name->str) == 0))
> +    {
> +      return TABLE_CATEGORY_PERFORMANCE;
> +    }
> +
> +    if ((name->length == BACKUP_SETTINGS_NAME.length) &&
> +        (my_strcasecmp(system_charset_info,
> +                      BACKUP_SETTINGS_NAME.str,
>                        name->str) == 0))
>      {
>        return TABLE_CATEGORY_PERFORMANCE;
> 


> === modified file 'sql/unireg.h'
> --- a/sql/unireg.h	2008-04-30 16:16:45 +0000
> +++ b/sql/unireg.h	2008-06-25 21:29:44 +0000
> @@ -32,6 +32,9 @@
>  #ifndef DATADIR
>  #define DATADIR		"data/"
>  #endif
> +#ifndef BACKUPDIR
> +#define BACKUPDIR		"data/"
> +#endif
>  #ifndef SHAREDIR
>  #define SHAREDIR	"share/"
>  #endif
> 
> 

Rafal

=== modified file 'sql/backup/CMakeLists.txt'
--- sql/backup/CMakeLists.txt	2008-05-27 19:47:15 +0000
+++ sql/backup/CMakeLists.txt	2008-06-27 09:53:09 +0000
@@ -25,7 +25,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/
 SET(BACKUP_SOURCES stream.cc logger.cc kernel.cc
                image_info.cc backup_info.cc data_backup.cc
                be_default.cc buffer_iterator.cc
-               be_snapshot.cc be_thread.cc backup_progress.cc
+               be_snapshot.cc be_thread.cc 
                backup_test.cc be_nodata.cc)
 
 IF(NOT SOURCE_SUBLIBS)

=== modified file 'sql/backup/Makefile.am'
--- sql/backup/Makefile.am	2008-06-25 13:30:04 +0000
+++ sql/backup/Makefile.am	2008-06-27 09:53:09 +0000
@@ -38,7 +38,6 @@ libbackup_la_SOURCES = \
   be_nodata.cc \
   buffer_iterator.cc \
   be_thread.cc \
-  backup_progress.cc \
   backup_test.cc
 
 libbackup_la_LIBADD = libbackupstream.la
@@ -67,7 +66,6 @@ noinst_HEADERS = \
   be_nodata.h \
   buffer_iterator.h \
   be_thread.h \
-  backup_progress.h \
   stream_v1.h \
   stream_v1_services.h \
   backup_test.h

=== modified file 'sql/backup/backup_kernel.h'
--- sql/backup/backup_kernel.h	2008-06-25 13:30:04 +0000
+++ sql/backup/backup_kernel.h	2008-06-28 11:50:56 +0000
@@ -79,6 +79,8 @@ class Backup_restore_ctx: public backup:
 
  private:
 
+  ulonglong m_id; ///< Unique id of the operation.
+
   /** Indicates if a backup/restore operation is in progress. */
   static bool is_running;
   static pthread_mutex_t  run_lock; ///< To guard @c is_running flag.
@@ -111,7 +113,10 @@ class Backup_restore_ctx: public backup:
   /** Memory allocator for backup stream library. */
   static backup::Mem_allocator *mem_alloc;
 
-  int prepare(LEX_STRING location);
+  void save_persistent_state();
+  int  load_persistent_state();
+
+  int prepare(enum_type op_type, LEX_STRING location, const char *query);
   void disable_fkey_constraints();
   
   friend class Backup_info;
@@ -133,7 +138,7 @@ bool Backup_restore_ctx::is_valid() cons
 inline
 ulonglong Backup_restore_ctx::op_id() const
 {
-  return m_op_id; // inherited from Logger class
+  return m_id;
 }
 
 /// Disable foreign key constraint checks (needed during restore).

=== removed file 'sql/backup/backup_progress.cc'
--- sql/backup/backup_progress.cc	2008-03-25 10:04:09 +0000
+++ sql/backup/backup_progress.cc	1970-01-01 00:00:00 +0000
@@ -1,907 +0,0 @@
-/* Copyright (C) 2004-2007 MySQL AB
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; version 2 of the License.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-*/
-
-/**
-   @file backup_progress.cc
-
-   This file contains the methods to create and update rows in the 
-   online backup progress tables.
-
-   @todo Decide on what "size" means. Does it mean number of rows or number
-         of byte?
-  */
-
-#include "../mysql_priv.h"
-#include "backup_progress.h"
-#include "be_thread.h"
-
-/* BACKUP_HISTORY_LOG name */
-LEX_STRING BACKUP_HISTORY_LOG_NAME= {C_STRING_WITH_LEN("online_backup")};
-
-/* BACKUP_PROGRESS_LOG name */
-LEX_STRING BACKUP_PROGRESS_LOG_NAME= {C_STRING_WITH_LEN("online_backup_progress")};
-
-/**
-   Check online backup progress tables.
-
-   This method attempts to open the online backup progress tables. It returns
-   an error if either table is not present or cannot be opened.
-
-   @param[in] THD * The current thread.
-
-   @returns Information whether backup progress tables can be used.
-
-   @retval FALSE  success
-   @retval TRUE  failed to open one of the tables
-  */
-my_bool check_ob_progress_tables(THD *thd)
-{
-  TABLE_LIST tables;
-  my_bool ret= FALSE;
-
-  DBUG_ENTER("check_ob_progress_tables");
-
-  /* Check mysql.online_backup */
-  tables.init_one_table("mysql", "online_backup", TL_READ);
-  if (simple_open_n_lock_tables(thd, &tables))
-  {
-    ret= TRUE;
-    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
-    DBUG_RETURN(ret);
-  }
-  close_thread_tables(thd);
-
-  /* Check mysql.online_backup_progress */
-  tables.init_one_table("mysql", "online_backup_progress", TL_READ);
-  if (simple_open_n_lock_tables(thd, &tables))
-  {
-    ret= TRUE;
-    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
-    DBUG_RETURN(ret);
-  }
-  close_thread_tables(thd);
-  DBUG_RETURN(ret);
-}
-
-/**
-   Get text string for state.
-
-   @param enum_backup_state  state        The current state of the operation
-
-   @returns char * a text string for state.
-  */
-void get_state_string(enum_backup_state state, String *str)
-{
-  DBUG_ENTER("get_state_string()");
-
-  str->length(0);
-  switch (state) {
-  case BUP_COMPLETE:
-    str->append("complete");
-    break;
-  case BUP_STARTING:
-    str->append("starting");
-    break;
-  case BUP_VALIDITY_POINT:
-    str->append("validity point");
-    break;
-  case BUP_RUNNING:
-    str->append("running");
-    break;
-  case BUP_ERRORS:
-    str->append("error");
-    break;
-  case BUP_CANCEL:
-    str->append("cancel");
-    break;
-  default:
-    str->append("unknown");
-    break;
-  }
-  DBUG_VOID_RETURN;
-}
-
-/**
-  Write the backup log entry for the backup history log to a table.
-
-  This method creates a new row in the backup history log with the
-  information provided.
-
-  @param[IN]   thd          The current thread
-  @param[OUT]  backup_id    The new row id for the backup history
-  @param[IN]   process_id   The process id of the operation 
-  @param[IN]   state        The current state of the operation
-  @param[IN]   operation    The current operation (backup or restore)
-  @param[IN]   error_num    The error number
-  @param[IN]   user_comment The user's comment specified in the
-                            command (not implemented yet)
-  @param[IN]   backup_file  The name of the target file
-  @param[IN]   command      The actual command entered
-
-  @retval TRUE if error.
-
-  @todo Add internal error handler to handle errors that occur on
-        open. See  thd->push_internal_handler(&error_handler).
-*/
-bool backup_history_log_write(THD *thd, 
-                              ulonglong *backup_id,
-                              int process_id,
-                              enum_backup_state state,
-                              enum_backup_operation operation,
-                              int error_num,
-                              const char *user_comment,
-                              const char *backup_file,
-                              const char *command)
-{
-  TABLE_LIST table_list;
-  TABLE *table= NULL;
-  bool result= TRUE;
-  bool need_close= FALSE;
-  bool need_rnd_end= FALSE;
-  Open_tables_state open_tables_backup;
-  bool save_time_zone_used;
-  char *host= current_thd->security_ctx->host; // host name
-  char *user= current_thd->security_ctx->user; // user name
-
-  save_time_zone_used= thd->time_zone_used;
-  bzero(& table_list, sizeof(TABLE_LIST));
-  table_list.alias= table_list.table_name= BACKUP_HISTORY_LOG_NAME.str;
-  table_list.table_name_length= BACKUP_HISTORY_LOG_NAME.length;
-
-  table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
-
-  table_list.db= MYSQL_SCHEMA_NAME.str;
-  table_list.db_length= MYSQL_SCHEMA_NAME.length;
-
-  if (!(table= open_performance_schema_table(thd, & table_list,
-                                             & open_tables_backup)))
-    goto err;
-
-  need_close= TRUE;
-
-  if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
-      table->file->ha_rnd_init(0))
-    goto err;
-
-  need_rnd_end= TRUE;
-
-  /* Honor next number columns if present */
-  table->next_number_field= table->found_next_number_field;
-
-  /*
-    Get defaults for new record.
-  */
-  restore_record(table, s->default_values); 
-
-  /* check that all columns exist */
-  if (table->s->fields < ET_OBH_FIELD_COUNT)
-    goto err;
-
-  /*
-    Fill in the data.
-  */
-  table->field[ET_OBH_FIELD_PROCESS_ID]->store(process_id, TRUE);
-  table->field[ET_OBH_FIELD_PROCESS_ID]->set_notnull();
-  table->field[ET_OBH_FIELD_BACKUP_STATE]->store(state, TRUE);
-  table->field[ET_OBH_FIELD_BACKUP_STATE]->set_notnull();
-  table->field[ET_OBH_FIELD_OPER]->store(operation, TRUE);
-  table->field[ET_OBH_FIELD_OPER]->set_notnull();
-  table->field[ET_OBH_FIELD_ERROR_NUM]->store(error_num, TRUE);
-  table->field[ET_OBH_FIELD_ERROR_NUM]->set_notnull();
-
-  if (host)
-  {
-    if(table->field[ET_OBH_FIELD_HOST_OR_SERVER]->store(host, 
-       strlen(host), system_charset_info))
-      goto err;
-    table->field[ET_OBH_FIELD_HOST_OR_SERVER]->set_notnull();
-  }
-
-  if (user)
-  {
-    if (table->field[ET_OBH_FIELD_USERNAME]->store(user,
-        strlen(user), system_charset_info))
-      goto err;
-    table->field[ET_OBH_FIELD_USERNAME]->set_notnull();
-  }
-
-  if (user_comment)
-  {
-    if (table->field[ET_OBH_FIELD_COMMENT]->store(user_comment,
-        strlen(user_comment), system_charset_info))
-      goto err;
-    table->field[ET_OBH_FIELD_COMMENT]->set_notnull();
-  }
-
-  if (backup_file)
-  {
-    if (table->field[ET_OBH_FIELD_BACKUP_FILE]->store(backup_file, 
-        strlen(backup_file), system_charset_info))
-      goto err;
-    table->field[ET_OBH_FIELD_BACKUP_FILE]->set_notnull();
-  }
-
-  if (command)
-  {
-    if (table->field[ET_OBH_FIELD_COMMAND]->store(command,
-        strlen(command), system_charset_info))
-      goto err;
-    table->field[ET_OBH_FIELD_COMMAND]->set_notnull();
-  }
-
-  /* log table entries are not replicated */
-  if (table->file->ha_write_row(table->record[0]))
-    goto err;
-
-  /*
-    Get last insert id for row.
-  */
-  *backup_id= table->file->insert_id_for_cur_row;
-
-  result= FALSE;
-
-err:
-  if (result && !thd->killed)
-    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                        ER_BACKUP_LOG_WRITE_ERROR,
-                        ER(ER_BACKUP_LOG_WRITE_ERROR),
-                        "mysql.online_backup");
-
-  if (need_rnd_end)
-  {
-    table->file->ha_rnd_end();
-    table->file->ha_release_auto_increment();
-  }
-  if (need_close)
-    close_performance_schema_table(thd, & open_tables_backup);
-
-  thd->time_zone_used= save_time_zone_used;
-  return result;
-}
-
-/**
-  Update a backup history log entry for the given backup_id to a table.
-
-  This method updates a row in the backup history log using one
-  of four data types as determined by the field (see fld).
-
-  @param[IN]   thd          The current thread
-  @param[IN]   backup_id    The row id for the backup history to be updated
-  @param[IN]   fld          The enum for the field to be updated 
-  @param[IN]   val_long     The value for long fields
-  @param[IN]   val_time     The value for time fields
-  @param[IN]   val_str      The value for char * fields
-  @param[IN]   val_state    The value for state fields
-
-  @retval TRUE if error.
-
-  @todo Add internal error handler to handle errors that occur on
-        open. See  thd->push_internal_handler(&error_handler).
-*/
-bool backup_history_log_update(THD *thd, 
-                               ulonglong backup_id,
-                               enum_backup_history_table_field fld,
-                               ulonglong val_long,
-                               time_t val_time,
-                               const char *val_str,
-                               int val_state)
-{
-  TABLE_LIST table_list;
-  TABLE *table= NULL;
-  bool result= TRUE;
-  bool need_close= FALSE;
-  Open_tables_state open_tables_backup;
-  bool save_time_zone_used;
-  int ret= 0;
-
-  save_time_zone_used= thd->time_zone_used;
-
-  bzero(& table_list, sizeof(TABLE_LIST));
-  table_list.alias= table_list.table_name= BACKUP_HISTORY_LOG_NAME.str;
-  table_list.table_name_length= BACKUP_HISTORY_LOG_NAME.length;
-
-  table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
-
-  table_list.db= MYSQL_SCHEMA_NAME.str;
-  table_list.db_length= MYSQL_SCHEMA_NAME.length;
-
-  if (!(table= open_performance_schema_table(thd, & table_list,
-                                             & open_tables_backup)))
-    goto err;
-
-  if (find_backup_history_row(table, backup_id))
-    goto err;
-
-  need_close= TRUE;
-
-  store_record(table, record[1]);
-
-  /*
-    Fill in the data.
-  */
-  switch (fld) {
-    case ET_OBH_FIELD_BINLOG_POS:
-    case ET_OBH_FIELD_ERROR_NUM:
-    case ET_OBH_FIELD_NUM_OBJ:
-    case ET_OBH_FIELD_TOTAL_BYTES:
-    {
-      table->field[fld]->store(val_long, TRUE);
-      table->field[fld]->set_notnull();
-      break;
-    }
-    case ET_OBH_FIELD_BINLOG_FILE:
-    {
-      if (val_str)
-      {
-        if(table->field[fld]->store(val_str, strlen(val_str), 
-                                    system_charset_info))
-          goto err;
-        table->field[fld]->set_notnull();
-      }
-      break;
-    }    
-    case ET_OBH_FIELD_ENGINES:
-    {
-      String str;    // engines string
-      str.length(0);
-      table->field[fld]->val_str(&str);
-      if (str.length() > 0)
-        str.append(", ");
-      str.append(val_str);
-      if (str.length() > 0)
-      {
-        if(table->field[fld]->store(str.c_ptr(), 
-           str.length(), system_charset_info))
-          goto err;
-        table->field[fld]->set_notnull();
-      }
-      break;
-    }    
-    case ET_OBH_FIELD_START_TIME:
-    case ET_OBH_FIELD_STOP_TIME:
-    case ET_OBH_FIELD_VP:
-    {
-      if (val_time)
-      {
-        MYSQL_TIME time;
-        my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)val_time);
-
-        table->field[fld]->set_notnull();
-        table->field[fld]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
-      }
-      break;
-    }
-    case ET_OBH_FIELD_BACKUP_STATE:
-    {
-      table->field[fld]->store(val_state, TRUE);
-      table->field[fld]->set_notnull();
-      break;
-    }
-    default:
-      goto err;
-  }
-
-  /*
-    Update the row.
-  */
-  if ((ret= table->file->ha_update_row(table->record[1], table->record[0])))
-    goto err;
-
-  result= FALSE;
-
-err:
-  if (result && !thd->killed)
-    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                        ER_BACKUP_LOG_WRITE_ERROR,
-                        ER(ER_BACKUP_LOG_WRITE_ERROR),
-                        "mysql.online_backup");
-
-  if (need_close)
-    close_performance_schema_table(thd, & open_tables_backup);
-
-  thd->time_zone_used= save_time_zone_used;
-  return result;
-}
-
-/**
-  Write the backup log entry for the backup progress log to a table.
-
-  This method creates a new row in the backup progress log with the
-  information provided.
-
-  @param[IN]   thd         The current thread
-  @param[OUT]  backup_id   The id of the backup/restore operation for
-                           the progress information
-  @param[IN]   object      The name of the object processed
-  @param[IN]   start       Start datetime
-  @param[IN]   stop        Stop datetime
-  @param[IN]   size        Size value
-  @param[IN]   progress    Progress (percent)
-  @param[IN]   error_num   Error number (should be 0 if success)
-  @param[IN]   notes       Misc data from engine
-
-  @retval TRUE if error.
-
-  @todo Add internal error handler to handle errors that occur on
-        open. See  thd->push_internal_handler(&error_handler).
-*/
-bool backup_progress_log_write(THD *thd,
-                               ulonglong backup_id,
-                               const char *object,
-                               time_t start,
-                               time_t stop,
-                               longlong size,
-                               longlong progress,
-                               int error_num,
-                               const char *notes)
-{
-  TABLE_LIST table_list;
-  TABLE *table;
-  bool result= TRUE;
-  bool need_close= FALSE;
-  bool need_rnd_end= FALSE;
-  Open_tables_state open_tables_backup;
-  bool save_time_zone_used;
-
-  save_time_zone_used= thd->time_zone_used;
-
-  bzero(& table_list, sizeof(TABLE_LIST));
-  table_list.alias= table_list.table_name= BACKUP_PROGRESS_LOG_NAME.str;
-  table_list.table_name_length= BACKUP_PROGRESS_LOG_NAME.length;
-
-  table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
-
-  table_list.db= MYSQL_SCHEMA_NAME.str;
-  table_list.db_length= MYSQL_SCHEMA_NAME.length;
-
-  if (!(table= open_performance_schema_table(thd, & table_list,
-                                             & open_tables_backup)))
-    goto err;
-
-  need_close= TRUE;
-
-  if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
-      table->file->ha_rnd_init(0))
-    goto err;
-
-  need_rnd_end= TRUE;
-
-  /* Honor next number columns if present */
-  table->next_number_field= table->found_next_number_field;
-
-  /*
-    Get defaults for new record.
-  */
-  restore_record(table, s->default_values); 
-
-  /* check that all columns exist */
-  if (table->s->fields < ET_OBP_FIELD_PROG_COUNT)
-    goto err;
-
-  /*
-    Fill in the data.
-  */
-  table->field[ET_OBP_FIELD_BACKUP_ID_FK]->store(backup_id, TRUE);
-  table->field[ET_OBP_FIELD_BACKUP_ID_FK]->set_notnull();
-
-  if (object)
-  {
-    if (table->field[ET_OBP_FIELD_PROG_OBJECT]->store(object,
-        strlen(object), system_charset_info))
-      goto err;
-    table->field[ET_OBP_FIELD_PROG_OBJECT]->set_notnull();
-  }
-
-  if (notes)
-  {
-    if (table->field[ET_OBP_FIELD_PROG_NOTES]->store(notes,
-        strlen(notes), system_charset_info))
-      goto err;
-    table->field[ET_OBP_FIELD_PROG_NOTES]->set_notnull();
-  }
-
-  if (start)
-  {
-    MYSQL_TIME time;
-    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)start);
-
-    table->field[ET_OBP_FIELD_PROG_START_TIME]->set_notnull();
-    table->field[ET_OBP_FIELD_PROG_START_TIME]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
-  }
-
-  if (stop)
-  {
-    MYSQL_TIME time;
-    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)stop);
-
-    table->field[ET_OBP_FIELD_PROG_STOP_TIME]->set_notnull();
-    table->field[ET_OBP_FIELD_PROG_STOP_TIME]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
-  }
-
-  table->field[ET_OBP_FIELD_PROG_SIZE]->store(size, TRUE);
-  table->field[ET_OBP_FIELD_PROG_SIZE]->set_notnull();
-  table->field[ET_OBP_FIELD_PROGRESS]->store(progress, TRUE);
-  table->field[ET_OBP_FIELD_PROGRESS]->set_notnull();
-  table->field[ET_OBP_FIELD_PROG_ERROR_NUM]->store(error_num, TRUE);
-  table->field[ET_OBP_FIELD_PROG_ERROR_NUM]->set_notnull();
-
-  /* log table entries are not replicated */
-  if (table->file->ha_write_row(table->record[0]))
-    goto err;
-
-  result= FALSE;
-
-err:
-  if (result && !thd->killed)
-    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                        ER_BACKUP_LOG_WRITE_ERROR,
-                        ER(ER_BACKUP_LOG_WRITE_ERROR),
-                        "mysql.online_backup_progress");
-
-  if (need_rnd_end)
-  {
-    table->file->ha_rnd_end();
-    table->file->ha_release_auto_increment();
-  }
-  if (need_close)
-    close_performance_schema_table(thd, & open_tables_backup);
-
-  thd->time_zone_used= save_time_zone_used;
-  return result;
-}
-
-/**
-   Find the row in the table that matches the backup_id.
-
-   This method locates the row in the online backup table that matches the
-   backup_id passed.
-
-   @param TABLE      table      The open table.
-   @param ulonglong  backup_id  The id of the row to locate.
-
-   @retval 0  success
-   @retval 1  failed to find row
-  */
-bool find_backup_history_row(TABLE *table, ulonglong backup_id)
-{
-  uchar key[MAX_KEY_LENGTH]; // key buffer for search
-  /*
-    Create key to find row. We have to use field->store() to be able to
-    handle different field types (method is overloaded).
-  */
-  table->field[ET_OBH_FIELD_BACKUP_ID]->store(backup_id, TRUE);
-
-  key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
-
-  if (table->file->index_read_idx_map(table->record[0], 0, key, HA_WHOLE_KEY,
-                                      HA_READ_KEY_EXACT))
-    return true;
-
-  return false;
-}
-
-/**
-   report_ob_init()
-
-   This method inserts a new row in the online_backup table populating it
-   with the initial values passed. It returns the backup_id of the new row.
-
-   @param THD                thd          The current thread class.
-   @param int                process_id   The process id of the operation 
-   @param enum_backup_state  state        The current state of the operation
-   @param enum_backup_op     operation    The current operation 
-                                          (backup or restore)
-   @param int                error_num    The error number
-   @param char *             user_comment The user's comment specified in the
-                                          command (not implemented yet)
-   @param char *             backup_file  The name of the target file
-   @param char *             command      The actual command entered
-
-   @retval long backup_id  The autoincrement value for the new row.
-  */
-ulonglong report_ob_init(THD *thd, 
-                         int process_id,
-                         enum_backup_state state,
-                         enum_backup_operation operation,
-                         int error_num,
-                         const char *user_comment,
-                         const char *backup_file,
-                         const char *command)
-{ 
-  ulonglong backup_id= 0;
-  int ret= 0;                                  // return value
-  DBUG_ENTER("report_ob_init()");
-
-  ret= backup_history_log_write(thd, &backup_id, process_id, state, operation,
-                                error_num, user_comment, backup_file, command);
-  /*
-    Record progress update.
-  */
-  String str;
-  get_state_string(state, &str);
-  report_ob_progress(thd, backup_id, "backup kernel", 0, 
-                     0, 0, 0, 0, str.c_ptr());
-  DBUG_RETURN(backup_id);
-}
-
-/**
-   Update the binlog information for the row that matches the backup_id.
-
-   This method locates the row in the online backup table that matches the
-   backup_id passed and updates the binlog values.
-
-   @param THD                  thd          The current thread class.
-   @param ulonglong            backup_id    The id of the row to locate.
-   @param int                  backup_pos   The id of the row to locate.
-   @param char *               binlog_file  The filename of the binlog.
-
-   @retval 0  success
-   @retval 1  failed to find row
-  */
-int report_ob_binlog_info(THD *thd,
-                          ulonglong backup_id,
-                          int binlog_pos,
-                          const char *binlog_file)
-{
-  int ret= 0;                           // return value
-  DBUG_ENTER("report_ob_binlog_info()");
-
-  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_BINLOG_POS, 
-                                 binlog_pos, 0, 0, 0);
-  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_BINLOG_FILE, 
-                                 0, 0, binlog_file, 0);
-  DBUG_RETURN(ret);
-}
-
-/**
-   Update the error number for the row that matches the backup_id.
-
-   This method locates the row in the online backup table that matches the
-   backup_id passed and updates the error number value.
-
-   @param THD        thd        The current thread class.
-   @param ulonglong  backup_id  The id of the row to locate.
-   @param int        error_num  New error number.
-
-   @retval 0  success
-   @retval 1  failed to find row
-  */
-int report_ob_error(THD *thd,
-                    ulonglong backup_id,
-                    int error_num)
-{
-  int ret= 0;  // return value
-  DBUG_ENTER("report_ob_error()");
-
-  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_ERROR_NUM, 
-                                 error_num, 0, 0, 0);
-
-  DBUG_RETURN(ret);
-}
-
-/**
-   Update the number of objects for the row that matches the backup_id.
-
-   This method locates the row in the online backup table that matches the
-   backup_id passed and updates the number of objects value.
-
-   @param THD        thd         The current thread class.
-   @param ulonglong  backup_id    The id of the row to locate.
-   @param int        num_objects  New error number.
-
-   @retval 0  success
-   @retval 1  failed to find row
-  */
-int report_ob_num_objects(THD *thd,
-                          ulonglong backup_id,
-                          int num_objects)
-{
-  int ret= 0;  // return value
-  DBUG_ENTER("report_ob_num_objects()");
-
-  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_NUM_OBJ, 
-                                 num_objects, 0, 0, 0);
-
-  DBUG_RETURN(ret);
-}
-
-/**
-   Update the size for the row that matches the backup_id.
-
-   This method locates the row in the online backup table that matches the
-   backup_id passed and updates the size value.
-
-   @param THD        thd        The current thread class.
-   @param ulonglong  backup_id  The id of the row to locate.
-   @param int        size       New size value.
-
-   @retval 0  success
-   @retval 1  failed to find row
-  */
-int report_ob_size(THD *thd,
-                   ulonglong backup_id,
-                   longlong size)
-{
-  int ret= 0;  // return value
-  DBUG_ENTER("report_ob_size()");
-
-  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_TOTAL_BYTES, 
-                                 size, 0, 0, 0);
-
-  DBUG_RETURN(ret);
-}
-
-/**
-   Update the start/stop time for the row that matches the backup_id.
-
-   This method locates the row in the online backup table that matches the
-   backup_id passed and updates the start/stop values.
-
-   @param THD        thd        The current thread class.
-   @param ulonglong  backup_id  The id of the row to locate.
-   @param my_time_t  start      Start datetime.
-   @param my_time_t  stop       Stop datetime.
-
-   @retval 0  success
-   @retval 1  failed to find row
-  */
-int report_ob_time(THD *thd,
-                   ulonglong backup_id,
-                   time_t start,
-                   time_t stop)
-{
-  int ret= 0;  // return value
-  DBUG_ENTER("report_ob_time()");
-
-  if (start)
-    ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_START_TIME, 
-                                   0, start, 0, 0);
-
-  if (stop)
-    ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_STOP_TIME, 
-                                   0, stop, 0, 0);
-
-  DBUG_RETURN(ret);
-}
-
-/**
-   Update the validity point time for the row that matches the backup_id.
-
-   This method updates the validity point time for the backup operation
-   identified by backup_id.
-
-   @param THD        thd        The current thread class.
-   @param ulonglong  backup_id  The id of the row to locate.
-   @param my_time_t  vp_time    Validity point datetime.
-
-   @retval 0  success
-   @retval 1  failed to find row
-  */
-int report_ob_vp_time(THD *thd,
-                      ulonglong backup_id,
-                      time_t vp_time)
-{
-  int ret= 0;  // return value
-  DBUG_ENTER("report_ob_vp_time()");
-
-  if (vp_time)
-    ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_VP, 
-                                   0, vp_time, 0, 0);
-
-  DBUG_RETURN(ret);
-}
-
-/**
-   Update the engines string for the row that matches the backup_id.
-
-   This method updates the engines information for the backup operation
-   identified by backup_id. This method appends to the those listed in the
-   table for the backup_id.
-
-   @param THD        thd          The current thread class.
-   @param ulonglong  backup_id    The id of the row to locate.
-   @param char *     egnine_name  The name of the engine to add.
-
-   @retval 0  success
-   @retval 1  failed to find row
-  */
-int report_ob_engines(THD *thd,
-                      ulonglong backup_id,
-                      const char *engine_name)
-{
-  int ret= 0;  // return value
-  DBUG_ENTER("report_ob_engines()");
-
-  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_ENGINES, 
-                                 0, 0, engine_name, 0);
-
-  DBUG_RETURN(ret);
-}
-
-/**
-   Update the state for the row that matches the backup_id.
-
-   This method locates the row in the online backup table that matches the
-   backup_id passed and updates the state value.
-
-   @param THD                thd        The current thread class.
-   @param ulonglong          backup_id  The id of the row to locate.
-   @param enum_backup_state  state      New state value.
-
-   @retval 0  success
-   @retval 1  failed to find row
-  */
-int report_ob_state(THD *thd, 
-                    ulonglong backup_id,
-                    enum_backup_state state)
-{
-  int ret= 0;  // return value
-  String str;
-  DBUG_ENTER("report_ob_state()");
-
-  ret= backup_history_log_update(thd, backup_id, ET_OBH_FIELD_BACKUP_STATE, 
-                                 0, 0, 0, state);
-  /*
-    Record progress update.
-  */
-  get_state_string(state, &str);
-  report_ob_progress(thd, backup_id, "backup kernel", 0, 
-                     0, 0, 0, 0, str.c_ptr());
-
-  DBUG_RETURN(ret);
-}
-
-/**
-   Creates a new progress row for the row that matches the backup_id.
-
-   This method inserts a new row in the online backup progress table using
-   the values passed. This method is used to insert progress information during
-   the backup operation.
-
-   @param THD        thd        The current thread class.
-   @param ulonglong  backup_id  The id of the master table row.
-   @param char *     object     The name of the object processed.
-   @param my_time_t  start      Start datetime.
-   @param my_time_t  stop       Stop datetime.
-   @param longlong   size       Size value.
-   @param longlong   progress   Progress (percent).
-   @param int        error_num  Error number (should be 0 is success).
-   @param char *     notes      Misc data from engine
-
-   @retval 0  success
-   @retval 1  failed to find row
-  */
-inline int report_ob_progress(THD *thd,
-                       ulonglong backup_id,
-                       const char *object,
-                       time_t start,
-                       time_t stop,
-                       longlong size,
-                       longlong progress,
-                       int error_num,
-                       const char *notes)
-{
-  int ret= 0;                           // return value
-  DBUG_ENTER("report_ob_progress()");
-
-  ret= backup_progress_log_write(thd, backup_id, object, start, stop, 
-                                 size, progress, error_num, notes);
-
-  DBUG_RETURN(ret);
-}
-
-
-

=== modified file 'sql/backup/data_backup.cc'
--- sql/backup/data_backup.cc	2008-06-05 12:26:31 +0000
+++ sql/backup/data_backup.cc	2008-06-27 09:53:14 +0000
@@ -10,7 +10,7 @@
   @todo Implement better scheduling strategy in Scheduler::step
   @todo Add error reporting in the scheduler and elsewhere
   @todo If an error from driver is ignored (and operation retried) leave trace
-        of the error in the log.
+        of the error in the log.`
  */
 
 #include "../mysql_priv.h"
@@ -18,7 +18,6 @@
 #include "backup_kernel.h"
 #include "backup_engine.h"
 #include "stream.h"
-#include "backup_progress.h"
 #include "debug.h"
 #include "be_default.h"  // needed for table locking code
 

=== modified file 'sql/backup/kernel.cc'
--- sql/backup/kernel.cc	2008-06-25 13:30:04 +0000
+++ sql/backup/kernel.cc	2008-06-30 07:42:18 +0000
@@ -75,7 +75,6 @@
 #include "be_snapshot.h"
 #include "be_nodata.h"
 #include "ddl_blocker.h"
-#include "backup_progress.h"
 
 
 /** 
@@ -329,21 +328,106 @@ pthread_mutex_t Backup_restore_ctx::run_
 backup::Mem_allocator *Backup_restore_ctx::mem_alloc= NULL;
 
 
+void Backup_restore_ctx::save_persistent_state()
+{
+  File fd= 0;
+  byte buf[8];
+  ulonglong saved_id= m_id;
+
+  // Store id in endianess agnostic form.
+
+  for (uint i=sizeof(buf); i > 0; --i)
+  {
+    buf[i-1]= saved_id & 0xFF;
+    saved_id >>= 8;
+  }
+
+  // TODO: set the name via options -- need an API for that
+  
+  fd= my_open("backup_settings.obx", O_WRONLY|O_BINARY|O_CREAT, MYF(MY_WME));      
+
+  if (fd < 0)
+    return;
+
+  my_seek(fd, 0, 0, MYF(MY_WME));
+  my_write(fd, buf, sizeof(buf), MYF(MY_WME));
+}
+
+int Backup_restore_ctx::load_persistent_state()
+{
+  int error= 0;
+  File fd= 0;
+  byte buf[8];
+
+  // TODO: set the name via options -- need an API for that
+  // TODO: ensure that my_open() doesn't push error if file not found.
+   
+  fd= my_open("backup_settings.obx", O_RDONLY|O_BINARY, MYF(MY_FFNF));      
+
+  // TODO: write warnings if something goes wrong
+
+  if (!fd)
+  {
+    error= TRUE;
+    goto end;
+  }
+
+  // TODO: add version number to the setting file and check it.
+
+  if (my_read(fd, buf, sizeof(buf), MYF(MY_WME|MY_NABP)) != sizeof(buf))
+  {
+    error= TRUE;
+    goto end;
+  }
+
+  for (uint i=0; i < sizeof(buf); ++i)
+  {
+    m_id = m_id | buf[i];
+    m_id <<= 8;
+  }
+
+end:
+
+  if (fd > 0)
+    my_close(fd, MYF(MY_WME));
+
+  return error;
+}
+
+
 Backup_restore_ctx::Backup_restore_ctx(THD *thd)
  :Logger(thd), m_state(CREATED), m_thd_options(thd->options),
   m_error(0), m_path(NULL), m_remove_loc(FALSE), m_stream(NULL), m_catalog(NULL)
 {
-  /*
-    Check for progress tables.
-  */
-  if (check_ob_progress_tables(thd))
-    m_error= ER_BACKUP_PROGRESS_TABLES;
+  // set-up basic error logging destinations.
+
+  if (Logger::set_output(DBUG_TRACE|ERROR_LOG|ERROR_STACK))
+    m_error= ER_BACKUP_LOGGER_INIT;
+
+  save_errors();  
+
+  // load saved parameters (currently only backup_id)
+
+  if (load_persistent_state())
+  {
+    /*
+      We could not read saved state - perhaps the file was deleted. Thus
+      we need to start from scratch and pick a new id to start from.
+
+      Function generate_backup_id() looks into backup logs and
+      tries to guess an id which was not used yet.
+    */
+    m_id= generate_backup_id();
+  }
+  else
+    ++m_id;
+
 }
 
 Backup_restore_ctx::~Backup_restore_ctx()
 {
   close();
-  
+
   delete m_catalog;  
   delete m_stream;
 }
@@ -359,18 +443,12 @@ Backup_restore_ctx::~Backup_restore_ctx(
 
   @returns 0 on success, error code otherwise.
  */ 
-int Backup_restore_ctx::prepare(LEX_STRING location)
+int Backup_restore_ctx::prepare(Logger::enum_type op_type, 
+                                LEX_STRING location, const char *query)
 {
   if (m_error)
     return m_error;
   
-  // Prepare error reporting context.
-  
-  mysql_reset_errors(m_thd, 0);
-  m_thd->no_warnings_for_error= FALSE;
-  save_errors();  
-
-
   /*
     Check access for SUPER rights. If user does not have SUPER, fail with error.
   */
@@ -432,6 +510,25 @@ int Backup_restore_ctx::prepare(LEX_STRI
     return m_error;
   }
 
+  // We are ready for the BACKUP/RESTORE operation which starts now.
+  // Setup logging into the backup log.
+
+  if (Logger::set_id(m_id) || Logger::set_op(op_type, location, query))
+  {
+    fatal_error(ER_BACKUP_LOGGER_INIT);
+    return m_error;
+  }
+
+  if (Logger::set_output(Logger::BACKUP_LOG))
+  {
+    fatal_error(ER_BACKUP_LOGGER_INIT);
+    return m_error;
+  }
+
+  // We save persistent state of the new context which is now fully initialized.
+
+  save_persistent_state();
+
   // Freeze all meta-data. 
 
   if (obs::ddl_blocker_enable(m_thd))
@@ -469,22 +566,17 @@ Backup_restore_ctx::prepare_for_backup(L
   if (m_error)
     return NULL;
   
-  if (Logger::init(BACKUP, location, query))
-  {
-    fatal_error(ER_BACKUP_LOGGER_INIT);
-    return NULL;
-  }
-
   time_t when= my_time(0);
-  report_start(when);
   
   /*
     Do preparations common to backup and restore operations. After call
     to prepare() all meta-data changes are blocked.
    */ 
-  if (prepare(location))
+  if (prepare(BACKUP,location,query))
     return NULL;
 
+  report_start(when);
+
   backup::String path(location);
   
   /*
@@ -548,21 +640,16 @@ Backup_restore_ctx::prepare_for_restore(
   if (m_error)
     return NULL;
   
-  if (Logger::init(RESTORE, location, query))
-  {
-    fatal_error(ER_BACKUP_LOGGER_INIT);
-    return NULL;
-  }
-
   time_t when= my_time(0);  
-  report_start(when);
 
   /*
     Do preparations common to backup and restore operations. After this call
     changes of meta-data are blocked.
    */ 
-  if (prepare(location))
+  if (prepare(BACKUP, location, query))
     return NULL;
+
+  report_start(when);
   
   /*
     Open input stream.

=== modified file 'sql/backup/logger.cc'
--- sql/backup/logger.cc	2008-03-21 09:57:45 +0000
+++ sql/backup/logger.cc	2008-06-30 07:41:31 +0000
@@ -1,7 +1,7 @@
 #include "../mysql_priv.h"
 
-#include "logger.h"
 #include "image_info.h"
+#include "logger.h"
 
 /** @file
  
@@ -10,6 +10,31 @@
 
 namespace backup {
 
+int Logger::set_output(uint mask)
+{
+  int err=0;
+  uint to_set= mask & ~out_set;
+
+  if (to_set & ERROR_STACK)
+  {
+    // TODO: hide these behind SI interface.
+    mysql_reset_errors(m_thd, 0);
+    m_thd->no_warnings_for_error= FALSE;
+  }
+
+  if (to_set & BACKUP_LOG)
+    if ((err= check_backup_logs(m_thd)))
+      to_set&= ~BACKUP_LOG;
+  
+  out_set|= to_set;
+
+  return err;
+}
+
+void Logger::dont_output(uint mask)
+{
+  out_set&= ~mask;
+}
 
 /**
   Output message on a given level.
@@ -37,38 +62,69 @@ int Logger::write_message(log_level::val
    char buf[ERRMSGSIZE + 30];
    const char *out= msg;
 
-   if (m_state == READY || m_state == RUNNING)
+   /*
+     Prepend "Backup:" or "Restore:" to the message if type of the operation 
+     is known.
+   */
+   if (m_state >= READY)
    {
      my_snprintf(buf, sizeof(buf), "%s: %s", 
                  m_type == BACKUP ? "Backup" : "Restore" , msg);
      out= buf;
    }
-   
+
+   time_t ts; // TODO: set it to the current time
+
    switch (level) {
+
    case log_level::ERROR:
      if (m_save_errors)
        errors.push_front(new MYSQL_ERROR(::current_thd, error_code,
                                          MYSQL_ERROR::WARN_LEVEL_ERROR, msg));
-     sql_print_error(out);
-     push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
-                         error_code, msg);
-     DBUG_PRINT("backup_log",("[ERROR] %s", out));
-     
-     if (m_state == READY || m_state == RUNNING)
-       report_ob_error(m_thd, m_op_id, error_code);
+
+     // Store last error code in the history record
+     m_op_hist.error_num= error_code;
+
+     // Write error message to destinations
+
+     if (output_to(DBUG_TRACE))
+       DBUG_PRINT("backup_log",("[ERROR] %s", out));
+
+     if (output_to(ERROR_LOG))
+       sql_print_error(out);
+
+     if (output_to(ERROR_STACK))
+       push_warning_printf(m_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+                           error_code, msg);
      
+     if (output_to(BACKUP_LOG))
+       backup_progress_log_write(m_thd, m_op_hist.backup_id,
+                                 "backup kernel", ts, ts, 0, 0,
+                                 error_code, msg);
+
      return 0;
 
    case log_level::WARNING:
-     sql_print_warning(out);
-     push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                         error_code, msg);
-     DBUG_PRINT("backup_log",("[Warning] %s", out));
+
+     if (output_to(DBUG_TRACE))
+       DBUG_PRINT("backup_log",("[Warning] %s", out));
+
+     if (output_to(ERROR_LOG))
+       sql_print_warning(out);
+
+     if (output_to(ERROR_STACK))
+       push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                           error_code, msg);
      return 0;
 
    case log_level::INFO:
-     sql_print_information(out);
-     DBUG_PRINT("backup_log",("[Info] %s", out));
+
+     if (output_to(DBUG_TRACE))
+       DBUG_PRINT("backup_log",("[Info] %s", out));
+
+     if (output_to(ERROR_LOG))
+       sql_print_information(out);
+
      return 0;
 
    default: return ERROR;
@@ -114,8 +170,12 @@ int Logger::v_write_message(log_level::v
 void Logger::report_stats_pre(const Image_info &info)
 {
   DBUG_ASSERT(m_state == RUNNING);
-  
-  report_ob_num_objects(m_thd, m_op_id, info.table_count());
+
+  m_op_hist.num_objects= info.table_count(); 
+
+  // TODO: Create list of drivers in m_op_hist.engine_name
+  //for (ushort n=0; n < info.snap_count(); ++n)
+  //  m_ctx.report_driver(info.m_snap[n]->name());
 }
 
 /**
@@ -125,8 +185,10 @@ void Logger::report_stats_pre(const Imag
 void Logger::report_stats_post(const Image_info &info)
 {
   DBUG_ASSERT(m_state == RUNNING);
-  
-  report_ob_size(m_thd, m_op_id, info.data_size);
+
+  m_op_hist.size= info.data_size;  
+
+  backup_history_log_write(m_thd, &m_op_hist);
 }
 
 } // backup namespace

=== modified file 'sql/backup/logger.h'
--- sql/backup/logger.h	2008-03-21 09:57:45 +0000
+++ sql/backup/logger.h	2008-06-30 07:37:16 +0000
@@ -4,7 +4,6 @@
 #include <backup_stream.h>
 #include <backup/error.h>
 #include <backup/debug.h>
-#include <backup/backup_progress.h>
 
 
 namespace backup {
@@ -43,10 +42,21 @@ class Logger
 
    enum enum_type { BACKUP, RESTORE } m_type;
    enum { CREATED, READY, RUNNING, DONE } m_state;
+   enum enum_out_destinations {
+     DBUG_TRACE  = 1U<<0,
+     ERROR_LOG   = 1U<<1,
+     ERROR_STACK = 1U<<2,
+     BACKUP_LOG  = 1U<<3,
+   };
 
    Logger(THD*);
    ~Logger();
-   int init(enum_type, const LEX_STRING, const char*);
+   int  set_id(ulonglong id);
+   int  set_op(enum_type op_type, const LEX_STRING path, const char *query);
+
+   int  set_output(uint mask);
+   void dont_output(uint mask);
+   bool output_to(uint mask) const;
 
    int report_error(int error_code, ...);
    int report_error(log_level::value level, int error_code, ...);
@@ -72,30 +82,28 @@ class Logger
   /// Thread in which this logger is used.
   THD *m_thd;
 
-  /**
-    Id of the backup or restore operation.
-    
-    This id is used in the backup progress and log tables to identify the
-    operation. Value of @c m_op_id is meaningful only after a successful 
-    call to @c init(), when @m_state != CREATED.
-   */ 
-  ulonglong m_op_id;
+  st_backup_history m_op_hist;
 
   int v_report_error(log_level::value, int, va_list);
   int v_write_message(log_level::value, int, const char*, va_list);
   int write_message(log_level::value level , int error_code, const char *msg);
+  const char* get_state_string(enum_backup_state state);
 
  private:
 
   List<MYSQL_ERROR> errors;  ///< Used to store saved errors.
   bool m_save_errors;        ///< Flag telling if errors should be saved.
+  uint out_set;              ///< Set of output destinations.
 };
 
 inline
 Logger::Logger(THD *thd) 
   :m_type(BACKUP), m_state(CREATED),
-   m_thd(thd), m_op_id(0), m_save_errors(FALSE)
-{}
+   m_thd(thd), m_save_errors(FALSE), out_set(0)
+{
+  bzero(&m_op_hist,sizeof(m_op_hist));
+  m_op_hist.process_id= m_thd->id;
+}
 
 inline
 Logger::~Logger()
@@ -103,22 +111,35 @@ Logger::~Logger()
   clear_saved_errors();
 }
 
+inline
+int Logger::set_id(ulonglong id)
+{
+  m_op_hist.backup_id= id;
+  return 0; // always succeed
+}
+
+inline
+bool Logger::output_to(uint mask) const
+{
+  return out_set & mask;
+}
+
+
 /**
-  Initialize logger for backup or restore operation.
-  
-  A new id for that operation is assigned and stored in @c m_op_id
-  member.
-  
+  Setup logger for backup or restore operation.
+    
   @param[in]  type  type of operation (backup or restore)
-  @param[in]  path  location of the backup image
+  @param[in]  path  location of the backup image (as specified in BACKUP/RESTORE
+                    command
   @param[in]  query backup or restore query starting the operation
   
   @returns 0 on success, error code otherwise.
 
-  @todo Decide what to do if @c report_ob_init() signals errors.
- */ 
+  @todo Decide what to do if @c initialize() signals errors.
+  @todo Add code to get the user comment from command.
+*/ 
 inline
-int Logger::init(enum_type type, const LEX_STRING path, const char *query)
+int Logger::set_op(enum_type type, const LEX_STRING path, const char *query)
 {
   if (m_state != CREATED)
     return 0;
@@ -126,10 +147,15 @@ int Logger::init(enum_type type, const L
   m_type= type;
   m_state= READY;
 
-  // TODO: how to detect and report errors in report_ob_init()?
-  m_op_id= report_ob_init(m_thd, m_thd->id, BUP_STARTING, 
-                          type == BACKUP ? OP_BACKUP : OP_RESTORE, 
-                          0, "", path.str, query);  
+  m_op_hist.operation= type == BACKUP ? OP_BACKUP : OP_RESTORE;
+  m_op_hist.backup_file= path.str;
+  m_op_hist.command= (char*) query; // TODO: change type of m_op_hist.command to const char*
+
+  /*
+    Record progress update.
+  */
+  report_state(BUP_STARTING);
+
   BACKUP_BREAKPOINT("bp_starting_state");
   return 0;
 }
@@ -228,7 +254,7 @@ void Logger::report_start(time_t when)
   
   report_error(log_level::INFO, m_type == BACKUP ? ER_BACKUP_BACKUP_START
                                                  : ER_BACKUP_RESTORE_START);  
-  report_ob_time(m_thd, m_op_id, when, 0);
+  m_op_hist.start= when;
   report_state(BUP_RUNNING);
 }
 
@@ -245,9 +271,11 @@ void Logger::report_stop(time_t when, bo
 
   DBUG_ASSERT(m_state == RUNNING);
 
+  // TODO: report something different in case of error.
+
   report_error(log_level::INFO, m_type == BACKUP ? ER_BACKUP_BACKUP_DONE
                                                  : ER_BACKUP_RESTORE_DONE);  
-  report_ob_time(m_thd, m_op_id, 0, when);
+  m_op_hist.stop= when;
   report_state(success ? BUP_COMPLETE : BUP_ERRORS);
   m_state= DONE;
 }
@@ -256,7 +284,7 @@ void Logger::report_stop(time_t when, bo
   Report change of the state of operation
  
   For possible states see definition of @c enum_backup_state in 
-  backup_progress.h
+  backup_log.h
 
   @todo Consider reporting state changes in the server error log (as info
   entries).
@@ -264,10 +292,15 @@ void Logger::report_stop(time_t when, bo
 inline
 void Logger::report_state(enum_backup_state state)
 {
-  DBUG_ASSERT(m_state == RUNNING);
+  time_t ts; // TODO: set it to the current time
   
   // TODO: info about state change in the log?
-  report_ob_state(m_thd, m_op_id, state);
+
+  m_op_hist.state= state;
+
+  if (output_to(BACKUP_LOG))
+    backup_progress_log_write(m_thd, m_op_hist.backup_id, "backup kernel", ts, ts, 
+                              0, 0, 0, get_state_string(state));
 }
 
 /// Report validity point creation time.
@@ -276,7 +309,11 @@ void Logger::report_vp_time(time_t when)
 {
   DBUG_ASSERT(m_state == RUNNING);
   
-  report_ob_vp_time(m_thd, m_op_id, when);
+  m_op_hist.vp_time= when;
+
+  if (output_to(BACKUP_LOG))
+    backup_progress_log_write(m_thd, m_op_hist.backup_id, "backup kernel", 
+                              when, when, 0, 0, 0, "validity point time"); // TODO: internatinalize this  
 }
 
 /** 
@@ -289,17 +326,42 @@ void Logger::report_binlog_pos(const st_
 {
   DBUG_ASSERT(m_state == RUNNING);
   
-  // TODO: write to the log
-  report_ob_binlog_info(m_thd, m_op_id, pos.pos, pos.file);
+  m_op_hist.binlog_pos= pos.pos;
+  m_op_hist.binlog_file= pos.file;
+  
+  // TODO: write binlog position to the logs
 }
 
 /// Report name of a driver used in backup/restore operation.
 inline
 void Logger::report_driver(const char *name)
 {
-  DBUG_ASSERT(m_state == READY || m_state == RUNNING);
-  
-  report_ob_engines(m_thd, m_op_id, name);
+  /* 
+    We do nothing here, because list of drivers is reported only in the 
+    history log and then it is constructed from the snapshot list stored
+    in the Image_info object (see @c report_stats_pre()).
+  */
+}
+
+/**
+  Get text string for state.
+
+  @param enum_backup_state  state        The current state of the operation
+
+  @returns char * a text string for state.
+*/
+inline
+const char* Logger::get_state_string(enum_backup_state state)
+{
+  switch (state) {
+  case BUP_COMPLETE: return "complete";
+  case BUP_STARTING: return "starting";
+  case BUP_VALIDITY_POINT: return "validity point";
+  case BUP_RUNNING: return "running";
+  case BUP_ERRORS: return "error";
+  case BUP_CANCEL: return "cancel";
+  default: return "unknown";
+  }
 }
 
 } // backup namespace

=== modified file 'sql/log.cc'
--- sql/log.cc	2008-05-23 21:39:20 +0000
+++ sql/log.cc	2008-06-28 11:06:42 +0000
@@ -114,6 +114,34 @@ char *make_default_log_name(char *buff,c
 }
 
 /*
+  Set the default for the backupdir
+*/
+char *make_default_backupdir(char *buff)
+{
+  strmake(buff, mysql_data_home, FN_REFLEN-5);
+  return buff;
+}
+
+/**
+  Create the name of the backup log specified.
+
+  This method forms a new path + file name for the backup
+  log specified in @c name.
+
+  @param[IN] buff    Location for building new string.
+  @param[IN] name    Name of the backup log.
+  @param[IN] log_ext The extension for the log (e.g. .log).
+
+  @returns Pointer to new string containing the name.
+*/
+char *make_backup_log_name(char *buff, const char *name, const char* log_ext)
+{
+  strmake(buff, name, FN_REFLEN-5);
+  return fn_format(buff, buff, mysql_data_home, log_ext,
+                   MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT));
+}
+
+/*
   Helper class to hold a mutex for the duration of the
   block.
 
@@ -682,16 +710,37 @@ int Log_to_csv_event_handler::
 
   bzero(& table_list, sizeof(TABLE_LIST));
 
-  if (log_table_type == QUERY_LOG_GENERAL)
+  /*
+    Code changed to use a switch now that there are 4 logs.
+  */
+  switch (log_table_type) {
+  case QUERY_LOG_GENERAL:
   {
     table_list.alias= table_list.table_name= GENERAL_LOG_NAME.str;
     table_list.table_name_length= GENERAL_LOG_NAME.length;
+    break;
   }
-  else
+  case QUERY_LOG_SLOW:
   {
     DBUG_ASSERT(log_table_type == QUERY_LOG_SLOW);
     table_list.alias= table_list.table_name= SLOW_LOG_NAME.str;
     table_list.table_name_length= SLOW_LOG_NAME.length;
+    break;
+  }
+  case BACKUP_HISTORY_LOG:
+  {
+    DBUG_ASSERT(log_table_type == BACKUP_HISTORY_LOG);
+    table_list.alias= table_list.table_name= BACKUP_HISTORY_LOG_NAME.str;
+    table_list.table_name_length= BACKUP_HISTORY_LOG_NAME.length;
+    break;
+  }
+  case BACKUP_PROGRESS_LOG:
+  {
+    DBUG_ASSERT(log_table_type == BACKUP_PROGRESS_LOG);
+    table_list.alias= table_list.table_name= BACKUP_PROGRESS_LOG_NAME.str;
+    table_list.table_name_length= BACKUP_PROGRESS_LOG_NAME.length;
+    break;
+  }
   }
 
   table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
@@ -712,6 +761,377 @@ int Log_to_csv_event_handler::
   DBUG_RETURN(result);
 }
 
+/**
+  List of fields for online backup table.
+*/
+enum enum_backup_history_table_field
+{
+  ET_OBH_FIELD_BACKUP_ID = 0, /* start from 0 to correspond with field array */
+  ET_OBH_FIELD_PROCESS_ID,
+  ET_OBH_FIELD_BINLOG_POS,
+  ET_OBH_FIELD_BINLOG_FILE,
+  ET_OBH_FIELD_BACKUP_STATE,
+  ET_OBH_FIELD_OPER,
+  ET_OBH_FIELD_ERROR_NUM,
+  ET_OBH_FIELD_NUM_OBJ,
+  ET_OBH_FIELD_TOTAL_BYTES,
+  ET_OBH_FIELD_VP,
+  ET_OBH_FIELD_START_TIME,
+  ET_OBH_FIELD_STOP_TIME,
+  ET_OBH_FIELD_HOST_OR_SERVER,
+  ET_OBH_FIELD_USERNAME,
+  ET_OBH_FIELD_BACKUP_FILE,
+  ET_OBH_FIELD_COMMENT,
+  ET_OBH_FIELD_COMMAND,
+  ET_OBH_FIELD_DRIVERS,
+  ET_OBH_FIELD_COUNT /* a cool trick to count the number of fields  :)  */
+};
+
+/**
+  List of fields for online backup progress table.
+*/
+enum enum_backup_progress_table_field
+{
+  ET_OBP_FIELD_BACKUP_ID_FK = 0, /* start from 0 to correspond with field array */
+  ET_OBP_FIELD_PROG_OBJECT,
+  ET_OBP_FIELD_PROG_START_TIME,
+  ET_OBP_FIELD_PROG_STOP_TIME,
+  ET_OBP_FIELD_PROG_SIZE,
+  ET_OBP_FIELD_PROGRESS,
+  ET_OBP_FIELD_PROG_ERROR_NUM,
+  ET_OBP_FIELD_PROG_NOTES,
+  ET_OBP_FIELD_PROG_COUNT /* a cool trick to count the number of fields  :)  */
+};
+
+/**
+  Write the backup log entry for the backup history log to a table.
+
+  This method creates a new row in the backup history log with the
+  information provided.
+
+  @param[IN]   thd   The current thread
+  @param[IN]   st_backup_history   Data to write to log.
+
+  @retval TRUE if error.
+
+  @todo Add internal error handler to handle errors that occur on
+        open. See  thd->push_internal_handler(&error_handler).
+*/
+bool Log_to_csv_event_handler::
+  log_backup_history(THD *thd, 
+                     st_backup_history *history_data)
+{
+  TABLE_LIST table_list;
+  TABLE *table= NULL;
+  bool result= TRUE;
+  bool need_close= FALSE;
+  bool need_rnd_end= FALSE;
+  Open_tables_state open_tables_backup;
+  bool save_time_zone_used;
+  char *host= current_thd->security_ctx->host; // host name
+  char *user= current_thd->security_ctx->user; // user name
+
+  save_time_zone_used= thd->time_zone_used;
+  bzero(& table_list, sizeof(TABLE_LIST));
+  table_list.alias= table_list.table_name= BACKUP_HISTORY_LOG_NAME.str;
+  table_list.table_name_length= BACKUP_HISTORY_LOG_NAME.length;
+
+  table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
+
+  table_list.db= MYSQL_SCHEMA_NAME.str;
+  table_list.db_length= MYSQL_SCHEMA_NAME.length;
+
+  if (!(table= open_performance_schema_table(thd, & table_list,
+                                             & open_tables_backup)))
+    goto err;
+
+  need_close= TRUE;
+
+  if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
+      table->file->ha_rnd_init(0))
+    goto err;
+
+  need_rnd_end= TRUE;
+
+  /*
+    Get defaults for new record.
+  */
+  restore_record(table, s->default_values); 
+
+  /* check that all columns exist */
+  if (table->s->fields < ET_OBH_FIELD_COUNT)
+    goto err;
+
+  /*
+    Fill in the data.
+  */
+  table->field[ET_OBH_FIELD_BACKUP_ID]->store(history_data->backup_id, TRUE);
+  table->field[ET_OBH_FIELD_BACKUP_ID]->set_notnull();
+  table->field[ET_OBH_FIELD_PROCESS_ID]->store(history_data->process_id, TRUE);
+  table->field[ET_OBH_FIELD_PROCESS_ID]->set_notnull();
+  table->field[ET_OBH_FIELD_BINLOG_POS]->store(history_data->binlog_pos, TRUE);
+  table->field[ET_OBH_FIELD_BINLOG_POS]->set_notnull();
+
+  if (history_data->binlog_file)
+  {
+    if (table->field[ET_OBH_FIELD_BINLOG_FILE]->store(history_data->binlog_file, 
+                                                      strlen(history_data->binlog_file), 
+                                                      system_charset_info))
+      goto err;
+    table->field[ET_OBH_FIELD_BINLOG_FILE]->set_notnull();
+  }
+
+  table->field[ET_OBH_FIELD_BACKUP_STATE]->store(history_data->state, TRUE);
+  table->field[ET_OBH_FIELD_BACKUP_STATE]->set_notnull();
+  table->field[ET_OBH_FIELD_OPER]->store(history_data->operation, TRUE);
+  table->field[ET_OBH_FIELD_OPER]->set_notnull();
+  table->field[ET_OBH_FIELD_ERROR_NUM]->store(history_data->error_num, TRUE);
+  table->field[ET_OBH_FIELD_ERROR_NUM]->set_notnull();
+  table->field[ET_OBH_FIELD_NUM_OBJ]->store(history_data->num_objects, TRUE);
+  table->field[ET_OBH_FIELD_NUM_OBJ]->set_notnull();
+  table->field[ET_OBH_FIELD_TOTAL_BYTES]->store(history_data->size, TRUE);
+  table->field[ET_OBH_FIELD_TOTAL_BYTES]->set_notnull();
+
+  if (history_data->vp_time)
+  {
+    MYSQL_TIME time;
+    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)history_data->vp_time);
+
+    table->field[ET_OBH_FIELD_VP]->set_notnull();
+    table->field[ET_OBH_FIELD_VP]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+  }
+
+  if (history_data->start)
+  {
+    MYSQL_TIME time;
+    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)history_data->start);
+
+    table->field[ET_OBH_FIELD_START_TIME]->set_notnull();
+    table->field[ET_OBH_FIELD_START_TIME]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+  }
+
+  if (history_data->stop)
+  {
+    MYSQL_TIME time;
+    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)history_data->stop);
+
+    table->field[ET_OBH_FIELD_STOP_TIME]->set_notnull();
+    table->field[ET_OBH_FIELD_STOP_TIME]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+  }
+
+  if (host)
+  {
+    if(table->field[ET_OBH_FIELD_HOST_OR_SERVER]->store(host, 
+       strlen(host), system_charset_info))
+      goto err;
+    table->field[ET_OBH_FIELD_HOST_OR_SERVER]->set_notnull();
+  }
+
+  if (user)
+  {
+    if (table->field[ET_OBH_FIELD_USERNAME]->store(user,
+        strlen(user), system_charset_info))
+      goto err;
+    table->field[ET_OBH_FIELD_USERNAME]->set_notnull();
+  }
+
+  if (history_data->backup_file)
+  {
+    if (table->field[ET_OBH_FIELD_BACKUP_FILE]->store(
+        history_data->backup_file, 
+        strlen(history_data->backup_file), system_charset_info))
+      goto err;
+    table->field[ET_OBH_FIELD_BACKUP_FILE]->set_notnull();
+  }
+
+  if (history_data->user_comment)
+  {
+    if (table->field[ET_OBH_FIELD_COMMENT]->store(history_data->user_comment,
+        strlen(history_data->user_comment), system_charset_info))
+      goto err;
+    table->field[ET_OBH_FIELD_COMMENT]->set_notnull();
+  }
+
+  if (history_data->command)
+  {
+    if (table->field[ET_OBH_FIELD_COMMAND]->store(history_data->command,
+        strlen(history_data->command), system_charset_info))
+      goto err;
+    table->field[ET_OBH_FIELD_COMMAND]->set_notnull();
+  }
+
+  if (history_data->engine_name)
+  {
+    if (table->field[ET_OBH_FIELD_DRIVERS]->store(history_data->engine_name,
+        strlen(history_data->engine_name), system_charset_info))
+      goto err;
+    table->field[ET_OBH_FIELD_DRIVERS]->set_notnull();
+  }
+
+  /* log table entries are not replicated */
+  if (table->file->ha_write_row(table->record[0]))
+    goto err;
+
+  result= FALSE;
+
+err:
+  if (result && !thd->killed)
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                        ER_BACKUP_LOG_WRITE_ERROR,
+                        ER(ER_BACKUP_LOG_WRITE_ERROR),
+                        "mysql.backup_history");
+
+  if (need_rnd_end)
+    table->file->ha_rnd_end();
+  if (need_close)
+    close_performance_schema_table(thd, & open_tables_backup);
+
+  thd->time_zone_used= save_time_zone_used;
+  return result;
+}
+
+/**
+  Write the backup log entry for the backup progress log to a table.
+
+  This method creates a new row in the backup progress log with the
+  information provided.
+
+  @param[IN]   thd         The current thread
+  @param[OUT]  backup_id   The id of the backup/restore operation for
+                           the progress information
+  @param[IN]   object      The name of the object processed
+  @param[IN]   start       Start datetime
+  @param[IN]   stop        Stop datetime
+  @param[IN]   size        Size value
+  @param[IN]   progress    Progress (percent)
+  @param[IN]   error_num   Error number (should be 0 if success)
+  @param[IN]   notes       Misc data from engine
+
+  @retval TRUE if error.
+
+  @todo Add internal error handler to handle errors that occur on
+        open. See  thd->push_internal_handler(&error_handler).
+*/
+bool Log_to_csv_event_handler::
+  log_backup_progress(THD *thd,
+                      ulonglong backup_id,
+                      const char *object,
+                      time_t start,
+                      time_t stop,
+                      longlong size,
+                      longlong progress,
+                      int error_num,
+                      const char *notes)
+{
+  TABLE_LIST table_list;
+  TABLE *table;
+  bool result= TRUE;
+  bool need_close= FALSE;
+  bool need_rnd_end= FALSE;
+  Open_tables_state open_tables_backup;
+  bool save_time_zone_used;
+
+  save_time_zone_used= thd->time_zone_used;
+
+  bzero(& table_list, sizeof(TABLE_LIST));
+  table_list.alias= table_list.table_name= BACKUP_PROGRESS_LOG_NAME.str;
+  table_list.table_name_length= BACKUP_PROGRESS_LOG_NAME.length;
+
+  table_list.lock_type= TL_WRITE_CONCURRENT_INSERT;
+
+  table_list.db= MYSQL_SCHEMA_NAME.str;
+  table_list.db_length= MYSQL_SCHEMA_NAME.length;
+
+  if (!(table= open_performance_schema_table(thd, & table_list,
+                                             & open_tables_backup)))
+    goto err;
+
+  need_close= TRUE;
+
+  if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
+      table->file->ha_rnd_init(0))
+    goto err;
+
+  need_rnd_end= TRUE;
+
+  /*
+    Get defaults for new record.
+  */
+  restore_record(table, s->default_values); 
+
+  /* check that all columns exist */
+  if (table->s->fields < ET_OBP_FIELD_PROG_COUNT)
+    goto err;
+
+  /*
+    Fill in the data.
+  */
+  table->field[ET_OBP_FIELD_BACKUP_ID_FK]->store(backup_id, TRUE);
+  table->field[ET_OBP_FIELD_BACKUP_ID_FK]->set_notnull();
+
+  if (object)
+  {
+    if (table->field[ET_OBP_FIELD_PROG_OBJECT]->store(object,
+        strlen(object), system_charset_info))
+      goto err;
+    table->field[ET_OBP_FIELD_PROG_OBJECT]->set_notnull();
+  }
+
+  if (start)
+  {
+    MYSQL_TIME time;
+    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)start);
+
+    table->field[ET_OBP_FIELD_PROG_START_TIME]->set_notnull();
+    table->field[ET_OBP_FIELD_PROG_START_TIME]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+  }
+
+  if (stop)
+  {
+    MYSQL_TIME time;
+    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)stop);
+
+    table->field[ET_OBP_FIELD_PROG_STOP_TIME]->set_notnull();
+    table->field[ET_OBP_FIELD_PROG_STOP_TIME]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+  }
+
+  table->field[ET_OBP_FIELD_PROG_SIZE]->store(size, TRUE);
+  table->field[ET_OBP_FIELD_PROG_SIZE]->set_notnull();
+  table->field[ET_OBP_FIELD_PROGRESS]->store(progress, TRUE);
+  table->field[ET_OBP_FIELD_PROGRESS]->set_notnull();
+  table->field[ET_OBP_FIELD_PROG_ERROR_NUM]->store(error_num, TRUE);
+  table->field[ET_OBP_FIELD_PROG_ERROR_NUM]->set_notnull();
+
+  if (notes)
+  {
+    if (table->field[ET_OBP_FIELD_PROG_NOTES]->store(notes,
+        strlen(notes), system_charset_info))
+      goto err;
+    table->field[ET_OBP_FIELD_PROG_NOTES]->set_notnull();
+  }
+
+  /* log table entries are not replicated */
+  if (table->file->ha_write_row(table->record[0]))
+    goto err;
+
+  result= FALSE;
+
+err:
+  if (result && !thd->killed)
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                        ER_BACKUP_LOG_WRITE_ERROR,
+                        ER(ER_BACKUP_LOG_WRITE_ERROR),
+                        "mysql.backup_progress");
+
+  if (need_rnd_end)
+    table->file->ha_rnd_end();
+  if (need_close)
+    close_performance_schema_table(thd, & open_tables_backup);
+
+  thd->time_zone_used= save_time_zone_used;
+  return result;
+}
+
 bool Log_to_csv_event_handler::
   log_error(enum loglevel level, const char *format, va_list args)
 {
@@ -731,6 +1151,8 @@ void Log_to_file_event_handler::init_pth
 {
   mysql_log.init_pthread_objects();
   mysql_slow_log.init_pthread_objects();
+  mysql_backup_history_log.init_pthread_objects();
+  mysql_backup_progress_log.init_pthread_objects();
 }
 
 
@@ -774,6 +1196,65 @@ bool Log_to_file_event_handler::
   return retval;
 }
 
+/**
+  Write the history data to a file.
+
+  This method calls the write method for the backup log
+  class to write the history data to the file.
+
+  @param[IN]   thd   The current thread
+  @param[IN]   st_backup_history   Data to write to log.
+
+  @returns TRUE if error.
+*/
+bool Log_to_file_event_handler::
+  log_backup_history(THD *thd, 
+                     st_backup_history *history_data)
+{
+  Silence_log_table_errors error_handler;
+  thd->push_internal_handler(&error_handler);
+  bool retval= mysql_backup_history_log.write(thd, history_data);
+  thd->pop_internal_handler();
+  return retval;
+}
+
+/**
+  Write the progress data to a file.
+
+  This method calls the write method for the backup log
+  class to write the progress data to the file.
+
+  @param[IN]   thd         The current thread
+  @param[OUT]  backup_id   The new row id for the backup history
+  @param[IN]   object      The name of the object processed
+  @param[IN]   start       Start datetime
+  @param[IN]   stop        Stop datetime
+  @param[IN]   size        Size value
+  @param[IN]   progress    Progress (percent)
+  @param[IN]   error_num   Error number (should be 0 is success)
+  @param[IN]   notes       Misc data from engine
+
+  @returns TRUE if error.
+*/
+bool Log_to_file_event_handler::
+  log_backup_progress(THD *thd,
+                      ulonglong backup_id,
+                      const char *object,
+                      time_t start,
+                      time_t stop,
+                      longlong size,
+                      longlong progress,
+                      int error_num,
+                      const char *notes)
+{
+  Silence_log_table_errors error_handler;
+  thd->push_internal_handler(&error_handler);
+  bool retval= mysql_backup_progress_log.write(thd, backup_id, object, start,
+                 stop, size, progress, error_num, notes);
+  thd->pop_internal_handler();
+  return retval;
+}
+
 
 bool Log_to_file_event_handler::init()
 {
@@ -785,17 +1266,39 @@ bool Log_to_file_event_handler::init()
     if (opt_log)
       mysql_log.open_query_log(sys_var_general_log_path.value);
 
+    /*
+      Check the backup log options and open if they are turned on.
+    */
+    if (opt_backup_history_log)
+      mysql_backup_history_log.open_backup_history_log(
+        sys_var_backup_history_log_path.value);
+
+    if (opt_backup_progress_log)
+      mysql_backup_progress_log.open_backup_progress_log(
+        sys_var_backup_progress_log_path.value);
+
     is_initialized= TRUE;
   }
 
   return FALSE;
 }
 
+/**
+  Close and reopen the backup logs.
+*/
+void Log_to_file_event_handler::flush_backup_logs()
+{
+  /* reopen log files */
+  mysql_backup_history_log.reopen_file(TRUE);
+  mysql_backup_progress_log.reopen_file(FALSE);
+}
 
 void Log_to_file_event_handler::cleanup()
 {
   mysql_log.cleanup();
   mysql_slow_log.cleanup();
+  mysql_backup_history_log.cleanup();
+  mysql_backup_progress_log.cleanup();
 }
 
 void Log_to_file_event_handler::flush()
@@ -914,6 +1417,32 @@ bool LOGGER::flush_logs(THD *thd)
 }
 
 
+/**
+  Close and reopen the backup logs (with locks).
+
+  @param[IN]  thd   The current thread.
+
+  @returns FALSE.
+*/
+bool LOGGER::flush_backup_logs(THD *thd)
+{
+  int rc= 0;
+
+  /*
+    Now we lock logger, as nobody should be able to use logging routines while
+    log tables are closed
+  */
+  logger.lock_exclusive();
+
+  /* reopen log files */
+  file_log_handler->flush_backup_logs();
+
+  /* end of log flush */
+  logger.unlock();
+  return rc;
+}
+
+
 /*
   Log slow query with all enabled log event handlers
 
@@ -1065,6 +1594,106 @@ bool LOGGER::general_log_print(THD *thd,
   return general_log_write(thd, command, message_buff, message_buff_len);
 }
 
+
+/**
+  Write the backup log entry for the backup history logs (file or table).
+
+  This method creates a new row in the backup history log with the
+  information provided. It is a high-level wrapper for writing to any
+  of the log types (e.g., FILE or TABLE) as specified by --log-option.
+
+  @Note The backup logs currently only write to tables.
+
+  @param[IN]   thd   The current thread
+  @param[IN]   st_backup_history   Data to write to log.
+  
+  @returns TRUE if error.
+*/
+bool LOGGER::
+  backup_history_log_write(THD *thd, 
+                           st_backup_history *history_data)
+{
+  bool error= FALSE;
+  Log_event_handler **current_handler= backup_history_log_handler_list;
+  ulong id;
+
+  /*
+    Don't write if log is turned off.
+  */
+  if (!opt_backup_history_log)
+    return 0;
+
+  if (thd)
+    id= thd->thread_id;                 /* Normal thread */
+  else
+    id= 0;                              /* Log from connect handler */
+
+  lock_shared();
+  while (*current_handler)
+    error|= (*current_handler++)->
+      log_backup_history(thd, history_data) || error;
+  unlock();
+
+  return error;
+}
+
+/**
+  Write the backup log entry for the backup progress logs (file or table).
+
+  This method creates a new row in the backup progress log with the
+  information provided. It is a high-level wrapper for writing to any
+  of the log types (e.g., FILE or TABLE) as specified by --log-option.
+
+  @Note The backup logs currently only write to tables.
+
+  @param[IN]   thd         The current thread
+  @param[OUT]  backup_id   The new row id for the backup history
+  @param[IN]   object      The name of the object processed
+  @param[IN]   start       Start datetime
+  @param[IN]   stop        Stop datetime
+  @param[IN]   size        Size value
+  @param[IN]   progress    Progress (percent)
+  @param[IN]   error_num   Error number (should be 0 is success)
+  @param[IN]   notes       Misc data from engine
+
+  @returns TRUE if error.
+*/
+bool LOGGER::backup_progress_log_write(THD *thd,
+                                       ulonglong backup_id,
+                                       const char *object,
+                                       time_t start,
+                                       time_t stop,
+                                       longlong size,
+                                       longlong progress,
+                                       int error_num,
+                                       const char *notes)
+{
+  bool error= FALSE;
+  Log_event_handler **current_handler= backup_progress_log_handler_list;
+  ulong id;
+
+  /*
+    Don't write if log is turned off.
+  */
+  if (!opt_backup_progress_log)
+    return 0;
+
+  if (thd)
+    id= thd->thread_id;                 /* Normal thread */
+  else
+    id= 0;                              /* Log from connect handler */
+
+  lock_shared();
+  while (*current_handler)
+    error|= (*current_handler++)->
+      log_backup_progress(thd, backup_id, object, start, 
+                             stop, size, progress, error_num, notes) || error;
+  unlock();
+
+  return error;
+}
+
+
 void LOGGER::init_error_log(uint error_log_printer)
 {
   if (error_log_printer & LOG_NONE)
@@ -1139,9 +1768,77 @@ void LOGGER::init_general_log(uint gener
 }
 
 
+/**
+  Initialize the backup history log.
+
+  This method initializes the backup log handlers. Currently, only
+  log to table is supported.
+
+  @param[IN]   backup_history_log_printer  The output type for log.
+*/
+void LOGGER::init_backup_history_log(uint backup_history_log_printer)
+{
+  if (backup_history_log_printer & LOG_NONE)
+  {
+    backup_history_log_handler_list[0]= 0;
+    return;
+  }
+
+  switch (backup_history_log_printer) {
+  case LOG_FILE:
+    backup_history_log_handler_list[0]= file_log_handler;
+    backup_history_log_handler_list[1]= 0;
+    break;
+  case LOG_TABLE:
+    backup_history_log_handler_list[0]= table_log_handler;
+    backup_history_log_handler_list[1]= 0;
+    break;
+  case LOG_TABLE|LOG_FILE:
+    backup_history_log_handler_list[0]= file_log_handler;
+    backup_history_log_handler_list[1]= table_log_handler;
+    backup_history_log_handler_list[2]= 0;
+    break;
+  }
+}
+
+/**
+  Initialize the backup progress log.
+
+  This method initializes the backup log handlers. Currently, only
+  log to table is supported.
+
+  @param[IN]   backup_history_log_printer  The output type for log.
+*/
+void LOGGER::init_backup_progress_log(uint backup_progress_log_printer)
+{
+  if (backup_progress_log_printer & LOG_NONE)
+  {
+    backup_progress_log_handler_list[0]= 0;
+    return;
+  }
+
+  switch (backup_progress_log_printer) {
+  case LOG_FILE:
+    backup_progress_log_handler_list[0]= file_log_handler;
+    backup_progress_log_handler_list[1]= 0;
+    break;
+  case LOG_TABLE:
+    backup_progress_log_handler_list[0]= table_log_handler;
+    backup_progress_log_handler_list[1]= 0;
+    break;
+  case LOG_TABLE|LOG_FILE:
+    backup_progress_log_handler_list[0]= file_log_handler;
+    backup_progress_log_handler_list[1]= table_log_handler;
+    backup_progress_log_handler_list[2]= 0;
+    break;
+  }
+}
+
+
 bool LOGGER::activate_log_handler(THD* thd, uint log_type)
 {
   MYSQL_QUERY_LOG *file_log;
+  MYSQL_BACKUP_LOG *backup_log;
   bool res= FALSE;
   lock_exclusive();
   switch (log_type) {
@@ -1183,6 +1880,51 @@ bool LOGGER::activate_log_handler(THD* t
       }
     }
     break;
+  /*
+    Check the backup history and progress logs for activation.
+  */
+  case BACKUP_HISTORY_LOG:
+  {
+    if (!opt_backup_history_log)
+    {
+      backup_log= file_log_handler->get_backup_history_log();
+
+      backup_log->open_backup_history_log(sys_var_backup_history_log_path.value);
+      if (table_log_handler->activate_log(thd, BACKUP_HISTORY_LOG))
+      {
+        /* Error printed by open table in activate_log() */
+        res= TRUE;
+        backup_log->close(0);
+      }
+      else
+      {
+        init_backup_history_log(log_backup_output_options);
+        opt_backup_history_log= TRUE;
+      }
+    }
+    break;
+  }
+  case BACKUP_PROGRESS_LOG:
+  {
+    if (!opt_backup_progress_log)
+    {
+      backup_log= file_log_handler->get_backup_progress_log();
+
+      backup_log->open_backup_progress_log(sys_var_backup_progress_log_path.value);
+      if (table_log_handler->activate_log(thd, BACKUP_PROGRESS_LOG))
+      {
+        /* Error printed by open table in activate_log() */
+        res= TRUE;
+        backup_log->close(0);
+      }
+      else
+      {
+        init_backup_progress_log(log_backup_output_options);
+        opt_backup_progress_log= TRUE;
+      }
+    }
+    break;
+  }
   default:
     DBUG_ASSERT(0);
   }
@@ -1205,6 +1947,17 @@ void LOGGER::deactivate_log_handler(THD 
     tmp_opt= &opt_log;
     file_log= file_log_handler->get_mysql_log();
     break;
+  /*
+    Deactivate the backup history and progress logs on request.
+  */
+  case BACKUP_HISTORY_LOG:
+    tmp_opt= &opt_backup_history_log;
+    file_log= file_log_handler->get_backup_history_log();
+    break;
+  case BACKUP_PROGRESS_LOG:
+    tmp_opt= &opt_backup_progress_log;
+    file_log= file_log_handler->get_backup_progress_log();
+    break;
   default:
     assert(0);                                  // Impossible
   }
@@ -1240,20 +1993,45 @@ int LOGGER::set_handlers(uint error_log_
     slow_log_printer= (slow_log_printer & ~LOG_TABLE) | LOG_FILE;
     general_log_printer= (general_log_printer & ~LOG_TABLE) | LOG_FILE;
 
-    sql_print_error("Failed to initialize log tables. "
-                    "Falling back to the old-fashioned logs");
-  }
+    sql_print_error("Failed to initialize log tables. "
+                    "Falling back to the old-fashioned logs");
+  }
+
+  init_error_log(error_log_printer);
+  init_slow_log(slow_log_printer);
+  init_general_log(general_log_printer);
+
+  unlock();
+
+  return 0;
+}
+
+/**
+  Set the logging handlers for operation on the backup logs.
+
+  This method allows the caller to set the method of logging
+  for the backup logs. Values for these variables equate
+  to the {FILE, TABLE, NONE} definitions.
+
+  @param[IN] backup_history_log_printer  The type of output.
+  @param[IN] backup_progress_log_printer The type of output.
+
+  @returns 0
+*/
+
+int LOGGER::set_backup_handlers(uint backup_history_log_printer,
+                                uint backup_progress_log_printer)
+{
+  lock_exclusive();
 
-  init_error_log(error_log_printer);
-  init_slow_log(slow_log_printer);
-  init_general_log(general_log_printer);
+  init_backup_history_log(backup_history_log_printer);
+  init_backup_progress_log(backup_progress_log_printer);
 
   unlock();
 
   return 0;
 }
 
-
  /*
   Save position of binary log transaction cache.
 
@@ -2332,6 +3110,409 @@ bool MYSQL_QUERY_LOG::write(THD *thd, ti
 
 
 /**
+  Open a (new) backup log file.
+
+  Open the backup log file, init IO_CACHE and write startup messages.
+
+  @param[IN] log_name          The name of the log to open
+  @param[IN] log_type_arg      The type of the log. E.g. LOG_NORMAL
+  @param[IN] new_name          The new name for the logfile.
+  @param[IN] io_cache_type_arg The type of the IO_CACHE to use for this loge
+  @param[IN] history           If TRUE, process history log headeer else do
+                               progress header
+
+  @returns 0 success, 1 error
+*/
+bool MYSQL_BACKUP_LOG::open(const char *log_name, 
+                            enum_log_type log_type_arg,
+                            const char *new_name, 
+                            enum cache_type io_cache_type_arg,
+                            bool history)
+{
+  char buff[FN_REFLEN];
+  File file= -1;
+  int open_flags= O_CREAT | O_BINARY;
+  DBUG_ENTER("MYSQL_BACKUP_LOG::open");
+  DBUG_PRINT("enter", ("log_type: %d", (int) log_type_arg));
+
+  write_error= 0;
+
+  init(log_type_arg, io_cache_type_arg);
+
+  if (!(name= my_strdup(log_name, MYF(MY_WME))))
+  {
+    name= (char *)log_name; // for the error message
+    goto err;
+  }
+
+  if (new_name)
+    strmov(log_file_name, new_name);
+  else if (generate_new_name(log_file_name, name))
+    goto err;
+
+  if (io_cache_type == SEQ_READ_APPEND)
+    open_flags |= O_RDWR | O_APPEND;
+  else
+    open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND);
+
+  db[0]= 0;
+
+  if ((file= my_open(log_file_name, open_flags,
+                     MYF(MY_WME | ME_WAITTANG))) < 0 ||
+      init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
+                    my_tell(file, MYF(MY_WME)), 0,
+                    MYF(MY_WME | MY_NABP |
+                        ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
+    goto err;
+
+  /*
+    Write header of column names if this is the first time the log
+    has been opened.
+  */
+  if (!headers_written && (log_type == LOG_NORMAL))
+  {
+    char *end;
+
+    int len=my_snprintf(buff, sizeof(buff), "Columns for this log:\n");
+    if (history)
+      end= strnmov(buff + len, "backup_id \tprocess_id \tbinlog_pos "
+                   "\tbinlog_file \tbackup_state \toperation "
+                   "\terror_num \tnum_objects \ttotal_bytes "
+                   "\tvalidity_point_time \tstart_time \tstop_time "
+                   "\thost_or_server_name \tusername \tbackup_file "
+                   "\tuser_comment \tcommand \tdrivers\n",
+                   sizeof(buff) - len);
+    else
+      end= strnmov(buff + len, "\nbackup_id \tobject \tstart_time \tstop_time "
+                   "\ttotal_bytes \tprogress \terror_num \tnotes \tbackup_id "
+                   "\tobject \tstart_time \tstop_time \ttotal_bytes "
+                   "\tprogress \terror_num \tnotes\n",
+                   sizeof(buff) - len);
+    if (my_b_write(&log_file, (uchar*) buff, (uint) (end-buff)) ||
+        flush_io_cache(&log_file))
+      goto err;
+    headers_written= TRUE;
+  }
+
+  log_state= LOG_OPENED;
+  DBUG_RETURN(0);
+
+err:
+  sql_print_error("Could not use %s for backup logging (error %d).", name, errno);
+  if (file >= 0)
+    my_close(file, MYF(0));
+  end_io_cache(&log_file);
+  safeFree(name);
+  log_state= LOG_CLOSED;
+  DBUG_RETURN(1);
+}
+
+/**
+  Write an integer value to the log file.
+
+  This method writes the data passed and appends a tab character.
+
+  @param[IN]   thd   The current thread
+  @param[IN]   num   Data to write to log.
+
+  @returns TRUE if error.
+*/
+bool MYSQL_BACKUP_LOG::write_int(ulonglong num)
+{
+  char buff[32];
+  uint length= 0;
+
+  /*
+    This field is wide to allow ulonglong fields.
+    We don't want to truncate any large backup id values.
+  */
+  length= my_snprintf(buff, 32, "%10lu ", (ulong)num);
+  if (my_b_write(&log_file, (uchar*) buff, length))
+    return TRUE;
+  if (my_b_write(&log_file, (uchar*) "\t", 1))
+    return TRUE;
+  return FALSE;
+}
+
+
+/**
+  Write a datetime value to the log file.
+
+  This method writes the data passed (if not null) and appends a tab character.
+
+  @param[IN]   thd       The current thread
+  @param[IN]   time_val  Data to write to log.
+
+  @returns TRUE if error.
+*/
+bool MYSQL_BACKUP_LOG::write_datetime(time_t time_val)
+{
+  char local_time_buff[MAX_TIME_SIZE];
+  uint time_buff_len= 0;
+
+  if (time_val)
+  {
+    MYSQL_TIME time;
+    my_tz_OFFSET0->gmt_sec_to_TIME(&time, (my_time_t)time_val);
+
+    time_buff_len= my_snprintf(local_time_buff, MAX_TIME_SIZE,
+                               "%02d%02d%02d %2d:%02d:%02d",
+                               time.year % 100, time.month + 1,
+                               time.day, time.hour,
+                               time.minute, time.second);
+
+    if (my_b_write(&log_file, (uchar*) local_time_buff, time_buff_len))
+      return TRUE;
+    if (my_b_write(&log_file, (uchar*) "\t", 1))
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+  Write a character string value to the log file.
+
+  This method writes the data passed (if not null) and appends a tab character.
+
+  @param[IN]   thd       The current thread
+  @param[IN]   str       Data to write to log.
+
+  @returns TRUE if error.
+*/
+bool MYSQL_BACKUP_LOG::write_str(const char *str)
+{
+  if (str)
+  {
+    if (my_b_write(&log_file, (uchar*)str, strlen(str)))
+      return TRUE;
+    if (my_b_write(&log_file, (uchar*) "\t", 1))
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+  Write the backup log entry for the backup history log to a file.
+
+  This method creates a new row in the backup history log with the
+  information provided.
+
+  @param[IN]   thd   The current thread
+  @param[IN]   st_backup_history   Data to write to log.
+
+  @returns TRUE if error.
+*/
+bool MYSQL_BACKUP_LOG::write(THD *thd, st_backup_history *history_data)
+{
+  char *host= current_thd->security_ctx->host; // host name
+  char *user= current_thd->security_ctx->user; // user name
+  bool save_time_zone_used;
+
+  save_time_zone_used= thd->time_zone_used;
+
+  (void) pthread_mutex_lock(&LOCK_log);
+
+  /* 
+    Test if someone closed between the is_open test and lock 
+  */
+  if (is_open())
+  {
+    /*
+      Write log data.
+    */
+    if (write_int(history_data->backup_id))
+      goto err;
+    if (write_int(history_data->process_id))
+      goto err;
+    if (write_int(history_data->binlog_pos))
+      goto err;
+    if (write_str(history_data->binlog_file))
+      goto err;
+    if (write_int(history_data->state))
+      goto err;
+    if (write_int(history_data->operation))
+      goto err;
+    if (write_int(history_data->error_num))
+      goto err;
+    if (write_int(history_data->num_objects))
+      goto err;
+    if (write_int(history_data->size))
+      goto err;
+    if (write_datetime(history_data->vp_time))
+      goto err;
+    if (write_datetime(history_data->start))
+      goto err;
+    if (write_datetime(history_data->stop))
+      goto err;
+    if (write_str(host))
+      goto err;
+    if (write_str(user))
+      goto err;
+    if (write_str(history_data->user_comment))
+      goto err;
+    if (write_str(history_data->command))
+      goto err;
+    if (write_str(history_data->engine_name))
+      goto err;
+
+    if (my_b_write(&log_file, (uchar*) "\n", 1) ||
+        flush_io_cache(&log_file))
+      goto err;
+  }
+
+  (void) pthread_mutex_unlock(&LOCK_log);
+  thd->time_zone_used= save_time_zone_used;
+  return FALSE;
+err:
+
+  if (!write_error)
+  {
+    write_error= 1;
+    sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
+  }
+  (void) pthread_mutex_unlock(&LOCK_log);
+  thd->time_zone_used= save_time_zone_used;
+  return TRUE;
+}
+
+
+/**
+  Write the backup log entry for the backup progress log to a file.
+
+  This method creates a new row in the backup progress log with the
+  information provided.
+
+  @param[IN]   thd         The current thread
+  @param[OUT]  backup_id   The new row id for the backup history
+  @param[IN]   object      The name of the object processed
+  @param[IN]   start       Start datetime
+  @param[IN]   stop        Stop datetime
+  @param[IN]   size        Size value
+  @param[IN]   progress    Progress (percent)
+  @param[IN]   error_num   Error number (should be 0 is success)
+  @param[IN]   notes       Misc data from engine
+
+  @returns TRUE if error.
+*/
+bool MYSQL_BACKUP_LOG::write(THD *thd, ulonglong backup_id, const char *object, 
+                             time_t start, time_t stop, longlong size,
+                             longlong progress, int error_num, const char *notes)
+{
+  bool save_time_zone_used;
+
+  save_time_zone_used= thd->time_zone_used;
+
+  (void) pthread_mutex_lock(&LOCK_log);
+
+  /* 
+    Test if someone closed between the is_open test and lock 
+  */
+  if (is_open())
+  {
+    /*
+      Write log data.
+    */
+    if (write_int(backup_id))
+      goto err;
+    if (write_str(object))
+      goto err;
+    if (write_datetime(start))
+      goto err;
+    if (write_datetime(stop))
+      goto err;
+    if (write_int(size))
+      goto err;
+    if (write_int(progress))
+      goto err;
+    if (write_int(error_num))
+      goto err;
+    if (write_str(notes))
+      goto err;
+
+    if (my_b_write(&log_file, (uchar*) "\n", 1) ||
+        flush_io_cache(&log_file))
+      goto err;
+  }
+
+  (void) pthread_mutex_unlock(&LOCK_log);
+  thd->time_zone_used= save_time_zone_used;
+  return FALSE;
+err:
+
+  if (!write_error)
+  {
+    write_error= 1;
+    sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
+  }
+  (void) pthread_mutex_unlock(&LOCK_log);
+  thd->time_zone_used= save_time_zone_used;
+  return TRUE;
+}
+
+/**
+  Reopen the log file.
+
+  This method opens the log file.
+
+  @param[IN] history Process as history log if TRUE else progress log
+*/
+void MYSQL_BACKUP_LOG::reopen_file(bool history)
+{
+  char *save_name;
+
+  DBUG_ENTER("MYSQL_BACKUP_LOG::reopen_file");
+  if (!is_open())
+  {
+    DBUG_PRINT("info",("log is closed"));
+    DBUG_VOID_RETURN;
+  }
+
+  pthread_mutex_lock(&LOCK_log);
+
+  save_name= name;
+  name= 0;				// Don't free name
+  close(LOG_CLOSE_TO_BE_OPENED);
+
+  /*
+     Note that at this point, log_state != LOG_CLOSED (important for is_open()).
+  */
+
+  open(save_name, log_type, 0, io_cache_type, history);
+  my_free(save_name, MYF(0));
+
+  pthread_mutex_unlock(&LOCK_log);
+
+  DBUG_VOID_RETURN;
+}
+
+/**
+  Generate the next backup id.
+  
+  Since autoincrement columns are not permitted in CSV files, an alternative 
+  mechanism has been developed to create monotonically increasing values. When 
+  a server that does not have any logs written (no backup logs), the system 
+  starts at backup_id = 0. This value is stored in a binary file in the data 
+  directory named backup_settings.obx. Each time a new backup_id is needed, 
+  this value is read, incremented, then the file rewritten. This ensures a 
+  monotonically increasing backup_id. If the backup logs exist and the 
+  backup_settings.obx file does not, the system uses the backup log file size 
+  as the starting backup_id. 
+
+  @todo Do we need a mutex to protect this call internally?
+*/
+ulonglong MYSQL_BACKUP_LOG::generate_backup_id()
+{
+  // TODO: Check if backup log is opened and in good shape
+  MY_STAT fstate;
+
+  my_stat(log_file_name, &fstate, MYF(0)); 
+  //my_fstat(log_file.file, &fstate, MYF(0)); // alternative - use already opened fd
+
+  return fstate.st_size+1;  
+}
+
+
+/**
   @todo
   The following should be using fn_format();  We just need to
   first change fn_format() to cut the file name if it's too long.

=== modified file 'sql/log.h'
--- sql/log.h	2008-02-03 09:00:49 +0000
+++ sql/log.h	2008-06-28 12:30:07 +0000
@@ -16,6 +16,8 @@
 #ifndef LOG_H
 #define LOG_H
 
+#include <si_objects.h> // For backup log types
+
 class Relay_log_info;
 
 class Format_description_log_event;
@@ -223,6 +225,43 @@ private:
   time_t last_time;
 };
 
+class MYSQL_BACKUP_LOG: public MYSQL_LOG
+{
+public:
+  MYSQL_BACKUP_LOG () { headers_written= FALSE; }
+  void reopen_file(bool history);
+  bool write(THD *thd, st_backup_history *history_data);
+  bool write(THD *thd, ulonglong backup_id, const char *object, 
+             time_t start, time_t stop, longlong size,
+             longlong progress, int error_num, const char *notes);
+
+  bool open(const char *log_name,
+            enum_log_type log_type,
+            const char *new_name,
+            enum cache_type io_cache_type_arg,
+            bool history);
+
+  bool open_backup_history_log(const char *log_name)
+  {
+    char buf[FN_REFLEN];
+    return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
+                WRITE_CACHE, TRUE);
+  }
+  bool open_backup_progress_log(const char *log_name)
+  {
+    char buf[FN_REFLEN];
+    return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
+                WRITE_CACHE, FALSE);
+  }
+  ulonglong generate_backup_id();
+
+private:
+  bool write_int(ulonglong num);
+  bool write_datetime(time_t time_val);
+  bool write_str(const char *str);
+  bool headers_written;
+};
+
 class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
 {
  private:
@@ -411,6 +450,20 @@ public:
                            const char *command_type, uint command_type_len,
                            const char *sql_text, uint sql_text_len,
                            CHARSET_INFO *client_cs)= 0;
+
+  virtual bool log_backup_history(THD *thd, 
+                                  st_backup_history *history_data)= 0;
+
+  virtual bool log_backup_progress(THD *thd,
+                                   ulonglong backup_id,
+                                   const char *object,
+                                   time_t start,
+                                   time_t stop,
+                                   longlong size,
+                                   longlong progress,
+                                   int error_num,
+                                   const char *notes)= 0;
+
   virtual ~Log_event_handler() {}
 };
 
@@ -441,6 +494,19 @@ public:
                            const char *sql_text, uint sql_text_len,
                            CHARSET_INFO *client_cs);
 
+  virtual bool log_backup_history(THD *thd, 
+                                  st_backup_history *history_data);
+
+  virtual bool log_backup_progress(THD *thd,
+                                   ulonglong backup_id,
+                                   const char *object,
+                                   time_t start,
+                                   time_t stop,
+                                   longlong size,
+                                   longlong progress,
+                                   int error_num,
+                                   const char *notes);
+
   int activate_log(THD *thd, uint log_type);
 };
 
@@ -448,11 +514,15 @@ public:
 /* type of the log table */
 #define QUERY_LOG_SLOW 1
 #define QUERY_LOG_GENERAL 2
+#define BACKUP_HISTORY_LOG 3
+#define BACKUP_PROGRESS_LOG 4
 
 class Log_to_file_event_handler: public Log_event_handler
 {
   MYSQL_QUERY_LOG mysql_log;
   MYSQL_QUERY_LOG mysql_slow_log;
+  MYSQL_BACKUP_LOG mysql_backup_history_log;
+  MYSQL_BACKUP_LOG mysql_backup_progress_log;
   bool is_initialized;
 public:
   Log_to_file_event_handler(): is_initialized(FALSE)
@@ -472,14 +542,36 @@ public:
                            const char *command_type, uint command_type_len,
                            const char *sql_text, uint sql_text_len,
                            CHARSET_INFO *client_cs);
+
+  virtual bool log_backup_history(THD *thd, 
+                                   st_backup_history *history_data);
+
+  virtual bool log_backup_progress(THD *thd,
+                                   ulonglong backup_id,
+                                   const char *object,
+                                   time_t start,
+                                   time_t stop,
+                                   longlong size,
+                                   longlong progress,
+                                   int error_num,
+                                   const char *notes);
+
   void flush();
+  void flush_backup_logs();
   void init_pthread_objects();
   MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; }
   MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; }
+  MYSQL_BACKUP_LOG *get_backup_history_log()
+  { return &mysql_backup_history_log; }
+  MYSQL_BACKUP_LOG *get_backup_progress_log() 
+  { return &mysql_backup_progress_log; }
 };
 
 
-/* Class which manages slow, general and error log event handlers */
+/*
+   Class which manages slow, general, error log, backup history, and
+   backup progress event handlers.
+*/
 class LOGGER
 {
   rw_lock_t LOCK_logger;
@@ -494,6 +586,8 @@ class LOGGER
   Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
   Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
   Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
+  Log_event_handler *backup_history_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
+  Log_event_handler *backup_progress_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
 
 public:
 
@@ -517,6 +611,7 @@ public:
   void init_base();
   void init_log_tables();
   bool flush_logs(THD *thd);
+  bool flush_backup_logs(THD *thd);
   /* Perform basic logger cleanup. this will leave e.g. error log open. */
   void cleanup_base();
   /* Free memory. Nothing could be logged after this function is called */
@@ -530,13 +625,30 @@ public:
   bool general_log_write(THD *thd, enum enum_server_command command,
                          const char *query, uint query_length);
 
+  bool backup_history_log_write(THD *thd, 
+                                st_backup_history *history_data);
+
+  bool backup_progress_log_write(THD *thd,
+                                 ulonglong backup_id,
+                                 const char *object,
+                                 time_t start,
+                                 time_t stop,
+                                 longlong size,
+                                 longlong progress,
+                                 int error_num,
+                                 const char *notes);
+
   /* we use this function to setup all enabled log event handlers */
   int set_handlers(uint error_log_printer,
                    uint slow_log_printer,
                    uint general_log_printer);
+  int set_backup_handlers(uint backup_history_log_printer,
+                          uint backup_progress_log_printer);
   void init_error_log(uint error_log_printer);
   void init_slow_log(uint slow_log_printer);
   void init_general_log(uint general_log_printer);
+  void init_backup_history_log(uint backup_history_log_printer);
+  void init_backup_progress_log(uint backup_progress_log_printer);
   void deactivate_log_handler(THD* thd, uint log_type);
   bool activate_log_handler(THD* thd, uint log_type);
   MYSQL_QUERY_LOG *get_slow_log_file_handler()
@@ -551,6 +663,18 @@ public:
       return file_log_handler->get_mysql_log();
     return NULL;
   }
+  MYSQL_BACKUP_LOG *get_backup_history_log_file_handler()
+  { 
+    if (file_log_handler)
+      return file_log_handler->get_backup_history_log();
+    return NULL;
+  }
+  MYSQL_BACKUP_LOG *get_backup_progress_log_file_handler()
+  { 
+    if (file_log_handler)
+      return file_log_handler->get_backup_progress_log();
+    return NULL;
+  }
 };
 
 enum enum_binlog_format {

=== modified file 'sql/mysql_priv.h'
--- sql/mysql_priv.h	2008-05-27 19:47:15 +0000
+++ sql/mysql_priv.h	2008-06-28 12:24:14 +0000
@@ -1461,6 +1461,9 @@ extern LEX_STRING INFORMATION_SCHEMA_NAM
 extern LEX_STRING MYSQL_SCHEMA_NAME;
 extern LEX_STRING GENERAL_LOG_NAME;
 extern LEX_STRING SLOW_LOG_NAME;
+extern LEX_STRING BACKUP_HISTORY_LOG_NAME;
+extern LEX_STRING BACKUP_PROGRESS_LOG_NAME;
+extern LEX_STRING BACKUP_SETTINGS_NAME;
 
 extern const LEX_STRING partition_keywords[];
 ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name);
@@ -1659,6 +1662,8 @@ void remove_db_from_cache(const char *db
 void flush_tables();
 bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
 char *make_default_log_name(char *buff,const char* log_ext);
+char *make_backup_log_name(char *buff, const char *name, const char* log_ext);
+char *make_default_backupdir(char *buff);
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
 uint fast_alter_partition_table(THD *thd, TABLE *table,
@@ -2045,7 +2050,10 @@ extern bool mysqld_embedded;
 extern bool using_update_log, opt_large_files, server_id_supplied;
 extern bool opt_update_log, opt_bin_log, opt_error_log;
 extern my_bool opt_log, opt_slow_log;
+extern my_bool opt_backup_history_log;
+extern my_bool opt_backup_progress_log;
 extern ulong log_output_options;
+extern ulong log_backup_output_options;
 extern my_bool opt_log_queries_not_using_indexes;
 extern bool opt_disable_networking, opt_skip_show_db;
 extern my_bool opt_character_set_client_handshake;
@@ -2074,11 +2082,15 @@ extern uint opt_large_page_size;
 #endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */
 #ifdef MYSQL_SERVER
 extern char *opt_logname, *opt_slow_logname;
+extern char *opt_backup_history_logname, *opt_backup_progress_logname,
+            *opt_backup_settings_name;
 extern const char *log_output_str;
+extern const char *log_backup_output_str;
 
 extern MYSQL_BIN_LOG mysql_bin_log;
 extern LOGGER logger;
-extern TABLE_LIST general_log, slow_log;
+extern TABLE_LIST general_log, slow_log, 
+       backup_history_log, backup_progress_log;
 extern FILE *bootstrap_file;
 extern int bootstrap_error;
 extern FILE *stderror_file;

=== modified file 'sql/mysqld.cc'
--- sql/mysqld.cc	2008-06-25 14:49:43 +0000
+++ sql/mysqld.cc	2008-06-27 09:53:14 +0000
@@ -427,7 +427,10 @@ static pthread_cond_t COND_thread_cache,
 extern DDL_blocker_class *DDL_blocker;
 bool opt_update_log, opt_bin_log;
 my_bool opt_log, opt_slow_log;
+my_bool opt_backup_history_log;
+my_bool opt_backup_progress_log;
 ulong log_output_options;
+ulong log_backup_output_options;
 my_bool opt_log_queries_not_using_indexes= 0;
 bool opt_error_log= IF_WIN(1,0);
 bool opt_disable_networking=0, opt_skip_show_db=0;
@@ -569,6 +572,7 @@ ulong slow_launch_threads = 0, sync_binl
 ulong expire_logs_days = 0;
 ulong rpl_recovery_rank=0;
 const char *log_output_str= "FILE";
+const char *log_backup_output_str= "TABLE";
 
 const double log_10[] = {
   1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
@@ -713,6 +717,8 @@ char *master_info_file;
 char *relay_log_info_file, *report_user, *report_password, *report_host;
 char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
 char *opt_logname, *opt_slow_logname;
+char *opt_backup_history_logname, *opt_backup_progress_logname,
+     *opt_backup_settings_name;
 
 /* Static variables */
 
@@ -1361,6 +1367,9 @@ void clean_up(bool print_message)
   my_free(sys_init_connect.value, MYF(MY_ALLOW_ZERO_PTR));
   my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR));
   my_free(sys_var_general_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
+  my_free(sys_var_backup_history_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
+  my_free(sys_var_backup_progress_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
+  my_free(sys_var_backupdir.value, MYF(MY_ALLOW_ZERO_PTR));
   my_free(sys_var_slow_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
   free_tmpdir(&mysql_tmpdir_list);
 #ifdef HAVE_REPLICATION
@@ -2866,6 +2875,8 @@ pthread_handler_t signal_hand(void *arg 
       /* switch to the old log message processing */
       logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
                           opt_log ? LOG_FILE:LOG_NONE);
+      logger.set_backup_handlers(opt_backup_history_log ? LOG_FILE : LOG_NONE,
+                                 opt_backup_progress_log ? LOG_FILE : LOG_NONE);
       DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
       if (!abort_loop)
       {
@@ -2883,6 +2894,7 @@ pthread_handler_t signal_hand(void *arg 
       }
       break;
     case SIGHUP:
+    {
       if (!abort_loop)
       {
         bool not_used;
@@ -2906,7 +2918,14 @@ pthread_handler_t signal_hand(void *arg 
                             opt_slow_log ? log_output_options : LOG_NONE,
                             opt_log ? log_output_options : LOG_NONE);
       }
+      if (log_backup_output_options & LOG_NONE)
+        logger.set_backup_handlers(LOG_NONE, LOG_NONE);
+      else
+        logger.set_backup_handlers(
+          opt_backup_history_log ? log_backup_output_options : LOG_NONE,
+          opt_backup_progress_log ? log_backup_output_options : LOG_NONE);
       break;
+    }
 #ifdef USE_ONE_SIGNAL_HAND
     case THR_SERVER_ALARM:
       process_alarm(sig);			// Trigger alarms.
@@ -3543,10 +3562,35 @@ static int init_common_variables(const c
                       "--log-slow-queries option, log tables are used. "
                       "To enable logging to files use the --log-output=file option.");
 
+  if (opt_backup_history_log && opt_backup_history_logname
+     && !(log_backup_output_options & LOG_FILE) && !(log_backup_output_options & LOG_NONE))
+    sql_print_warning("Although a path was specified for the "
+                      "--log-backup-history option, log tables are used. "
+                      "To enable logging to files use the --log-backup-output option.");
+
+  if (opt_backup_progress_log && opt_backup_progress_logname
+     && !(log_backup_output_options & LOG_FILE) && !(log_backup_output_options & LOG_NONE))
+    sql_print_warning("Although a path was specified for the "
+                      "--log-backup-progress option, log tables are used. "
+                      "To enable logging to files use the --log-backup-output option.");
+
   s= opt_logname ? opt_logname : make_default_log_name(buff, ".log");
   sys_var_general_log_path.value= my_strdup(s, MYF(0));
   sys_var_general_log_path.value_length= strlen(s);
 
+  /*
+    Set defaults for history and progress log paths.
+  */
+  s= opt_backup_history_logname ? opt_backup_history_logname : 
+    make_backup_log_name(buff, BACKUP_HISTORY_LOG_NAME.str, ".log");
+  sys_var_backup_history_log_path.value= my_strdup(s, MYF(0));
+  sys_var_backup_history_log_path.value_length= BACKUP_HISTORY_LOG_NAME.length;
+
+  s= opt_backup_progress_logname ? opt_backup_progress_logname : 
+    make_backup_log_name(buff, BACKUP_PROGRESS_LOG_NAME.str, ".log");
+  sys_var_backup_progress_log_path.value= my_strdup(s, MYF(0));
+  sys_var_backup_progress_log_path.value_length= BACKUP_PROGRESS_LOG_NAME.length;
+
   s= opt_slow_logname ? opt_slow_logname : make_default_log_name(buff, "-slow.log");
   sys_var_slow_log_path.value= my_strdup(s, MYF(0));
   sys_var_slow_log_path.value_length= strlen(s);
@@ -4062,7 +4106,10 @@ server.");
 
 #ifdef WITH_CSV_STORAGE_ENGINE
   if (opt_bootstrap)
+  {
     log_output_options= LOG_FILE;
+    log_backup_output_options= LOG_FILE;
+  }
   else
     logger.init_log_tables();
 
@@ -4094,9 +4141,41 @@ server.");
     logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
                         opt_log ? log_output_options:LOG_NONE);
   }
+
+  if (log_backup_output_options & LOG_NONE)
+  {
+    /*
+      Issue a warining if there were specified additional options to the
+      log-backup-output along with NONE. Probably this wasn't what user wanted.
+    */
+    if ((log_backup_output_options & LOG_NONE) && 
+        (log_backup_output_options & ~LOG_NONE))
+      sql_print_warning("There were other values specified to "
+                        "log-backup-output besides NONE. Disabling "
+                        "backup logs anyway.");
+    logger.set_backup_handlers(LOG_NONE, LOG_NONE);
+  }
+  else
+  {
+    /* fall back to the log files if tables are not present */
+    LEX_STRING csv_name={C_STRING_WITH_LEN("csv")};
+    if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
+    {
+      /* purecov: begin inspected */
+      sql_print_error("CSV engine is not present, falling back to the "
+                      "log files");
+      log_backup_output_options= 
+        (log_backup_output_options & ~LOG_TABLE) | LOG_FILE;
+      /* purecov: end */
+    }
+
+    logger.set_backup_handlers(log_backup_output_options,
+      log_backup_output_options);
+  }
 #else
   logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
                       opt_log ? LOG_FILE:LOG_NONE);
+  logger.set_backup_handlers(LOG_FILE, LOG_FILE);
 #endif
 
   /*
@@ -5688,10 +5767,13 @@ enum options_mysqld
   OPT_PLUGIN_LOAD,
   OPT_PLUGIN_DIR,
   OPT_LOG_OUTPUT,
+  OPT_LOG_BACKUP_OUTPUT,
   OPT_PORT_OPEN_TIMEOUT,
   OPT_PROFILING,
   OPT_KEEP_FILES_ON_CREATE,
   OPT_GENERAL_LOG,
+  OPT_BACKUP_HISTORY_LOG,
+  OPT_BACKUP_PROGRESS_LOG,
   OPT_SLOW_LOG,
   OPT_THREAD_HANDLING,
   OPT_INNODB_ROLLBACK_ON_TIMEOUT,
@@ -5745,6 +5827,14 @@ struct my_option my_long_options[] =
    "Creating and dropping stored procedures alters ACLs. Disable with --skip-automatic-sp-privileges.",
    (uchar**) &sp_automatic_privileges, (uchar**) &sp_automatic_privileges,
    0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+  {"backupdir", 'B', "Path used to store backup data.", (uchar**) &sys_var_backupdir.value,
+   (uchar**) &sys_var_backupdir.value, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"backup-history-log", OPT_BACKUP_HISTORY_LOG,
+   "Enable|disable backup history log", (uchar**) &opt_backup_history_log,
+   (uchar**) &opt_backup_history_log, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+  {"backup-progress-log", OPT_BACKUP_PROGRESS_LOG,
+   "Enable|disable backup progress log", (uchar**) &opt_backup_progress_log,
+   (uchar**) &opt_backup_progress_log, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
   {"basedir", 'b',
    "Path to installation directory. All paths are usually resolved relative to this.",
    (uchar**) &mysql_home_ptr, (uchar**) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG,
@@ -5990,6 +6080,11 @@ Disable with --skip-large-pages.",
    "FILE or NONE.",
    (uchar**) &log_output_str, (uchar**) &log_output_str, 0,
    GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+  {"log-backup-output", OPT_LOG_BACKUP_OUTPUT,
+   "Syntax: log-backup-output[=value[,value...]], where \"value\" could be TABLE, "
+   "FILE or NONE.",
+   (uchar**) &log_backup_output_str, (uchar**) &log_backup_output_str, 0,
+   GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 #endif
   {"log-queries-not-using-indexes", OPT_LOG_QUERIES_NOT_USING_INDEXES,
    "Log queries that are executed without benefit of any index to the slow log if it is open.",
@@ -7609,6 +7704,7 @@ static void mysql_init_variables(void)
   opt_log= opt_slow_log= 0;
   opt_update_log= 0;
   log_output_options= find_bit_type(log_output_str, &log_output_typelib);
+  log_backup_output_options= find_bit_type(log_backup_output_str, &log_output_typelib);
   opt_bin_log= 0;
   opt_disable_networking= opt_skip_show_db=0;
   opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
@@ -7695,6 +7791,8 @@ static void mysql_init_variables(void)
   mysql_data_home_buff[1]=0;
   mysql_data_home_len= 2;
 
+  strmake(language, LANGUAGE, sizeof(language)-1);
+ 
   /* Replication parameters */
   master_info_file= (char*) "master.info",
     relay_log_info_file= (char*) "relay-log.info";
@@ -7853,6 +7951,10 @@ mysqld_get_one_option(int optid,
   case 'l':
     opt_log=1;
     break;
+  case 'B':
+    strcpy(sys_var_backupdir.value, argument);
+    sys_var_backupdir.value_length= strlen(sys_var_backupdir.value);
+    break;
   case 'h':
     strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
     /* Correct pointer set by my_getopt (for embedded library) */
@@ -8038,6 +8140,21 @@ mysqld_get_one_option(int optid,
   }
     break;
   }
+  case  OPT_LOG_BACKUP_OUTPUT:
+  {
+    if (!argument || !argument[0])
+    {
+      log_backup_output_options= LOG_FILE;
+      log_backup_output_str= log_output_typelib.type_names[1];
+    }
+    else
+    {
+      log_backup_output_str= argument;
+      log_backup_output_options=
+        find_bit_type_or_exit(argument, &log_output_typelib, opt->name);
+  }
+    break;
+  }
 #endif
   case OPT_EVENT_SCHEDULER:
 #ifndef HAVE_EVENT_SCHEDULER

=== modified file 'sql/set_var.cc'
--- sql/set_var.cc	2008-05-27 19:47:15 +0000
+++ sql/set_var.cc	2008-06-28 10:43:05 +0000
@@ -147,8 +147,15 @@ static uchar *get_tmpdir(THD *thd);
 static int  sys_check_log_path(THD *thd,  set_var *var);
 static bool sys_update_general_log_path(THD *thd, set_var * var);
 static void sys_default_general_log_path(THD *thd, enum_var_type type);
+static bool sys_update_backup_history_log_path(THD *thd, set_var * var);
+static void sys_default_backup_history_log_path(THD *thd, enum_var_type type);
+static bool sys_update_backup_progress_log_path(THD *thd, set_var * var);
+static void sys_default_backup_progress_log_path(THD *thd, enum_var_type type);
 static bool sys_update_slow_log_path(THD *thd, set_var * var);
 static void sys_default_slow_log_path(THD *thd, enum_var_type type);
+static int sys_check_backupdir(THD *thd, set_var *var);
+static bool sys_update_backupdir(THD *thd, set_var * var);
+static void sys_default_backupdir(THD *thd, enum_var_type type);
 
 /*
   Variable definition list
@@ -760,6 +767,12 @@ static sys_var_const_str	sys_license(&va
 /* Global variables which enable|disable logging */
 static sys_var_log_state sys_var_general_log(&vars, "general_log", &opt_log,
                                       QUERY_LOG_GENERAL);
+static sys_var_log_state sys_var_backup_history_log(&vars, "backup_history_log", 
+                                                    &opt_backup_history_log,
+                                                    BACKUP_HISTORY_LOG);
+static sys_var_log_state sys_var_backup_progress_log(&vars, "backup_progress_log",
+                                                     &opt_backup_progress_log,
+                                                     BACKUP_PROGRESS_LOG);
 /* Synonym of "general_log" for consistency with SHOW VARIABLES output */
 static sys_var_log_state sys_var_log(&vars, "log", &opt_log,
                                       QUERY_LOG_GENERAL);
@@ -772,12 +785,39 @@ sys_var_str sys_var_general_log_path(&va
 				     sys_update_general_log_path,
 				     sys_default_general_log_path,
 				     opt_logname);
+/*
+  Added new variables for backup log file paths.
+*/
+sys_var_str sys_var_backup_history_log_path(&vars, "backup_history_log_file", 
+             sys_check_log_path,
+				     sys_update_backup_history_log_path,
+				     sys_default_backup_history_log_path,
+				     opt_logname);
+sys_var_str sys_var_backup_progress_log_path(&vars, "backup_progress_log_file", 
+             sys_check_log_path,
+				     sys_update_backup_progress_log_path,
+				     sys_default_backup_progress_log_path,
+				     opt_logname);
+/*
+  Create the backupdir dynamic variable.
+*/
+sys_var_str sys_var_backupdir(&vars, "backupdir",
+                              sys_check_backupdir,
+                              sys_update_backupdir,
+                              sys_default_backupdir,
+                               0);
+
 sys_var_str sys_var_slow_log_path(&vars, "slow_query_log_file", sys_check_log_path,
 				  sys_update_slow_log_path, 
 				  sys_default_slow_log_path,
 				  opt_slow_logname);
 static sys_var_log_output sys_var_log_output_state(&vars, "log_output", &log_output_options,
 					    &log_output_typelib, 0);
+/*
+  Defines variable for specifying the backup log output.
+*/
+static sys_var_log_backup_output sys_var_log_backup_output_state(&vars, "log_backup_output",
+              &log_backup_output_options, &log_output_typelib, 0);
 
 
 /*
@@ -2411,7 +2451,6 @@ void sys_var_log_state::set_default(THD 
   pthread_mutex_unlock(&LOCK_global_system_variables);
 }
 
-
 static int  sys_check_log_path(THD *thd,  set_var *var)
 {
   char path[FN_REFLEN], buff[FN_REFLEN];
@@ -2477,11 +2516,15 @@ bool update_sys_var_str_path(THD *thd, s
 			     bool log_state, uint log_type)
 {
   MYSQL_QUERY_LOG *file_log;
+  MYSQL_BACKUP_LOG *backup_log;
   char buff[FN_REFLEN];
   char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
   bool result= 0;
   uint str_length= (var ? var->value->str_value.length() : 0);
 
+  /*
+    Added support for backup log types.
+  */
   switch (log_type) {
   case QUERY_LOG_SLOW:
     file_log= logger.get_slow_log_file_handler();
@@ -2489,6 +2532,15 @@ bool update_sys_var_str_path(THD *thd, s
   case QUERY_LOG_GENERAL:
     file_log= logger.get_log_file_handler();
     break;
+  /* 
+    Check the backup logs to update their paths.
+  */
+  case BACKUP_HISTORY_LOG:
+    backup_log= logger.get_backup_history_log_file_handler();
+    break;
+  case BACKUP_PROGRESS_LOG:
+    backup_log= logger.get_backup_progress_log_file_handler();
+    break;
   default:
     assert(0);                                  // Impossible
   }
@@ -2515,6 +2567,9 @@ bool update_sys_var_str_path(THD *thd, s
   my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
   if (file_log && log_state)
   {
+    /*
+      Added support for backup log types.
+    */
     switch (log_type) {
     case QUERY_LOG_SLOW:
       file_log->open_slow_log(sys_var_slow_log_path.value);
@@ -2522,6 +2577,15 @@ bool update_sys_var_str_path(THD *thd, s
     case QUERY_LOG_GENERAL:
       file_log->open_query_log(sys_var_general_log_path.value);
       break;
+    /*
+      Open the backup logs if specified.
+    */
+    case BACKUP_HISTORY_LOG:
+      backup_log->open_backup_history_log(sys_var_backup_history_log_path.value);
+      break;
+    case BACKUP_PROGRESS_LOG:
+      backup_log->open_backup_progress_log(sys_var_backup_progress_log_path.value);
+      break;
     default:
       DBUG_ASSERT(0);
     }
@@ -2549,6 +2613,43 @@ static void sys_default_general_log_path
 }
 
 
+/*
+  Update the backup history log path variable.
+*/
+static bool sys_update_backup_history_log_path(THD *thd, set_var * var)
+{
+  return update_sys_var_str_path(thd, &sys_var_backup_history_log_path, 
+				 var, ".log", opt_log, BACKUP_HISTORY_LOG);
+}
+
+/*
+  Set the default for backup history log path variable.
+*/
+static void sys_default_backup_history_log_path(THD *thd, enum_var_type type)
+{
+  (void) update_sys_var_str_path(thd, &sys_var_backup_history_log_path,
+				 0, ".log", opt_log, BACKUP_HISTORY_LOG);
+}
+
+/*
+  Update the backup progress log path variable.
+*/
+static bool sys_update_backup_progress_log_path(THD *thd, set_var * var)
+{
+  return update_sys_var_str_path(thd, &sys_var_backup_progress_log_path, 
+				 var, ".log", opt_log, BACKUP_PROGRESS_LOG);
+}
+
+/*
+  Set the default for backup progress log path variable.
+*/
+static void sys_default_backup_progress_log_path(THD *thd, enum_var_type type)
+{
+  (void) update_sys_var_str_path(thd, &sys_var_backup_progress_log_path,
+				 0, ".log", opt_log, BACKUP_PROGRESS_LOG);
+}
+
+
 static bool sys_update_slow_log_path(THD *thd, set_var * var)
 {
   return update_sys_var_str_path(thd, &sys_var_slow_log_path,
@@ -2565,6 +2666,81 @@ static void sys_default_slow_log_path(TH
 }
 
 
+static int sys_check_backupdir(THD *thd, set_var *var)
+{
+  char path[FN_REFLEN], buff[FN_REFLEN];
+  MY_STAT f_stat;
+  String str(buff, sizeof(buff), system_charset_info), *res;
+  const char *log_file_str;
+  size_t path_length;
+
+  if (!(res= var->value->val_str(&str)))
+    goto err;
+
+  log_file_str= res->c_ptr();
+  bzero(&f_stat, sizeof(MY_STAT));
+
+  /* Get dirname of the file path. */
+  (void) dirname_part(path, log_file_str, &path_length);
+
+  /* Dirname is empty if file path is relative. */
+  if (!path_length)
+    return 0;
+
+  /*
+    Check if directory exists and we have permission to create file and
+    write to file.
+  */
+  if (my_access(path, (F_OK|W_OK)))
+    goto err;
+
+  return 0;
+
+err:
+  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, 
+           res ? log_file_str : "NULL");
+  return 1;
+}
+
+
+static bool sys_update_backupdir(THD *thd, set_var * var)
+{
+  char buff[FN_REFLEN];
+  char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
+  bool result= 0;
+  uint str_length= (var ? var->value->str_value.length() : 0);
+
+  if (!old_value)
+  {
+    old_value= make_default_backupdir(buff);
+    str_length= strlen(old_value);
+  }
+  if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME))))
+  {
+    result= 1;
+    goto err;
+  }
+
+  pthread_mutex_lock(&LOCK_global_system_variables);
+  logger.lock_exclusive();
+
+  old_value= sys_var_backupdir.value;
+  sys_var_backupdir.value= res;
+  sys_var_backupdir.value_length= str_length;
+  my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
+  logger.unlock();
+  pthread_mutex_unlock(&LOCK_global_system_variables);
+
+err:
+  return result;
+}
+
+static void sys_default_backupdir(THD *thd, enum_var_type type)
+{
+  sys_update_backupdir(thd, 0);
+}
+
+
 bool sys_var_log_output::update(THD *thd, set_var *var)
 {
   pthread_mutex_lock(&LOCK_global_system_variables);
@@ -2614,6 +2790,35 @@ uchar *sys_var_log_output::value_ptr(THD
   return (uchar*) thd->strmake(tmp.ptr(), length);
 }
 
+/*
+  Allow update of the log-backup-output variable.
+*/
+bool sys_var_log_backup_output::update(THD *thd, set_var *var)
+{
+  pthread_mutex_lock(&LOCK_global_system_variables);
+  logger.lock_exclusive();
+  logger.init_backup_history_log(var->save_result.ulong_value);
+  logger.init_backup_progress_log(var->save_result.ulong_value);
+  *value= var->save_result.ulong_value;
+  logger.unlock();
+  pthread_mutex_unlock(&LOCK_global_system_variables);
+  return 0;
+}
+
+/*
+  Set the default for the log-backup-output variable.
+*/
+void sys_var_log_backup_output::set_default(THD *thd, enum_var_type type)
+{
+  pthread_mutex_lock(&LOCK_global_system_variables);
+  logger.lock_exclusive();
+  logger.init_backup_history_log(LOG_TABLE);
+  logger.init_backup_progress_log(LOG_TABLE);
+  *value= LOG_TABLE;
+  logger.unlock();
+  pthread_mutex_unlock(&LOCK_global_system_variables);
+}
+
 
 /*****************************************************************************
   Functions to handle SET NAMES and SET CHARACTER SET

=== modified file 'sql/set_var.h'
--- sql/set_var.h	2008-05-27 19:47:15 +0000
+++ sql/set_var.h	2008-06-28 10:42:14 +0000
@@ -914,6 +914,7 @@ public:
 
 class sys_var_log_output :public sys_var
 {
+protected:
   ulong *value;
   TYPELIB *enum_names;
 public:
@@ -935,6 +936,20 @@ public:
   SHOW_TYPE show_type() { return SHOW_CHAR; }
 };
 
+/*
+  Class used to manage log-backup-output variable.
+*/
+class sys_var_log_backup_output : public sys_var_log_output
+{
+public:
+  sys_var_log_backup_output(sys_var_chain *chain, const char *name_arg, ulong *value_arg,
+                     TYPELIB *typelib, sys_after_update_func func)
+    :sys_var_log_output(chain,name_arg,value_arg,typelib,func)
+  {}
+  bool update(THD *thd, set_var *var);
+  void set_default(THD *thd, enum_var_type type);
+};
+
 
 /* Variable that you can only read from */
 
@@ -1345,7 +1360,9 @@ CHARSET_INFO *get_old_charset_by_name(co
 uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
 		NAMED_LIST **found);
 
-extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path;
+extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path,
+       sys_var_backup_history_log_path, sys_var_backup_progress_log_path,
+       sys_var_backupdir;
 
 /* key_cache functions */
 KEY_CACHE *get_key_cache(LEX_STRING *cache_name);

=== modified file 'sql/share/errmsg.txt'
--- sql/share/errmsg.txt	2008-06-25 13:30:04 +0000
+++ sql/share/errmsg.txt	2008-06-27 09:53:15 +0000
@@ -6246,7 +6246,7 @@ ER_BACKUP_THREAD_INIT
         eng "Backup driver's table locking thread can not be initialized."
 
 ER_BACKUP_PROGRESS_TABLES
-        eng "Can't open the online backup progress tables. Check 'mysql.online_backup' and 'mysql.online_backup_progress'."
+        eng "Can't open the backup log tables. Check 'mysql.backup_history' and 'mysql.backup_progress'."
 
 ER_TABLESPACE_EXIST
   eng "Tablespace '%-.192s' already exists"

=== modified file 'sql/si_objects.cc'
--- sql/si_objects.cc	2008-06-12 19:54:19 +0000
+++ sql/si_objects.cc	2008-06-28 11:30:27 +0000
@@ -25,6 +25,7 @@
 #include "sql_trigger.h"
 #include "sp.h"
 #include "sp_head.h" // for sp_add_to_query_tables().
+#include "log.h"
 
 TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list); // defined in sql_show.cc
 
@@ -1561,6 +1562,87 @@ ObjIterator* get_view_base_views(THD *th
 ///////////////////////////////////////////////////////////////////////////
 
 //
+// Implementation: Obj class.
+//
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Create the object in the database.
+
+  @param[in] thd              Server thread context.
+
+  @return error status.
+    @retval FALSE on success.
+    @retval TRUE on error.
+
+  @note The real work is done inside @c do_execute() primitive which should be
+  defied in derived classes. This method prepares appropriate context and calls
+  the primitive.
+*/
+bool Obj::execute(THD *thd)
+{
+  ulong saved_sql_mode= thd->variables.sql_mode;
+  thd->variables.sql_mode= 0;
+
+  set_var_collation_client saved_charset_settings(
+                             thd->variables.character_set_client,
+                             thd->variables.character_set_results,
+                             thd->variables.collation_connection);
+
+  set_var_collation_client new_charset_settings(::system_charset_info,
+                                                ::system_charset_info,
+                                                ::system_charset_info);
+  new_charset_settings.update(thd);
+
+  bool ret= do_execute(thd);
+
+  saved_charset_settings.update(thd);
+  thd->variables.sql_mode= saved_sql_mode;
+
+  return ret;
+}
+
+/**
+  Serialize object state into a buffer. The buffer actually should be a
+  binary buffer. String class is used here just because we don't have
+  convenient primitive for binary buffers.
+
+  Serialization format is opaque to the client, i.e. the client should
+  not make any assumptions about the format or the content of the
+  returned buffer.
+
+  Serialization format can be changed in the future versions. However,
+  the server must be able to materialize objects coded in any previous
+  formats.
+
+  @param[in] thd              Server thread context.
+  @param[in] serialialization Buffer to serialize the object
+
+  @return error status.
+    @retval FALSE on success.
+    @retval TRUE on error.
+
+  @note The real work is done inside @c do_serialize() primitive which should be
+  defied in derived classes. This method prepares appropriate context and calls
+  the primitive.
+*/
+bool Obj::serialize(THD *thd, String *serialization)
+{
+  ulong saved_sql_mode= thd->variables.sql_mode;
+  thd->variables.sql_mode= 0;
+  
+  bool ret= do_serialize(thd, serialization);
+
+  thd->variables.sql_mode= saved_sql_mode;
+
+  return ret;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+//
 // Implementation: DatabaseObj class.
 //
 
@@ -3102,3 +3184,128 @@ void ddl_blocker_exception_off(THD *thd)
 } // obs namespace
 
 ///////////////////////////////////////////////////////////////////////////
+
+// Implementation: backup logging services
+
+/**
+  Write the backup log entry for the backup history logs.
+
+  This method is a pass-through to allow calling of the logging 
+  functions for the backup history log.
+
+  @param[IN]   thd          The current thread
+  @param[IN]   history_data The data for the row
+  
+  @returns results of logging function (i.e., TRUE if error)
+*/
+bool backup_history_log_write(THD *thd, 
+                              st_backup_history *history_data)
+{
+  /* Write the message to the log if we want to log this king of commands */
+  return logger.backup_history_log_write(thd, history_data);
+}
+
+/**
+  Write the backup log entry for the backup progress log.
+
+  This method is a pass-through to allow calling of the logging 
+  functions for the backup history log.
+
+  @param[IN]   thd         The current thread
+  @param[OUT]  backup_id   The new row id for the backup history
+  @param[IN]   object      The name of the object processed
+  @param[IN]   start       Start datetime
+  @param[IN]   stop        Stop datetime
+  @param[IN]   size        Size value
+  @param[IN]   progress    Progress (percent)
+  @param[IN]   error_num   Error number (should be 0 is success)
+  @param[IN]   notes       Misc data from engine
+
+  @returns results of logging function (i.e., TRUE if error)
+*/
+bool backup_progress_log_write(THD *thd,
+                               ulonglong backup_id,
+                               const char *object,
+                               time_t start,
+                               time_t stop,
+                               longlong size,
+                               longlong progress,
+                               int error_num,
+                               const char *notes)
+{
+  /* Write the message to the log if we want to log this king of commands */
+  return logger.backup_progress_log_write(thd, backup_id, object, start,
+                                          stop, size, progress, error_num, notes);
+}
+
+/**
+  Generate the next backup id from backup logs.
+  
+  @todo Do we need a mutex to protect this call internally?
+*/
+ulonglong generate_backup_id()
+{
+  MYSQL_BACKUP_LOG *bl= logger.get_backup_history_log_file_handler();
+
+  // TODO: Decide what to do if we are logging to table, not a file
+  if (!bl)
+    return 1;
+
+  // TODO: Check if backup log is opened and in good shape
+
+  return bl->generate_backup_id();
+}
+
+/**
+  Check backup history logs.
+  
+  This method attempts to open the backup logs. It returns
+  an error if either log is not present or cannot be opened.
+
+  @param[in] THD * The current thread.
+
+  @returns Information whether backup logs can be used.
+
+  @retval FALSE  success
+  @retval TRUE  failed to open one of the logs
+*/
+my_bool check_backup_logs(THD *thd)
+{
+  TABLE_LIST tables;
+  my_bool ret= FALSE;
+
+  DBUG_ENTER("check_backup_logs");
+
+  /*
+     ADD TO THIS AREA!!!
+     CHECK TO SEE IF LOG TO TABLE OR LOG TO FILE! 
+     ONLY DO CHECK IF WE ARE LOGGING TO TABLE!
+  */
+
+  // TODO: remove fixed names - use abstraction provided by MYSQL_BACKUP_LOG
+  // Perhaps define MYSQL_BACKUP_LOG::check_logs() and call it here.
+
+  /* Check mysql.backup_history */
+  tables.init_one_table("mysql", "backup_history", TL_READ);
+  if (simple_open_n_lock_tables(thd, &tables))
+  {
+    ret= TRUE;
+    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
+    DBUG_RETURN(ret);
+  }
+  close_thread_tables(thd);
+
+  /* Check mysql.backup_progress */
+  tables.init_one_table("mysql", "backup_progress", TL_READ);
+  if (simple_open_n_lock_tables(thd, &tables))
+  {
+    ret= TRUE;
+    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
+    DBUG_RETURN(ret);
+  }
+  close_thread_tables(thd);
+  DBUG_RETURN(ret);
+}
+
+
+///////////////////////////////////////////////////////////////////////////

=== modified file 'sql/si_objects.h'
--- sql/si_objects.h	2008-05-05 15:03:24 +0000
+++ sql/si_objects.h	2008-06-28 11:32:16 +0000
@@ -118,80 +118,6 @@ private:
 };
 
 
-/**
-  Create the object in the database.
-
-  @param[in] thd              Server thread context.
-
-  @return error status.
-    @retval FALSE on success.
-    @retval TRUE on error.
-
-  @note The real work is done inside @c do_execute() primitive which should be
-  defied in derived classes. This method prepares appropriate context and calls
-  the primitive.
-*/
-inline
-bool Obj::execute(THD *thd)
-{
-  ulong saved_sql_mode= thd->variables.sql_mode;
-  thd->variables.sql_mode= 0;
-
-  set_var_collation_client saved_charset_settings(
-                             thd->variables.character_set_client,
-                             thd->variables.character_set_results,
-                             thd->variables.collation_connection);
-
-  set_var_collation_client new_charset_settings(::system_charset_info,
-                                                ::system_charset_info,
-                                                ::system_charset_info);
-  new_charset_settings.update(thd);
-
-  bool ret= do_execute(thd);
-
-  saved_charset_settings.update(thd);
-  thd->variables.sql_mode= saved_sql_mode;
-
-  return ret;
-}
-
-/**
-  Serialize object state into a buffer. The buffer actually should be a
-  binary buffer. String class is used here just because we don't have
-  convenient primitive for binary buffers.
-
-  Serialization format is opaque to the client, i.e. the client should
-  not make any assumptions about the format or the content of the
-  returned buffer.
-
-  Serialization format can be changed in the future versions. However,
-  the server must be able to materialize objects coded in any previous
-  formats.
-
-  @param[in] thd              Server thread context.
-  @param[in] serialialization Buffer to serialize the object
-
-  @return error status.
-    @retval FALSE on success.
-    @retval TRUE on error.
-
-  @note The real work is done inside @c do_serialize() primitive which should be
-  defied in derived classes. This method prepares appropriate context and calls
-  the primitive.
-*/
-inline
-bool Obj::serialize(THD *thd, String *serialization)
-{
-  ulong saved_sql_mode= thd->variables.sql_mode;
-  thd->variables.sql_mode= 0;
-  
-  bool ret= do_serialize(thd, serialization);
-
-  thd->variables.sql_mode= saved_sql_mode;
-
-  return ret;
-}
-
 ///////////////////////////////////////////////////////////////////////////
 
 /**
@@ -606,4 +532,78 @@ COND *create_db_select_condition(THD *th
 
 } // obs namespace
 
+
+///////////////////////////////////////////////////////////////////////////
+
+//
+//  Backup logging services.
+//
+
+// TODO: move it to a separate header file, e.g., si_other.h
+
+/**
+  List of states for online backup table.
+*/
+enum enum_backup_state
+{
+  BUP_UNKNOWN = 0,
+  BUP_COMPLETE,
+  BUP_STARTING,
+  BUP_VALIDITY_POINT,
+  BUP_RUNNING,
+  BUP_ERRORS,
+  BUP_CANCEL
+};
+
+/**
+  List of operations for online backup table.
+*/
+enum enum_backup_operation
+{
+  OP_BACKUP = 1,
+  OP_RESTORE,
+  OP_SHOW,
+  OP_OTHER
+};
+
+/**
+  Structure for holding backup history data.
+*/
+struct st_backup_history
+{
+  ulonglong backup_id;             ///< the id for this row in the log
+  uint process_id;                  ///< the process id of the backup/restore
+  enum_backup_state state;         ///< current state of the operaiont
+  enum_backup_operation operation; ///< the type of operation (backup, restore)
+  int error_num;                   ///< error number
+  const char *user_comment;              ///< user comment from command
+  const char *backup_file;               ///< the backup image file
+  const char *command;                   ///< the command used
+  ulong binlog_pos;                  ///< position in the binary log
+  const char *binlog_file;               ///< the name of the binary log file
+  ulong num_objects;                 ///< number of objects in backup
+  ulonglong size;                   ///< total size of the backup image file
+  time_t start;                    ///< start time of operation
+  time_t stop;                     ///< stop time of operation
+  time_t vp_time;                  ///< point in time validation was assured
+  const char *engine_name;               ///< list of backup engines used
+};
+
+
+bool backup_history_log_write(THD *thd, 
+                              st_backup_history *history_data);
+
+bool backup_progress_log_write(THD *thd,
+                               ulonglong backup_id,
+                               const char *object,
+                               time_t start,
+                               time_t stop,
+                               longlong size,
+                               longlong progress,
+                               int error_num,
+                               const char *notes);
+
+ulonglong generate_backup_id();
+my_bool check_backup_logs(THD *thd);
+
 #endif // SI_OBJECTS_H_

=== modified file 'sql/sql_parse.cc'
--- sql/sql_parse.cc	2008-06-04 13:20:03 +0000
+++ sql/sql_parse.cc	2008-06-27 09:53:15 +0000
@@ -6669,6 +6669,13 @@ bool reload_acl_and_cache(THD *thd, ulon
     if (flush_error_log())
       result=1;
   }
+  /*
+    Added support for flushing backup logs.
+  */
+  if (options & REFRESH_BACKUP_LOG)
+  {
+    logger.flush_backup_logs(thd);
+  }
 #ifdef HAVE_QUERY_CACHE
   if (options & REFRESH_QUERY_CACHE_FREE)
   {

=== modified file 'sql/sql_yacc.yy'
--- sql/sql_yacc.yy	2008-06-26 10:38:48 +0000
+++ sql/sql_yacc.yy	2008-06-27 09:53:15 +0000
@@ -9994,6 +9994,8 @@ flush_option:
           { Lex->type|= REFRESH_GRANT; }
         | LOGS_SYM
           { Lex->type|= REFRESH_LOG; }
+        | BACKUP_SYM LOGS_SYM
+          { Lex->type|= REFRESH_BACKUP_LOG; }
         | STATUS_SYM
           { Lex->type|= REFRESH_STATUS; }
         | SLAVE

=== modified file 'sql/table.cc'
--- sql/table.cc	2008-05-08 16:01:15 +0000
+++ sql/table.cc	2008-06-27 09:53:15 +0000
@@ -33,9 +33,20 @@ LEX_STRING GENERAL_LOG_NAME= {C_STRING_W
 /* SLOW_LOG name */
 LEX_STRING SLOW_LOG_NAME= {C_STRING_WITH_LEN("slow_log")};
 
+/* BACKUP_HISTORY_LOG name */
+LEX_STRING BACKUP_HISTORY_LOG_NAME= {C_STRING_WITH_LEN("backup_history")};
+
+/* BACKUP_PROGRESS_LOG name */
+LEX_STRING BACKUP_PROGRESS_LOG_NAME= {C_STRING_WITH_LEN("backup_progress")};
+
+/* BACKUP_SETTINGS name */
+LEX_STRING BACKUP_SETTINGS_NAME= {C_STRING_WITH_LEN("backup_settings")};
+
+
 #ifndef EMBEDDED_LIBRARY
 extern LEX_STRING BACKUP_HISTORY_LOG_NAME;
 extern LEX_STRING BACKUP_PROGRESS_LOG_NAME;
+extern LEX_STRING BACKUP_SETTINGS_NAME;
 #endif
 
 	/* Functions defined in this file */
@@ -251,6 +262,30 @@ TABLE_CATEGORY get_table_category(const 
       return TABLE_CATEGORY_PERFORMANCE;
     }
 
+    if ((name->length == BACKUP_HISTORY_LOG_NAME.length) &&
+        (my_strcasecmp(system_charset_info,
+                      BACKUP_HISTORY_LOG_NAME.str,
+                      name->str) == 0))
+    {
+      return TABLE_CATEGORY_PERFORMANCE;
+    }
+
+    if ((name->length == BACKUP_PROGRESS_LOG_NAME.length) &&
+        (my_strcasecmp(system_charset_info,
+                      BACKUP_PROGRESS_LOG_NAME.str,
+                      name->str) == 0))
+    {
+      return TABLE_CATEGORY_PERFORMANCE;
+    }
+
+    if ((name->length == BACKUP_SETTINGS_NAME.length) &&
+        (my_strcasecmp(system_charset_info,
+                      BACKUP_SETTINGS_NAME.str,
+                      name->str) == 0))
+    {
+      return TABLE_CATEGORY_PERFORMANCE;
+    }
+
 #ifndef EMBEDDED_LIBRARY
     if ((name->length == BACKUP_HISTORY_LOG_NAME.length) &&
         (my_strcasecmp(system_charset_info,

=== modified file 'sql/unireg.h'
--- sql/unireg.h	2008-04-30 16:16:45 +0000
+++ sql/unireg.h	2008-06-27 09:53:15 +0000
@@ -32,6 +32,9 @@
 #ifndef DATADIR
 #define DATADIR		"data/"
 #endif
+#ifndef BACKUPDIR
+#define BACKUPDIR		"data/"
+#endif
 #ifndef SHAREDIR
 #define SHAREDIR	"share/"
 #endif

--- mysql_priv.h.~1~	2008-06-27 11:52:27.000000000 +0200
+++ mysql_priv.h	2008-06-28 14:24:14.585924688 +0200
@@ -901,111 +901,6 @@ int end_trans(THD *thd, enum enum_mysql_
 Item *negate_expression(THD *thd, Item *expr);
 
 /* log.cc */
-
-/**
-  List of fields for online backup table.
-*/
-enum enum_backup_history_table_field
-{
-  ET_OBH_FIELD_BACKUP_ID = 0, /* start from 0 to correspond with field array */
-  ET_OBH_FIELD_PROCESS_ID,
-  ET_OBH_FIELD_BINLOG_POS,
-  ET_OBH_FIELD_BINLOG_FILE,
-  ET_OBH_FIELD_BACKUP_STATE,
-  ET_OBH_FIELD_OPER,
-  ET_OBH_FIELD_ERROR_NUM,
-  ET_OBH_FIELD_NUM_OBJ,
-  ET_OBH_FIELD_TOTAL_BYTES,
-  ET_OBH_FIELD_VP,
-  ET_OBH_FIELD_START_TIME,
-  ET_OBH_FIELD_STOP_TIME,
-  ET_OBH_FIELD_HOST_OR_SERVER,
-  ET_OBH_FIELD_USERNAME,
-  ET_OBH_FIELD_BACKUP_FILE,
-  ET_OBH_FIELD_COMMENT,
-  ET_OBH_FIELD_COMMAND,
-  ET_OBH_FIELD_DRIVERS,
-  ET_OBH_FIELD_COUNT /* a cool trick to count the number of fields  :)  */
-};
-
-/**
-  List of fields for online backup progress table.
-*/
-enum enum_backup_progress_table_field
-{
-  ET_OBP_FIELD_BACKUP_ID_FK = 0, /* start from 0 to correspond with field array */
-  ET_OBP_FIELD_PROG_OBJECT,
-  ET_OBP_FIELD_PROG_START_TIME,
-  ET_OBP_FIELD_PROG_STOP_TIME,
-  ET_OBP_FIELD_PROG_SIZE,
-  ET_OBP_FIELD_PROGRESS,
-  ET_OBP_FIELD_PROG_ERROR_NUM,
-  ET_OBP_FIELD_PROG_NOTES,
-  ET_OBP_FIELD_PROG_COUNT /* a cool trick to count the number of fields  :)  */
-};
-
-/**
-  List of states for online backup table.
-*/
-enum enum_backup_state
-{
-  BUP_UNKNOWN = 0,
-  BUP_COMPLETE,
-  BUP_STARTING,
-  BUP_VALIDITY_POINT,
-  BUP_RUNNING,
-  BUP_ERRORS,
-  BUP_CANCEL
-};
-
-/**
-  List of operations for online backup table.
-*/
-enum enum_backup_operation
-{
-  OP_BACKUP = 1,
-  OP_RESTORE,
-  OP_SHOW,
-  OP_OTHER
-};
-
-/**
-  Structure for holding backup history data.
-*/
-struct st_backup_history
-{
-  ulonglong backup_id;             ///< the id for this row in the log
-	int process_id;                  ///< the process id of the backup/restore
-	enum_backup_state state;         ///< current state of the operaiont
-	enum_backup_operation operation; ///< the type of operation (backup, restore)
-	int error_num;                   ///< error number
-	char *user_comment;              ///< user comment from command
-	char *backup_file;               ///< the backup image file
-	char *command;                   ///< the command used
-  int binlog_pos;                  ///< position in the binary log
-  char *binlog_file;               ///< the name of the binary log file
-  int num_objects;                 ///< number of objects in backup
-  longlong size;                   ///< total size of the backup image file
-  time_t start;                    ///< start time of operation
-	time_t stop;                     ///< stop time of operation
-  time_t vp_time;                  ///< point in time validation was assured
-  char *engine_name;               ///< list of backup engines used
-};
-
-
-bool backup_history_log_write(THD *thd, 
-                              st_backup_history *history_data);
-
-bool backup_progress_log_write(THD *thd,
-                               ulonglong backup_id,
-                               const char *object,
-                               time_t start,
-                               time_t stop,
-                               longlong size,
-                               longlong progress,
-                               int error_num,
-                               const char *notes);
-
 int vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
 void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
 void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
--- log.h.~1~	2008-06-27 11:52:27.000000000 +0200
+++ log.h	2008-06-28 14:30:07.670579384 +0200
@@ -16,6 +16,8 @@
 #ifndef LOG_H
 #define LOG_H
 
+#include <si_objects.h> // For backup log types
+
 class Relay_log_info;
 
 class Format_description_log_event;
@@ -251,6 +253,7 @@ public:
     return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
                 WRITE_CACHE, FALSE);
   }
+  ulonglong generate_backup_id();
 
 private:
   bool write_int(ulonglong num);
@@ -505,7 +508,6 @@ public:
                                    const char *notes);
 
   int activate_log(THD *thd, uint log_type);
-
 };
 
 
--- log.cc.~1~	2008-06-27 11:52:27.000000000 +0200
+++ log.cc	2008-06-28 13:06:42.018528600 +0200
@@ -762,6 +762,48 @@ int Log_to_csv_event_handler::
 }
 
 /**
+  List of fields for online backup table.
+*/
+enum enum_backup_history_table_field
+{
+  ET_OBH_FIELD_BACKUP_ID = 0, /* start from 0 to correspond with field array */
+  ET_OBH_FIELD_PROCESS_ID,
+  ET_OBH_FIELD_BINLOG_POS,
+  ET_OBH_FIELD_BINLOG_FILE,
+  ET_OBH_FIELD_BACKUP_STATE,
+  ET_OBH_FIELD_OPER,
+  ET_OBH_FIELD_ERROR_NUM,
+  ET_OBH_FIELD_NUM_OBJ,
+  ET_OBH_FIELD_TOTAL_BYTES,
+  ET_OBH_FIELD_VP,
+  ET_OBH_FIELD_START_TIME,
+  ET_OBH_FIELD_STOP_TIME,
+  ET_OBH_FIELD_HOST_OR_SERVER,
+  ET_OBH_FIELD_USERNAME,
+  ET_OBH_FIELD_BACKUP_FILE,
+  ET_OBH_FIELD_COMMENT,
+  ET_OBH_FIELD_COMMAND,
+  ET_OBH_FIELD_DRIVERS,
+  ET_OBH_FIELD_COUNT /* a cool trick to count the number of fields  :)  */
+};
+
+/**
+  List of fields for online backup progress table.
+*/
+enum enum_backup_progress_table_field
+{
+  ET_OBP_FIELD_BACKUP_ID_FK = 0, /* start from 0 to correspond with field array */
+  ET_OBP_FIELD_PROG_OBJECT,
+  ET_OBP_FIELD_PROG_START_TIME,
+  ET_OBP_FIELD_PROG_STOP_TIME,
+  ET_OBP_FIELD_PROG_SIZE,
+  ET_OBP_FIELD_PROGRESS,
+  ET_OBP_FIELD_PROG_ERROR_NUM,
+  ET_OBP_FIELD_PROG_NOTES,
+  ET_OBP_FIELD_PROG_COUNT /* a cool trick to count the number of fields  :)  */
+};
+
+/**
   Write the backup log entry for the backup history log to a table.
 
   This method creates a new row in the backup history log with the
@@ -1976,6 +2018,7 @@ int LOGGER::set_handlers(uint error_log_
 
   @returns 0
 */
+
 int LOGGER::set_backup_handlers(uint backup_history_log_printer,
                                 uint backup_progress_log_printer)
 {
@@ -3406,7 +3449,6 @@ err:
   return TRUE;
 }
 
-
 /**
   Reopen the log file.
 
@@ -3443,6 +3485,32 @@ void MYSQL_BACKUP_LOG::reopen_file(bool 
   DBUG_VOID_RETURN;
 }
 
+/**
+  Generate the next backup id.
+  
+  Since autoincrement columns are not permitted in CSV files, an alternative 
+  mechanism has been developed to create monotonically increasing values. When 
+  a server that does not have any logs written (no backup logs), the system 
+  starts at backup_id = 0. This value is stored in a binary file in the data 
+  directory named backup_settings.obx. Each time a new backup_id is needed, 
+  this value is read, incremented, then the file rewritten. This ensures a 
+  monotonically increasing backup_id. If the backup logs exist and the 
+  backup_settings.obx file does not, the system uses the backup log file size 
+  as the starting backup_id. 
+
+  @todo Do we need a mutex to protect this call internally?
+*/
+ulonglong MYSQL_BACKUP_LOG::generate_backup_id()
+{
+  // TODO: Check if backup log is opened and in good shape
+  MY_STAT fstate;
+
+  my_stat(log_file_name, &fstate, MYF(0)); 
+  //my_fstat(log_file.file, &fstate, MYF(0)); // alternative - use already opened fd
+
+  return fstate.st_size+1;  
+}
+
 
 /**
   @todo
@@ -5199,58 +5267,6 @@ bool general_log_write(THD *thd, enum en
   return FALSE;
 }
 
-
-/**
-  Write the backup log entry for the backup history logs.
-
-  This method is a pass-through to allow calling of the logging 
-  functions for the backup history log.
-
-  @param[IN]   thd          The current thread
-  @param[IN]   history_data The data for the row
-  
-  @returns results of logging function (i.e., TRUE if error)
-*/
-bool backup_history_log_write(THD *thd, 
-                              st_backup_history *history_data)
-{
-  /* Write the message to the log if we want to log this king of commands */
-  return logger.backup_history_log_write(thd, history_data);
-}
-
-/**
-  Write the backup log entry for the backup progress log.
-
-  This method is a pass-through to allow calling of the logging 
-  functions for the backup history log.
-
-  @param[IN]   thd         The current thread
-  @param[OUT]  backup_id   The new row id for the backup history
-  @param[IN]   object      The name of the object processed
-  @param[IN]   start       Start datetime
-  @param[IN]   stop        Stop datetime
-  @param[IN]   size        Size value
-  @param[IN]   progress    Progress (percent)
-  @param[IN]   error_num   Error number (should be 0 is success)
-  @param[IN]   notes       Misc data from engine
-
-  @returns results of logging function (i.e., TRUE if error)
-*/
-bool backup_progress_log_write(THD *thd,
-                               ulonglong backup_id,
-                               const char *object,
-                               time_t start,
-                               time_t stop,
-                               longlong size,
-                               longlong progress,
-                               int error_num,
-                               const char *notes)
-{
-  /* Write the message to the log if we want to log this king of commands */
-  return logger.backup_progress_log_write(thd, backup_id, object, start,
-                                          stop, size, progress, error_num, notes);
-}
-
 void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
 {
   if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
--- set_var.h.~1~	2008-06-27 11:52:27.000000000 +0200
+++ set_var.h	2008-06-28 12:42:14.190188248 +0200
@@ -914,6 +914,7 @@ public:
 
 class sys_var_log_output :public sys_var
 {
+protected:
   ulong *value;
   TYPELIB *enum_names;
 public:
@@ -938,27 +939,15 @@ public:
 /*
   Class used to manage log-backup-output variable.
 */
-class sys_var_log_backup_output : public sys_var
+class sys_var_log_backup_output : public sys_var_log_output
 {
-  ulong *value;
-  TYPELIB *enum_names;
 public:
   sys_var_log_backup_output(sys_var_chain *chain, const char *name_arg, ulong *value_arg,
                      TYPELIB *typelib, sys_after_update_func func)
-    :sys_var(name_arg,func), value(value_arg), enum_names(typelib)
-  {
-    chain_sys_var(chain);
-    set_allow_empty_value(FALSE);
-  }
-  virtual bool check(THD *thd, set_var *var)
-  {
-    return check_set(thd, var, enum_names);
-  }
+    :sys_var_log_output(chain,name_arg,value_arg,typelib,func)
+  {}
   bool update(THD *thd, set_var *var);
-  uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
-  bool check_update_type(Item_result type) { return 0; }
   void set_default(THD *thd, enum_var_type type);
-  SHOW_TYPE show_type() { return SHOW_CHAR; }
 };
 
 
--- si_objects.h.~1~	2008-06-24 13:24:20.000000000 +0200
+++ si_objects.h	2008-06-28 13:32:16.472713672 +0200
@@ -118,80 +118,6 @@ private:
 };
 
 
-/**
-  Create the object in the database.
-
-  @param[in] thd              Server thread context.
-
-  @return error status.
-    @retval FALSE on success.
-    @retval TRUE on error.
-
-  @note The real work is done inside @c do_execute() primitive which should be
-  defied in derived classes. This method prepares appropriate context and calls
-  the primitive.
-*/
-inline
-bool Obj::execute(THD *thd)
-{
-  ulong saved_sql_mode= thd->variables.sql_mode;
-  thd->variables.sql_mode= 0;
-
-  set_var_collation_client saved_charset_settings(
-                             thd->variables.character_set_client,
-                             thd->variables.character_set_results,
-                             thd->variables.collation_connection);
-
-  set_var_collation_client new_charset_settings(::system_charset_info,
-                                                ::system_charset_info,
-                                                ::system_charset_info);
-  new_charset_settings.update(thd);
-
-  bool ret= do_execute(thd);
-
-  saved_charset_settings.update(thd);
-  thd->variables.sql_mode= saved_sql_mode;
-
-  return ret;
-}
-
-/**
-  Serialize object state into a buffer. The buffer actually should be a
-  binary buffer. String class is used here just because we don't have
-  convenient primitive for binary buffers.
-
-  Serialization format is opaque to the client, i.e. the client should
-  not make any assumptions about the format or the content of the
-  returned buffer.
-
-  Serialization format can be changed in the future versions. However,
-  the server must be able to materialize objects coded in any previous
-  formats.
-
-  @param[in] thd              Server thread context.
-  @param[in] serialialization Buffer to serialize the object
-
-  @return error status.
-    @retval FALSE on success.
-    @retval TRUE on error.
-
-  @note The real work is done inside @c do_serialize() primitive which should be
-  defied in derived classes. This method prepares appropriate context and calls
-  the primitive.
-*/
-inline
-bool Obj::serialize(THD *thd, String *serialization)
-{
-  ulong saved_sql_mode= thd->variables.sql_mode;
-  thd->variables.sql_mode= 0;
-  
-  bool ret= do_serialize(thd, serialization);
-
-  thd->variables.sql_mode= saved_sql_mode;
-
-  return ret;
-}
-
 ///////////////////////////////////////////////////////////////////////////
 
 /**
@@ -604,38 +530,80 @@ COND *create_db_select_condition(THD *th
                                  TABLE *t,
                                  List<LEX_STRING> *db_list);
 
-/*
-  The following class is used to manage name locks on a list of tables.
+} // obs namespace
+
+
+///////////////////////////////////////////////////////////////////////////
+
+//
+//  Backup logging services.
+//
 
-  This class uses a list of type List<Obj> to establish the table list 
-  that will be used to manage locks on the tables.
+// TODO: move it to a separate header file, e.g., si_other.h
+
+/**
+  List of states for online backup table.
 */
-class Name_locker
+enum enum_backup_state
 {
-public:
-  Name_locker(THD *thd) { m_thd= thd; }
-  ~Name_locker() { my_free(m_table_list, MYF(0)); }
+  BUP_UNKNOWN = 0,
+  BUP_COMPLETE,
+  BUP_STARTING,
+  BUP_VALIDITY_POINT,
+  BUP_RUNNING,
+  BUP_ERRORS,
+  BUP_CANCEL
+};
 
-  /*
-    Gets name locks on table list.
-  */
-  int get_name_locks(List<Obj> *tables, thr_lock_type lock);
+/**
+  List of operations for online backup table.
+*/
+enum enum_backup_operation
+{
+  OP_BACKUP = 1,
+  OP_RESTORE,
+  OP_SHOW,
+  OP_OTHER
+};
 
-  /*
-    Releases name locks on table list.
-  */
-  int release_name_locks();
+/**
+  Structure for holding backup history data.
+*/
+struct st_backup_history
+{
+  ulonglong backup_id;             ///< the id for this row in the log
+  uint process_id;                  ///< the process id of the backup/restore
+  enum_backup_state state;         ///< current state of the operaiont
+  enum_backup_operation operation; ///< the type of operation (backup, restore)
+  int error_num;                   ///< error number
+  const char *user_comment;              ///< user comment from command
+  const char *backup_file;               ///< the backup image file
+  const char *command;                   ///< the command used
+  ulong binlog_pos;                  ///< position in the binary log
+  const char *binlog_file;               ///< the name of the binary log file
+  ulong num_objects;                 ///< number of objects in backup
+  ulonglong size;                   ///< total size of the backup image file
+  time_t start;                    ///< start time of operation
+  time_t stop;                     ///< stop time of operation
+  time_t vp_time;                  ///< point in time validation was assured
+  const char *engine_name;               ///< list of backup engines used
+};
 
-private:
-  TABLE_LIST *m_table_list; ///< The list of tables to obtain locks on.
-  THD *m_thd;               ///< Thread context.
 
-  /*
-    Builds a table list from the list of objects passed to constructor.
-  */
-  TABLE_LIST *build_table_list(List<Obj> *tables, thr_lock_type lock);
-};
+bool backup_history_log_write(THD *thd, 
+                              st_backup_history *history_data);
 
-} // obs namespace
+bool backup_progress_log_write(THD *thd,
+                               ulonglong backup_id,
+                               const char *object,
+                               time_t start,
+                               time_t stop,
+                               longlong size,
+                               longlong progress,
+                               int error_num,
+                               const char *notes);
+
+ulonglong generate_backup_id();
+my_bool check_backup_logs(THD *thd);
 
 #endif // SI_OBJECTS_H_
--- si_objects.cc.~1~	2008-06-24 13:24:20.000000000 +0200
+++ si_objects.cc	2008-06-28 13:30:27.006836816 +0200
@@ -25,6 +25,7 @@
 #include "sql_trigger.h"
 #include "sp.h"
 #include "sp_head.h" // for sp_add_to_query_tables().
+#include "log.h"
 
 TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list); // defined in sql_show.cc
 
@@ -1561,6 +1562,87 @@ ObjIterator* get_view_base_views(THD *th
 ///////////////////////////////////////////////////////////////////////////
 
 //
+// Implementation: Obj class.
+//
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Create the object in the database.
+
+  @param[in] thd              Server thread context.
+
+  @return error status.
+    @retval FALSE on success.
+    @retval TRUE on error.
+
+  @note The real work is done inside @c do_execute() primitive which should be
+  defied in derived classes. This method prepares appropriate context and calls
+  the primitive.
+*/
+bool Obj::execute(THD *thd)
+{
+  ulong saved_sql_mode= thd->variables.sql_mode;
+  thd->variables.sql_mode= 0;
+
+  set_var_collation_client saved_charset_settings(
+                             thd->variables.character_set_client,
+                             thd->variables.character_set_results,
+                             thd->variables.collation_connection);
+
+  set_var_collation_client new_charset_settings(::system_charset_info,
+                                                ::system_charset_info,
+                                                ::system_charset_info);
+  new_charset_settings.update(thd);
+
+  bool ret= do_execute(thd);
+
+  saved_charset_settings.update(thd);
+  thd->variables.sql_mode= saved_sql_mode;
+
+  return ret;
+}
+
+/**
+  Serialize object state into a buffer. The buffer actually should be a
+  binary buffer. String class is used here just because we don't have
+  convenient primitive for binary buffers.
+
+  Serialization format is opaque to the client, i.e. the client should
+  not make any assumptions about the format or the content of the
+  returned buffer.
+
+  Serialization format can be changed in the future versions. However,
+  the server must be able to materialize objects coded in any previous
+  formats.
+
+  @param[in] thd              Server thread context.
+  @param[in] serialialization Buffer to serialize the object
+
+  @return error status.
+    @retval FALSE on success.
+    @retval TRUE on error.
+
+  @note The real work is done inside @c do_serialize() primitive which should be
+  defied in derived classes. This method prepares appropriate context and calls
+  the primitive.
+*/
+bool Obj::serialize(THD *thd, String *serialization)
+{
+  ulong saved_sql_mode= thd->variables.sql_mode;
+  thd->variables.sql_mode= 0;
+  
+  bool ret= do_serialize(thd, serialization);
+
+  thd->variables.sql_mode= saved_sql_mode;
+
+  return ret;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+//
 // Implementation: DatabaseObj class.
 //
 
@@ -3099,96 +3181,131 @@ void ddl_blocker_exception_off(THD *thd)
   DBUG_VOID_RETURN;
 }
 
+} // obs namespace
+
+///////////////////////////////////////////////////////////////////////////
+
+// Implementation: backup logging services
+
 /**
-  Build a table list from a list of tables as class Obj.
+  Write the backup log entry for the backup history logs.
+
+  This method is a pass-through to allow calling of the logging 
+  functions for the backup history log.
+
+  @param[IN]   thd          The current thread
+  @param[IN]   history_data The data for the row
+  
+  @returns results of logging function (i.e., TRUE if error)
+*/
+bool backup_history_log_write(THD *thd, 
+                              st_backup_history *history_data)
+{
+  /* Write the message to the log if we want to log this king of commands */
+  return logger.backup_history_log_write(thd, history_data);
+}
 
-  This method creates a TABLE_LIST from a List<> of type Obj.
+/**
+  Write the backup log entry for the backup progress log.
 
-  param[IN]  tables    The list of tables
-  param[IN]  lock      The desired lock type
+  This method is a pass-through to allow calling of the logging 
+  functions for the backup history log.
 
-  @returns TABLE_LIST *
+  @param[IN]   thd         The current thread
+  @param[OUT]  backup_id   The new row id for the backup history
+  @param[IN]   object      The name of the object processed
+  @param[IN]   start       Start datetime
+  @param[IN]   stop        Stop datetime
+  @param[IN]   size        Size value
+  @param[IN]   progress    Progress (percent)
+  @param[IN]   error_num   Error number (should be 0 is success)
+  @param[IN]   notes       Misc data from engine
 
-  @note Caller must free memory.
+  @returns results of logging function (i.e., TRUE if error)
 */
-TABLE_LIST *Name_locker::build_table_list(List<Obj> *tables,
-                                          thr_lock_type lock)
+bool backup_progress_log_write(THD *thd,
+                               ulonglong backup_id,
+                               const char *object,
+                               time_t start,
+                               time_t stop,
+                               longlong size,
+                               longlong progress,
+                               int error_num,
+                               const char *notes)
 {
-  TABLE_LIST *tl= NULL;
-  Obj *tbl= NULL;
-  DBUG_ENTER("Name_locker::build_table_list()");
-  
-  List_iterator<Obj> it(*tables);
-  while (tbl= it++)
-  {
-    TABLE_LIST *ptr= (TABLE_LIST*)my_malloc(sizeof(TABLE_LIST), MYF(MY_WME));
-    DBUG_ASSERT(ptr);  // FIXME: report error instead
-    bzero(ptr, sizeof(TABLE_LIST));
+  /* Write the message to the log if we want to log this king of commands */
+  return logger.backup_progress_log_write(thd, backup_id, object, start,
+                                          stop, size, progress, error_num, notes);
+}
 
-    ptr->alias= ptr->table_name= const_cast<char*>(tbl->get_name()->ptr());
-    ptr->db= const_cast<char*>(tbl->get_db_name()->ptr());
-    ptr->lock_type= lock;
+/**
+  Generate the next backup id from backup logs.
+  
+  @todo Do we need a mutex to protect this call internally?
+*/
+ulonglong generate_backup_id()
+{
+  MYSQL_BACKUP_LOG *bl= logger.get_backup_history_log_file_handler();
 
-    // and add it to the list
+  // TODO: Decide what to do if we are logging to table, not a file
+  if (!bl)
+    return 1;
 
-    ptr->next_global= ptr->next_local=
-      ptr->next_name_resolution_table= tl;
-    tl= ptr;
-    tl->table= ptr->table;
-  }
+  // TODO: Check if backup log is opened and in good shape
 
-  DBUG_RETURN(tl);
+  return bl->generate_backup_id();
 }
 
 /**
-  Gets name locks on table list.
+  Check backup history logs.
+  
+  This method attempts to open the backup logs. It returns
+  an error if either log is not present or cannot be opened.
 
-  This method attempts to take an exclusive name lock on each table in the
-  list. It does nothing if the table list is empty.
+  @param[in] THD * The current thread.
 
-  @param[IN] tables  The list of tables to lock.
-  @param[IN] lock    The type of lock to take.
+  @returns Information whether backup logs can be used.
 
-  @returns 0 if success, 1 if error
+  @retval FALSE  success
+  @retval TRUE  failed to open one of the logs
 */
-int Name_locker::get_name_locks(List<Obj> *tables, thr_lock_type lock)
+my_bool check_backup_logs(THD *thd)
 {
-  int ret= 0;
-  DBUG_ENTER("Name_locker::get_name_locks()");
+  TABLE_LIST tables;
+  my_bool ret= FALSE;
+
+  DBUG_ENTER("check_backup_logs");
+
   /*
-    Convert List<Obj> to TABLE_LIST *
+     ADD TO THIS AREA!!!
+     CHECK TO SEE IF LOG TO TABLE OR LOG TO FILE! 
+     ONLY DO CHECK IF WE ARE LOGGING TO TABLE!
   */
-  m_table_list= build_table_list(tables, lock);
-  if (m_table_list)
-  {
-    pthread_mutex_lock(&LOCK_open);
-    if (lock_table_names_exclusively(m_thd, m_table_list))
-      ret= 1;
-    pthread_mutex_unlock(&LOCK_open);
-  }
-  DBUG_RETURN(ret);
-}
 
-/*
-  Releases name locks on table list.
+  // TODO: remove fixed names - use abstraction provided by MYSQL_BACKUP_LOG
+  // Perhaps define MYSQL_BACKUP_LOG::check_logs() and call it here.
 
-  This method releases the name locks on the table list. It does nothing if
-  the table list is empty.
+  /* Check mysql.backup_history */
+  tables.init_one_table("mysql", "backup_history", TL_READ);
+  if (simple_open_n_lock_tables(thd, &tables))
+  {
+    ret= TRUE;
+    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
+    DBUG_RETURN(ret);
+  }
+  close_thread_tables(thd);
 
-  @returns 0 if success, 1 if error
-*/
-int Name_locker::release_name_locks()
-{
-  DBUG_ENTER("Name_locker::release_name_locks()");
-  if (m_table_list)
+  /* Check mysql.backup_progress */
+  tables.init_one_table("mysql", "backup_progress", TL_READ);
+  if (simple_open_n_lock_tables(thd, &tables))
   {
-    pthread_mutex_lock(&LOCK_open);
-    unlock_table_names(m_thd, m_table_list, (TABLE_LIST*) 0);
-    pthread_mutex_unlock(&LOCK_open);
- }
-  DBUG_RETURN(0);
+    ret= TRUE;
+    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
+    DBUG_RETURN(ret);
+  }
+  close_thread_tables(thd);
+  DBUG_RETURN(ret);
 }
 
-} // obs namespace
 
 ///////////////////////////////////////////////////////////////////////////
--- backup/logger.h.~1~	2008-06-27 11:52:27.000000000 +0200
+++ backup/logger.h	2008-06-30 10:01:05.653065304 +0200
@@ -18,13 +18,6 @@ struct log_level {
 
 };
 
-/*
-  This method attempts to open the backup logs. It returns
-  an error if either log is not present or cannot be opened.
-*/
-my_bool check_backup_logs(THD *thd);
-
-extern pthread_mutex_t LOCK_backupid; ///< mutex for backupid generation
 
 class Image_info;
 
@@ -49,10 +42,21 @@ class Logger
 
    enum enum_type { BACKUP, RESTORE } m_type;
    enum { CREATED, READY, RUNNING, DONE } m_state;
+   enum enum_out_destinations {
+     DBUG_TRACE  = 1U<<0,
+     ERROR_LOG   = 1U<<1,
+     ERROR_STACK = 1U<<2,
+     BACKUP_LOG  = 1U<<3,
+   };
 
    Logger(THD*);
    ~Logger();
-   int init(enum_type type, const LEX_STRING path, const char *query);
+   int  set_id(ulonglong id);
+   int  set_op(enum_type op_type, const LEX_STRING path, const char *query);
+
+   int  set_output(uint mask);
+   void dont_output(uint mask);
+   bool output_to(uint mask) const;
 
    int report_error(int error_code, ...);
    int report_error(log_level::value level, int error_code, ...);
@@ -64,33 +68,10 @@ class Logger
    void report_state(enum_backup_state);
    void report_vp_time(time_t);
    void report_binlog_pos(const st_bstream_binlog_pos&);
-   void report_engine(const char*);
+   void report_driver(const char*);
    void report_stats_pre(const Image_info&);
    void report_stats_post(const Image_info&);
    
-   void report_error_to_log(THD *thd, int error_num);
-   void report_num_objects(THD *thd, int num_objects);
-   void report_size(THD *thd, longlong size);
-
-   /*
-     This method inserts a new row in the history log.
-   */
-   int write_history(THD *thd,
-                    st_backup_history *m_op_hist);
-
-   /*  
-     This method inserts a new row in the progress log.
-   */
-	 int write_progress(THD *thd,
-                      st_backup_history *m_op_hist,
-                      const char *object,
-                      time_t start,
-                      time_t stop,
-                      longlong size,
-                      longlong progress,
-                      int error_num,
-                      const char *notes);
-
    void save_errors();
    void stop_save_errors();
    void clear_saved_errors();
@@ -101,35 +82,30 @@ class Logger
   /// Thread in which this logger is used.
   THD *m_thd;
 
-  /**
-    history of the backup or restore operation.
-    
-    This id is used in the backup progress and log tables to identify the
-    operation. Value of @c m_op_hist is meaningful only after a successful 
-    call to @c init(), when @m_state != CREATED.
-   */ 
-  ulonglong m_op_id;
-  st_backup_history *m_op_hist;
+  st_backup_history m_op_hist;
 
   int v_report_error(log_level::value, int, va_list);
   int v_write_message(log_level::value, int, const char*, va_list);
   int write_message(log_level::value level , int error_code, const char *msg);
-	void get_state_string(enum_backup_state state, String *str);
+  const char* get_state_string(enum_backup_state state);
 
  private:
 
-  int cleanup();
-  void get_next_backup_id();
   List<MYSQL_ERROR> errors;  ///< Used to store saved errors.
   bool m_save_errors;        ///< Flag telling if errors should be saved.
-  ulonglong m_next_id;       ///< the next available backup_id
+  uint out_set;              ///< Set of output destinations.
+
+  String drivers;    ///< For storing comma separated list of driver names.
 };
 
 inline
 Logger::Logger(THD *thd) 
   :m_type(BACKUP), m_state(CREATED),
-   m_thd(thd), m_op_id(0), m_op_hist(0), m_save_errors(FALSE), m_next_id(0)
-{}
+   m_thd(thd), m_save_errors(FALSE), out_set(0)
+{
+  bzero(&m_op_hist,sizeof(m_op_hist));
+  m_op_hist.process_id= m_thd->id;
+}
 
 inline
 Logger::~Logger()
@@ -137,30 +113,52 @@ Logger::~Logger()
   clear_saved_errors();
 }
 
+inline
+int Logger::set_id(ulonglong id)
+{
+  m_op_hist.backup_id= id;
+  return 0; // always succeed
+}
+
+inline
+bool Logger::output_to(uint mask) const
+{
+  return out_set & mask;
+}
+
+
 /**
-  Free the memory for the history data.
-*/
+  Setup logger for backup or restore operation.
+    
+  @param[in]  type  type of operation (backup or restore)
+  @param[in]  path  location of the backup image (as specified in BACKUP/RESTORE
+                    command
+  @param[in]  query backup or restore query starting the operation
+  
+  @returns 0 on success, error code otherwise.
+
+  @todo Decide what to do if @c initialize() signals errors.
+  @todo Add code to get the user comment from command.
+*/ 
 inline
-int Logger::cleanup()
+int Logger::set_op(enum_type type, const LEX_STRING path, const char *query)
 {
-  if (m_op_hist)
-  {
-    /*
-    Free memory for strings used
-    */
-    if (m_op_hist->backup_file)
-      delete m_op_hist->backup_file;
-    if (m_op_hist->binlog_file)
-      delete m_op_hist->binlog_file;
-    if (m_op_hist->command)
-      delete m_op_hist->command;
-    if (m_op_hist->engine_name)
-      delete m_op_hist->engine_name;
-    if (m_op_hist->user_comment)
-      delete m_op_hist->user_comment;
-    my_free(m_op_hist, MYF(0));
-    m_op_hist= 0;
-  }
+  if (m_state != CREATED)
+    return 0;
+
+  m_type= type;
+  m_state= READY;
+
+  m_op_hist.operation= type == BACKUP ? OP_BACKUP : OP_RESTORE;
+  m_op_hist.backup_file= path.str;
+  m_op_hist.command= (char*) query; // TODO: change type of m_op_hist.command to const char*
+                                    // so that (char*) cast can be removed.
+  /*
+    Record progress update.
+  */
+  report_state(BUP_STARTING);
+
+  BACKUP_BREAKPOINT("bp_starting_state");
   return 0;
 }
 
@@ -258,8 +256,7 @@ void Logger::report_start(time_t when)
   
   report_error(log_level::INFO, m_type == BACKUP ? ER_BACKUP_BACKUP_START
                                                  : ER_BACKUP_RESTORE_START);  
-  if (when)
-    m_op_hist->start= when;
+  m_op_hist.start= when;
   report_state(BUP_RUNNING);
 }
 
@@ -276,12 +273,12 @@ void Logger::report_stop(time_t when, bo
 
   DBUG_ASSERT(m_state == RUNNING);
 
+  // TODO: report something different in case of error.
+
   report_error(log_level::INFO, m_type == BACKUP ? ER_BACKUP_BACKUP_DONE
                                                  : ER_BACKUP_RESTORE_DONE);  
-  if (when)
-    m_op_hist->stop= when;
+  m_op_hist.stop= when;
   report_state(success ? BUP_COMPLETE : BUP_ERRORS);
-  cleanup();
   m_state= DONE;
 }
 
@@ -297,15 +294,15 @@ void Logger::report_stop(time_t when, bo
 inline
 void Logger::report_state(enum_backup_state state)
 {
-  String str;
-  DBUG_ASSERT(m_state == RUNNING);
+  time_t ts; // TODO: set it to the current time
   
   // TODO: info about state change in the log?
 
-  m_op_hist->state= state;
-  get_state_string(state, &str);
-  write_progress(m_thd, m_op_hist, "backup kernel", 0, 
-                     0, 0, 0, 0, str.c_ptr());
+  m_op_hist.state= state;
+
+  if (output_to(BACKUP_LOG))
+    backup_progress_log_write(m_thd, m_op_hist.backup_id, "backup kernel", ts, ts, 
+                              0, 0, 0, get_state_string(state));
 }
 
 /// Report validity point creation time.
@@ -314,8 +311,11 @@ void Logger::report_vp_time(time_t when)
 {
   DBUG_ASSERT(m_state == RUNNING);
   
-  if (when)
-    m_op_hist->vp_time= when;
+  m_op_hist.vp_time= when;
+
+  if (output_to(BACKUP_LOG))
+    backup_progress_log_write(m_thd, m_op_hist.backup_id, "backup kernel", 
+                              when, when, 0, 0, 0, "validity point time"); // TODO: internatinalize this  
 }
 
 /** 
@@ -328,125 +328,21 @@ void Logger::report_binlog_pos(const st_
 {
   DBUG_ASSERT(m_state == RUNNING);
   
-  // TODO: write to the log
-  m_op_hist->binlog_pos= pos.pos;
-  if (!m_op_hist->binlog_file && (strlen(pos.file) > 0))
-  {
-    m_op_hist->binlog_file= new char[strlen(pos.file)+1];
-    strcpy(m_op_hist->binlog_file, pos.file);
-  }
-}
-
-/**
-  Update the error number for the row.
-
-  This method saves error number value to the history data.
-
-  @param[IN] THD               thd          The current thread class.
-  @param[IN] int               error_num    New error number.
-*/
-inline
-void Logger::report_error_to_log(THD *thd,
-                                    int error_num)
-{
-  m_op_hist->error_num= error_num;
-}
-
-/**
-  Update the number of objects for the row.
-
-  This method updates the number of objects value in the history data.
-
-  @param[IN] THD               thd          The current thread class.
-  @param[IN[ int               num_objects  New error number.
-*/
-inline
-void Logger::report_num_objects(THD *thd,
-                               int num_objects)
-{
-  m_op_hist->num_objects= num_objects;
-}
-
-/**
-  Update the size for the row.
-
-  This method updates the size value in the history data.
-
-  @param[IN] THD               thd          The current thread class.
-  @param[IN] int               size         New size value.
-*/
-inline
-void Logger::report_size(THD *thd, longlong size)
-{
-  m_op_hist->size= size;
-}
-
-/**
-  Initialize logger for backup or restore operation.
-  
-  A new id for that operation is assigned and stored in @c m_op_hist
-  member.
-  
-  @param[in]  type  type of operation (backup or restore)
-  @param[in]  path  location of the backup image
-  @param[in]  query backup or restore query starting the operation
+  m_op_hist.binlog_pos= pos.pos;
+  m_op_hist.binlog_file= pos.file;
   
-  @returns 0 on success, error code otherwise.
+  // TODO: write binlog position to the logs
+}
 
-  @todo Decide what to do if @c initialize() signals errors.
-  @todo Add code to get the user comment from command.
-*/ 
+/// Report name of a driver used in backup/restore operation.
 inline
-int Logger::init(enum_type type, const LEX_STRING path, const char *query)
+void Logger::report_driver(const char *name)
 {
-  ulonglong backup_id= 0;
-
-  if (m_state != CREATED)
-    return 0;
-
-  m_type= type;
-  m_state= READY;
-
-  m_op_hist= (st_backup_history *)my_malloc(sizeof(st_backup_history), 
-    MYF(MY_WME | MY_ZEROFILL));
-  m_op_hist->user_comment= 0; 
-  m_op_hist->backup_file= 0; 
-  m_op_hist->command= 0; 
-  m_op_hist->engine_name= 0; 
-  m_op_hist->binlog_file= 0; 
-  m_op_hist->process_id= m_thd->id;
-  m_op_hist->state= BUP_STARTING;
-  m_op_hist->operation= BACKUP ? OP_BACKUP : OP_RESTORE;
-  m_op_hist->error_num= 0;
-
-  if (!m_op_hist->backup_file && (path.length > 0))
-  {
-    m_op_hist->backup_file= new char[path.length+1];
-    strcpy(m_op_hist->backup_file, path.str);
-  }
-  if (!m_op_hist->command && (strlen(query) > 0))
-  {
-    m_op_hist->command= new char[strlen(query)+1];
-    strcpy(m_op_hist->command, query);
-  }
-
-  pthread_mutex_lock(&LOCK_backupid);
-  get_next_backup_id();
-  m_op_hist->backup_id= m_next_id;
-  pthread_mutex_unlock(&LOCK_backupid);
-
-  /*
-    Record progress update.
+  /* 
+    We do nothing here, because list of drivers is reported only in the 
+    history log and then it is constructed from the snapshot list stored
+    in the Image_info object (see @c report_stats_pre()).
   */
-  String str;
-  get_state_string(BUP_STARTING, &str);
-  write_progress(m_thd, m_op_hist, "backup kernel", 0, 
-                 0, 0, 0, 0, str.c_ptr());
-
-  if (m_op_hist)
-    m_op_id= m_op_hist->backup_id;
-  BACKUP_BREAKPOINT("bp_starting_state");
-  return 0;
 }
 
 /**
@@ -457,35 +353,19 @@ int Logger::init(enum_type type, const L
   @returns char * a text string for state.
 */
 inline
-void Logger::get_state_string(enum_backup_state state, String *str)
+const char* Logger::get_state_string(enum_backup_state state)
 {
-  str->length(0);
   switch (state) {
-  case BUP_COMPLETE:
-    str->append("complete");
-    break;
-  case BUP_STARTING:
-    str->append("starting");
-    break;
-  case BUP_VALIDITY_POINT:
-    str->append("validity point");
-    break;
-  case BUP_RUNNING:
-    str->append("running");
-    break;
-  case BUP_ERRORS:
-    str->append("error");
-    break;
-  case BUP_CANCEL:
-    str->append("cancel");
-    break;
-  default:
-    str->append("unknown");
-    break;
+  case BUP_COMPLETE: return "complete";
+  case BUP_STARTING: return "starting";
+  case BUP_VALIDITY_POINT: return "validity point";
+  case BUP_RUNNING: return "running";
+  case BUP_ERRORS: return "error";
+  case BUP_CANCEL: return "cancel";
+  default: return "unknown";
   }
 }
 
-
 } // backup namespace
 
 #endif
--- backup/logger.cc.~1~	2008-06-27 11:52:27.000000000 +0200
+++ backup/logger.cc	2008-06-30 09:55:34.202306208 +0200
@@ -1,7 +1,6 @@
 #include "../mysql_priv.h"
 
 #include "image_info.h"
-#include <my_dir.h>
 #include "logger.h"
 
 /** @file
@@ -11,54 +10,30 @@
 
 namespace backup {
 
-pthread_mutex_t LOCK_backupid; ///< mutex for backupid generation
-
-/**
-  Check backup history logs.
-  
-  This method attempts to open the backup logs. It returns
-  an error if either log is not present or cannot be opened.
-
-  @param[in] THD * The current thread.
-
-  @returns Information whether backup logs can be used.
-
-  @retval FALSE  success
-  @retval TRUE  failed to open one of the logs
-*/
-my_bool check_backup_logs(THD *thd)
+int Logger::set_output(uint mask)
 {
-  TABLE_LIST tables;
-  my_bool ret= FALSE;
-
-  DBUG_ENTER("check_backup_logs");
+  int err=0;
+  uint to_set= mask & ~out_set;
 
-  /*
-     ADD TO THIS AREA!!!
-     CHECK TO SEE IF LOG TO TABLE OR LOG TO FILE! 
-     ONLY DO CHECK IF WE ARE LOGGING TO TABLE!
-  */
-
-  /* Check mysql.backup_history */
-  tables.init_one_table("mysql", "backup_history", TL_READ);
-  if (simple_open_n_lock_tables(thd, &tables))
+  if (to_set & ERROR_STACK)
   {
-    ret= TRUE;
-    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
-    DBUG_RETURN(ret);
+    // TODO: hide these behind SI interface.
+    mysql_reset_errors(m_thd, 0);
+    m_thd->no_warnings_for_error= FALSE;
   }
-  close_thread_tables(thd);
 
-  /* Check mysql.backup_progress */
-  tables.init_one_table("mysql", "backup_progress", TL_READ);
-  if (simple_open_n_lock_tables(thd, &tables))
-  {
-    ret= TRUE;
-    sql_print_error(ER(ER_BACKUP_PROGRESS_TABLES));
-    DBUG_RETURN(ret);
-  }
-  close_thread_tables(thd);
-  DBUG_RETURN(ret);
+  if (to_set & BACKUP_LOG)
+    if ((err= check_backup_logs(m_thd)))
+      to_set&= ~BACKUP_LOG;
+  
+  out_set|= to_set;
+
+  return err;
+}
+
+void Logger::dont_output(uint mask)
+{
+  out_set&= ~mask;
 }
 
 /**
@@ -87,38 +62,69 @@ int Logger::write_message(log_level::val
    char buf[ERRMSGSIZE + 30];
    const char *out= msg;
 
-   if (m_state == READY || m_state == RUNNING)
+   /*
+     Prepend "Backup:" or "Restore:" to the message if type of the operation 
+     is known.
+   */
+   if (m_state >= READY)
    {
      my_snprintf(buf, sizeof(buf), "%s: %s", 
                  m_type == BACKUP ? "Backup" : "Restore" , msg);
      out= buf;
    }
-   
+
+   time_t ts= my_time(0); // current timestamp
+
    switch (level) {
+
    case log_level::ERROR:
      if (m_save_errors)
        errors.push_front(new MYSQL_ERROR(::current_thd, error_code,
                                          MYSQL_ERROR::WARN_LEVEL_ERROR, msg));
-     sql_print_error(out);
-     push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
-                         error_code, msg);
-     DBUG_PRINT("backup_log",("[ERROR] %s", out));
-     
-     if (m_state == READY || m_state == RUNNING)
-       report_error_to_log(m_thd, error_code);
+
+     // Store last error code in the history record
+     m_op_hist.error_num= error_code;
+
+     // Write error message to destinations
+
+     if (output_to(DBUG_TRACE))
+       DBUG_PRINT("backup_log",("[ERROR] %s", out));
+
+     if (output_to(ERROR_LOG))
+       sql_print_error(out);
+
+     if (output_to(ERROR_STACK))
+       push_warning_printf(m_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+                           error_code, msg);
      
+     if (output_to(BACKUP_LOG))
+       backup_progress_log_write(m_thd, m_op_hist.backup_id,
+                                 "backup kernel", ts, ts, 0, 0,
+                                 error_code, msg);
+
      return 0;
 
    case log_level::WARNING:
-     sql_print_warning(out);
-     push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                         error_code, msg);
-     DBUG_PRINT("backup_log",("[Warning] %s", out));
+
+     if (output_to(DBUG_TRACE))
+       DBUG_PRINT("backup_log",("[Warning] %s", out));
+
+     if (output_to(ERROR_LOG))
+       sql_print_warning(out);
+
+     if (output_to(ERROR_STACK))
+       push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                           error_code, msg);
      return 0;
 
    case log_level::INFO:
-     sql_print_information(out);
-     DBUG_PRINT("backup_log",("[Info] %s", out));
+
+     if (output_to(DBUG_TRACE))
+       DBUG_PRINT("backup_log",("[Info] %s", out));
+
+     if (output_to(ERROR_LOG))
+       sql_print_information(out);
+
      return 0;
 
    default: return ERROR;
@@ -164,207 +170,30 @@ int Logger::v_write_message(log_level::v
 void Logger::report_stats_pre(const Image_info &info)
 {
   DBUG_ASSERT(m_state == RUNNING);
-  
-  report_num_objects(m_thd, info.table_count());
-}
-
-/**
-  Report statistics from backup/restore catalogue after the operation is
-  completed.
- */ 
-void Logger::report_stats_post(const Image_info &info)
-{
-  DBUG_ASSERT(m_state == RUNNING);
-  
-  report_size(m_thd, info.data_size);
-  write_history(m_thd, m_op_hist);
-}
-
-/**
-  Report name of a driver used in backup/restore operation.
 
-  This method updates the engines information in the history data. This method 
-  appends to the those listed in the history data.
+  m_op_hist.num_objects= info.table_count(); 
 
-  @param[IN] THD               thd          The current thread class.
-  @param[IN] char *            driver_name  The name of the engine to add.
-*/
-void Logger::report_engine(const char *engine_name)
-{
-  String str;    // engines string
-  DBUG_ASSERT(m_state == READY || m_state == RUNNING);
-
-  str.length(0);
-  if (m_op_hist->engine_name &&
-      (strlen(m_op_hist->engine_name) > 0) &&
-      (strlen(engine_name) > 0))
-    str.append(", ");
-  if (strlen(engine_name) > 0)
-    str.append(engine_name);
-  if (str.length() > 0)
+  for (ushort n=0; n < info.snap_count(); ++n)
   {
-    if (m_op_hist->engine_name)
-      delete m_op_hist->engine_name;
-    m_op_hist->engine_name = new char[str.length()+1];
-    strcpy(m_op_hist->engine_name, str.ptr());
+    if (n>0)
+      drivers.append(",");
+    drivers.append(info.m_snap[n]->name());
   }
-}
-
-/**
-  Creates a new progress row in the progress log.
 
-  This method inserts a new row in the backup progress log using the values 
-  passed. This method is used to insert progress information during
-  the backup operation.
-
-  @param[IN] THD               thd          The current thread class.
-  @param[IN] st_backup_history m_op_hist Data for the row.
-  @param[IN] char *            object       The name of the object processed.
-  @param[IN] my_time_t         start        Start datetime.
-  @param[IN] my_time_t         stop         Stop datetime.
-  @param[IN] longlong          size         Size value.
-  @param[IN] longlong          progress     Progress (percent).
-  @param[IN] int               error_num    Error number (should be 0 is success).
-  @param[IN] char *            notes        Misc data from engine
-
-  @retval 0  success
-  @retval 1  failed to find row
-*/
-int Logger::write_progress(THD *thd,
-                           st_backup_history *m_op_hist,
-                           const char *object,
-                           time_t start,
-                           time_t stop,
-                           longlong size,
-                           longlong progress,
-                           int error_num,
-                           const char *notes)
-{
-  int ret= 0;                           // return value
-  DBUG_ENTER("write_progress()");
-
-  ret= backup_progress_log_write(thd, m_op_hist->backup_id, object, start,
-                                 stop, size, progress, error_num, notes);
-  DBUG_RETURN(ret);
+  m_op_hist.engine_name= drivers.ptr();
 }
 
 /**
-  Creates a new history row in the history log.
-
-  This method inserts a new row in the backup history log using the values 
-  passed in the history data.
-  
-  @param[IN] THD               thd          The current thread class.
-  @param[IN] st_backup_history m_op_hist Data for the row.
-
-  @retval 0  success
-  @retval 1  failed to find row
-*/
-int Logger::write_history(THD *thd, st_backup_history *m_op_hist)
+  Report statistics from backup/restore catalogue after the operation is
+  completed.
+ */ 
+void Logger::report_stats_post(const Image_info &info)
 {
-  int ret= 0;                           // return value
-  DBUG_ENTER("write_history()");
+  DBUG_ASSERT(m_state == RUNNING);
 
-  ret= backup_history_log_write(thd, m_op_hist);
-  DBUG_RETURN(ret);
-}
+  m_op_hist.size= info.data_size;  
 
-/**
-  Generate the next backup id.
-  
-  Since autoincrement columns are not permitted in CSV files, an alternative 
-  mechanism has been developed to create monotonically increasing values. When 
-  a server that does not have any logs written (no backup logs), the system 
-  starts at backup_id = 0. This value is stored in a binary file in the data 
-  directory named backup_settings.obx. Each time a new backup_id is needed, 
-  this value is read, incremented, then the file rewritten. This ensures a 
-  monotonically increasing backup_id. If the backup logs exist and the 
-  backup_settings.obx file does not, the system uses the backup log file size 
-  as the starting backup_id. 
-
-  @todo Do we need a mutex to protect this call internally?
-*/
-void Logger::get_next_backup_id()
-{
-  ulonglong id= 0;
-  char buff[FN_REFLEN], *file_path;
-  int error= 0;
-  File file= 0;
-
-  /*
-    This code attempts to generate a new backup_id. The process is:
-    1) Attempt to read from backup settings file.
-    2) If file exists, read value, increment, write new values.
-    3) If file does not exist, create it and set the first backup_id
-       equal to the filesize of the backup history log file.
-
-    Notes:
-    m_next_id == 0 means we need to read the next id from the file (on startup).
-    m_next_id > 0 means use this value
-  */
-  if (!m_next_id)
-  {
-    file_path= make_backup_log_name(buff, BACKUP_SETTINGS_NAME.str, ".obx");
-    MY_STAT state;  
-  
-    file= my_open(file_path, O_RDWR|O_BINARY|O_CREAT, MYF(MY_WME));
-    if (!file)
-      goto err_end; 
-
-    if (my_fstat(file, &state, MYF(0)))
-      goto err;
-    /*
-      Check to see if the file size is 0. If it is, we need to pick a 
-      new backup_id to start from. 
-    */
-    if (state.st_size == 0)
-    {
-      MY_STAT fstate;
-      File hist_file= my_open(sys_var_backup_history_log_path.value,
-        O_RDONLY|O_BINARY, MYF(MY_WME));
-      if (hist_file > 0)
-      {
-         my_fstat(hist_file, &fstate, MYF(0));
-         my_close(hist_file, MYF(MY_WME));
-        id= fstate.st_size + 1;
-      }
-      else
-        id= 1;
-    }
-    // else .... we read the next value in the file!
-    else
-    {
-      my_seek(file, 0, 0, MYF(MY_WME));
-      size_t read_len= my_read(file, (uchar *)&id, sizeof(ulonglong), 
-        MYF(MY_WME|MY_NABP));
-      id++;
-    }
-  }
-  else  // increment the counter
-    id= m_next_id + 1;
-  
-  /* 
-    Write the new value to the file
-  */
-  if ((m_next_id != id) && id)
-  {
-    if (!file)
-    {
-      file_path= make_backup_log_name(buff, BACKUP_SETTINGS_NAME.str, ".obx");
-      file= my_open(file_path, O_RDWR|O_BINARY|O_CREAT, MYF(MY_WME));
-      if (!file)
-        goto err_end; 
-    }
-    my_seek(file, 0, 0, MYF(MY_WME));
-    my_write(file, (uchar *)&id, sizeof(ulonglong), MYF(MY_WME));
-  }
-err:
-  if (file > 0)
-    my_close(file,MYF(MY_WME));
-  
-err_end:		     
-  m_next_id= id;
-  printf("The next id is %lu.\n", id);
+  backup_history_log_write(m_thd, &m_op_hist);
 }
 
 } // backup namespace
--- backup/backup_kernel.h.~1~	2008-06-24 16:29:03.000000000 +0200
+++ backup/backup_kernel.h	2008-06-28 13:50:56.331515312 +0200
@@ -66,7 +66,7 @@ class Backup_restore_ctx: public backup:
   bool is_valid() const;
   ulonglong op_id() const;
 
-  Backup_info*  prepare_for_backup(LEX_STRING location, const char*);
+  Backup_info*  prepare_for_backup(LEX_STRING location, const char*, bool);
   Restore_info* prepare_for_restore(LEX_STRING location, const char*);  
 
   int do_backup();
@@ -79,6 +79,8 @@ class Backup_restore_ctx: public backup:
 
  private:
 
+  ulonglong m_id; ///< Unique id of the operation.
+
   /** Indicates if a backup/restore operation is in progress. */
   static bool is_running;
   static pthread_mutex_t  run_lock; ///< To guard @c is_running flag.
@@ -111,9 +113,11 @@ class Backup_restore_ctx: public backup:
   /** Memory allocator for backup stream library. */
   static backup::Mem_allocator *mem_alloc;
 
-  int prepare(LEX_STRING location);
+  void save_persistent_state();
+  int  load_persistent_state();
+
+  int prepare(enum_type op_type, LEX_STRING location, const char *query);
   void disable_fkey_constraints();
-  int  restore_triggers_and_events();
   
   friend class Backup_info;
   friend class Restore_info;
@@ -134,7 +138,7 @@ bool Backup_restore_ctx::is_valid() cons
 inline
 ulonglong Backup_restore_ctx::op_id() const
 {
-  return m_op_id; // inherited from Logger class
+  return m_id;
 }
 
 /// Disable foreign key constraint checks (needed during restore).
--- backup/kernel.cc.~1~	2008-06-27 11:52:27.000000000 +0200
+++ backup/kernel.cc	2008-06-30 09:42:18.080256256 +0200
@@ -86,7 +86,6 @@
 int backup_init()
 {
   pthread_mutex_init(&Backup_restore_ctx::run_lock, MY_MUTEX_INIT_FAST);
-  pthread_mutex_init(&backup::LOCK_backupid, MY_MUTEX_INIT_FAST);
   return 0;
 }
 
@@ -99,7 +98,6 @@ int backup_init()
 void backup_shutdown()
 {
   pthread_mutex_destroy(&Backup_restore_ctx::run_lock);
-  pthread_mutex_destroy(&backup::LOCK_backupid);
 }
 
 /*
@@ -124,8 +122,6 @@ int
 execute_backup_command(THD *thd, LEX *lex)
 {
   int res= 0;
-  LEX_STRING path;
-  int path_len= 0;
   
   DBUG_ENTER("execute_backup_command");
   DBUG_ASSERT(thd && lex);
@@ -191,7 +187,7 @@ execute_backup_command(THD *thd, LEX *le
 
   case SQLCOM_RESTORE:
   {
-    Restore_info *info= context.prepare_for_restore(path, thd->query);
+    Restore_info *info= context.prepare_for_restore(lex->backup_dir, thd->query);
     
     if (!info || !info->is_valid())
       DBUG_RETURN(send_error(context, ER_BACKUP_RESTORE_PREPARE));
@@ -215,7 +211,6 @@ execute_backup_command(THD *thd, LEX *le
 
   } // switch(lex->sql_command)
 
-  my_free(path.str, MYF(0));  // free memory for path
   if (context.close())
     DBUG_RETURN(send_error(context, ER_BACKUP_CONTEXT_REMOVE));
 
@@ -333,15 +328,100 @@ pthread_mutex_t Backup_restore_ctx::run_
 backup::Mem_allocator *Backup_restore_ctx::mem_alloc= NULL;
 
 
+void Backup_restore_ctx::save_persistent_state()
+{
+  File fd= 0;
+  byte buf[8];
+  ulonglong saved_id= m_id;
+
+  // Store id in endianess agnostic form.
+
+  for (uint i=sizeof(buf); i > 0; --i)
+  {
+    buf[i-1]= saved_id & 0xFF;
+    saved_id >>= 8;
+  }
+
+  // TODO: set the name via options -- need an API for that
+  
+  fd= my_open("backup_settings.obx", O_WRONLY|O_BINARY|O_CREAT, MYF(MY_WME));      
+
+  if (fd < 0)
+    return;
+
+  my_seek(fd, 0, 0, MYF(MY_WME));
+  my_write(fd, buf, sizeof(buf), MYF(MY_WME));
+}
+
+int Backup_restore_ctx::load_persistent_state()
+{
+  int error= 0;
+  File fd= 0;
+  byte buf[8];
+
+  // TODO: set the name via options -- need an API for that
+  // TODO: ensure that my_open() doesn't push error if file not found.
+   
+  fd= my_open("backup_settings.obx", O_RDONLY|O_BINARY, MYF(MY_FFNF));      
+
+  // TODO: write warnings if something goes wrong
+
+  if (!fd)
+  {
+    error= TRUE;
+    goto end;
+  }
+
+  // TODO: add version number to the setting file and check it.
+
+  if (my_read(fd, buf, sizeof(buf), MYF(MY_WME|MY_NABP)) != sizeof(buf))
+  {
+    error= TRUE;
+    goto end;
+  }
+
+  for (uint i=0; i < sizeof(buf); ++i)
+  {
+    m_id = m_id | buf[i];
+    m_id <<= 8;
+  }
+
+end:
+
+  if (fd > 0)
+    my_close(fd, MYF(MY_WME));
+
+  return error;
+}
+
+
 Backup_restore_ctx::Backup_restore_ctx(THD *thd)
  :Logger(thd), m_state(CREATED), m_thd_options(thd->options),
   m_error(0), m_path(NULL), m_remove_loc(FALSE), m_stream(NULL), m_catalog(NULL)
 {
-  /*
-    Check for progress tables.
-  */
-  if (backup::check_backup_logs(thd))
-    m_error= ER_BACKUP_PROGRESS_TABLES;
+  // set-up basic error logging destinations.
+
+  if (Logger::set_output(DBUG_TRACE|ERROR_LOG|ERROR_STACK))
+    m_error= ER_BACKUP_LOGGER_INIT;
+
+  save_errors();  
+
+  // load saved parameters (currently only backup_id)
+
+  if (load_persistent_state())
+  {
+    /*
+      We could not read saved state - perhaps the file was deleted. Thus
+      we need to start from scratch and pick a new id to start from.
+
+      Function generate_backup_id() looks into backup logs and
+      tries to guess an id which was not used yet.
+    */
+    m_id= generate_backup_id();
+  }
+  else
+    ++m_id;
+
 }
 
 Backup_restore_ctx::~Backup_restore_ctx()
@@ -363,18 +443,12 @@ Backup_restore_ctx::~Backup_restore_ctx(
 
   @returns 0 on success, error code otherwise.
  */ 
-int Backup_restore_ctx::prepare(LEX_STRING location)
+int Backup_restore_ctx::prepare(Logger::enum_type op_type, 
+                                LEX_STRING location, const char *query)
 {
   if (m_error)
     return m_error;
   
-  // Prepare error reporting context.
-  
-  mysql_reset_errors(m_thd, 0);
-  m_thd->no_warnings_for_error= FALSE;
-  save_errors();  
-
-
   /*
     Check access for SUPER rights. If user does not have SUPER, fail with error.
   */
@@ -403,12 +477,7 @@ int Backup_restore_ctx::prepare(LEX_STRI
 
   // check if location is valid (we assume it is a file path)
 
-  /*
-    For this error to work correctly, we need to check original
-    file specified by the user rather than the path formed
-    using the backupdir.
-  */
-  bool bad_filename= (m_thd->lex->backup_dir.length == 0);
+  bool bad_filename= (location.length == 0);
   
   /*
     On some systems certain file names are invalid. We use 
@@ -416,13 +485,13 @@ int Backup_restore_ctx::prepare(LEX_STRI
    */ 
 #if defined(__WIN__) || defined(__EMX__)  
 
-  bad_filename = bad_filename || check_if_legal_filename(m_thd->lex->backup_dir.str);
-
+  bad_filename = bad_filename || check_if_legal_filename(location.str);
+  
 #endif
 
   if (bad_filename)
   {
-    fatal_error(ER_BAD_PATH, m_thd->lex->backup_dir.str);
+    fatal_error(ER_BAD_PATH, location.str);
     return m_error;
   }
 
@@ -441,6 +510,25 @@ int Backup_restore_ctx::prepare(LEX_STRI
     return m_error;
   }
 
+  // We are ready for the BACKUP/RESTORE operation which starts now.
+  // Setup logging into the backup log.
+
+  if (Logger::set_id(m_id) || Logger::set_op(op_type, location, query))
+  {
+    fatal_error(ER_BACKUP_LOGGER_INIT);
+    return m_error;
+  }
+
+  if (Logger::set_output(Logger::BACKUP_LOG))
+  {
+    fatal_error(ER_BACKUP_LOGGER_INIT);
+    return m_error;
+  }
+
+  // We save persistent state of the new context which is now fully initialized.
+
+  save_persistent_state();
+
   // Freeze all meta-data. 
 
   if (obs::ddl_blocker_enable(m_thd))
@@ -478,22 +566,17 @@ Backup_restore_ctx::prepare_for_backup(L
   if (m_error)
     return NULL;
   
-  if (Logger::init(BACKUP, location, query))
-  {
-    fatal_error(ER_BACKUP_LOGGER_INIT);
-    return NULL;
-  }
-
   time_t when= my_time(0);
-  report_start(when);
   
   /*
     Do preparations common to backup and restore operations. After call
     to prepare() all meta-data changes are blocked.
    */ 
-  if (prepare(location))
+  if (prepare(BACKUP,location,query))
     return NULL;
 
+  report_start(when);
+
   backup::String path(location);
   
   /*
@@ -510,12 +593,7 @@ Backup_restore_ctx::prepare_for_backup(L
   
   if (!s->open())
   {
-    /*
-      For this error, use the actual value returned instead of the
-      path complimented with backupdir.
-    */
-    THD *thd= ::current_thd;
-    fatal_error(ER_BACKUP_WRITE_LOC, thd->lex->backup_dir.str);
+    fatal_error(ER_BACKUP_WRITE_LOC, path.ptr());
     return NULL;
   }
 
@@ -562,21 +640,16 @@ Backup_restore_ctx::prepare_for_restore(
   if (m_error)
     return NULL;
   
-  if (Logger::init(RESTORE, location, query))
-  {
-    fatal_error(ER_BACKUP_LOGGER_INIT);
-    return NULL;
-  }
-
   time_t when= my_time(0);  
-  report_start(when);
 
   /*
     Do preparations common to backup and restore operations. After this call
     changes of meta-data are blocked.
    */ 
-  if (prepare(location))
+  if (prepare(BACKUP, location, query))
     return NULL;
+
+  report_start(when);
   
   /*
     Open input stream.
@@ -593,12 +666,7 @@ Backup_restore_ctx::prepare_for_restore(
   
   if (!s->open())
   {
-    /*
-      For this error, use the actual value returned instead of the
-      path complimented with backupdir.
-    */
-    THD *thd= ::current_thd;
-    fatal_error(ER_BACKUP_READ_LOC, thd->lex->backup_dir.str);
+    fatal_error(ER_BACKUP_READ_LOC, path.ptr());
     return NULL;
   }
 
@@ -1065,7 +1133,7 @@ int bcat_reset(st_bstream_image_header *
     }
 
     info->m_snap[n]->m_num= n + 1;
-    info->m_ctx.report_engine(info->m_snap[n]->name());
+    info->m_ctx.report_driver(info->m_snap[n]->name());
   }
 
   return BSTREAM_OK;
Thread
bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364, Bug#35230,WL#4296Chuck Bell25 Jun
  • Re: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364,Bug#35230, WL#4296Rafal Somla30 Jun
    • RE: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364, Bug#35230, WL#4296Chuck Bell2 Jul
      • Re: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364,Bug#35230, WL#4296Rafal Somla2 Jul
        • Re: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364,Bug#35230, WL#4296Rafal Somla2 Jul
          • RE: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364, Bug#35230, WL#4296Chuck Bell2 Jul
        • RE: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364, Bug#35230, WL#4296Chuck Bell2 Jul
  • Re: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364,Bug#35230, WL#4296Øystein Grøvlen5 Aug
    • RE: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364, Bug#35230, WL#4296Chuck Bell5 Aug
      • Re: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364,Bug#35230, WL#4296Øystein Grøvlen7 Aug
        • RE: bzr commit into mysql-6.0-backup branch (cbell:2638) Bug#33364, Bug#35230, WL#4296Chuck Bell13 Aug